drum

package
v0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2023 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MaxScaledBPM = 280 // 256
	MinScaledBPM = 60  // 128
)
View Source
const (
	DotReady = iota
	DotHit
	DotMiss
)
View Source
const (
	Normal = iota
	Roll
	Shake
)

Drum note has 3 components: Color, Size, Type(Note, Roll, Shake). Piano note has 2 components: Key, Type(Note, Head, Tail).

View Source
const (
	ColorNone = iota - 1
	Red       // aka Don.
	Blue      // aka Kat.
	Yellow    // For Roll.
	Purple    // For Shake.
)
View Source
const (
	SizeNone = iota - 1
	Regular
	Big
)
View Source
const (
	Cools = iota // Stands for Cool counts.
	Goods
	Misses
	CoolPartials
	GoodPartials
	TickHits
	TickDrops
)
View Source
const (
	TPS         = mode.TPS
	ScreenSizeX = mode.ScreenSizeX
	ScreenSizeY = mode.ScreenSizeY
)
View Source
const (
	Idle = iota
	High
)
View Source
const (
	DancerIdle = iota
	DancerYes
	DancerNo
	DancerHigh
)
View Source
const MaxBigHitDuration = 25

When hit big notes only with one press, the note gives half the score only. For example, when hit a Big note by one press with Good, it will gives 0.25 * 0.5 = 0.125. No Flow decrease for hitting Big note by one press. When one side of judgment is Cool, Good on the other hand, overall judgment of Big note goes Good. In other word, to get Cool at Big note, you have to hit it Cool with both sides. Todo: judge for Big note when judgment goes different depending on selecting 2 key actions

View Source
const Mode = 1 // ModeDrum

Variables

View Source
var (
	// TickDensity  float64 = 4
	DotDensity   float64 = 4 // Infers how many dots per beat in Roll note.
	ShakeDensity float64 = 3 // Infers how many shakes per beat in Shake note.
)
View Source
var (
	DotColorReady = color.NRGBA{255, 255, 255, 255} // White.
	DotColorHit   = color.NRGBA{255, 255, 0, 0}     // Transparent.
	DotColorMiss  = color.NRGBA{255, 0, 0, 255}     // Red.
)
View Source
var (
	Cool               = mode.Judgment{Flow: 0.01, Acc: 1, Window: 25}
	Good               = mode.Judgment{Flow: 0.01, Acc: 0.25, Window: 60}
	Miss               = mode.Judgment{Flow: -1, Acc: 0, Window: 100}
	DotHitWindow int64 = 35 // 25
)

Todo: let users use custom windows Todo: need to find best value for DotHitWindow

View Source
var (
	UserSettings = NewSettings()
	S            = &UserSettings
)
View Source
var (
	ColorRed    = color.NRGBA{235, 69, 44, 255}
	ColorBlue   = color.NRGBA{68, 141, 171, 255}
	ColorYellow = color.NRGBA{230, 170, 0, 255} // 252, 83, 6
	ColorPurple = color.NRGBA{150, 100, 200, 255}
)
View Source
var (
	DefaultSkin = &Skin{}
	UserSkin    = &Skin{}
)
View Source
var DefaultSampleNames = [2][2]string{{"red", "red-big"}, {"blue", "blue-big"}}
View Source
var JudgmentCountKinds = []string{
	"Cools", "Goods", "Misses",
	"CoolPartials", "GoodPartials",
	"TickHits", "TickDrops",
}
View Source
var Judgments = []mode.Judgment{Cool, Good, Miss}

Functions

func ExposureTime

func ExposureTime(speed float64) float64

func ExtraScoreRate

func ExtraScoreRate(nws, ews float64) float64

If a chart has not enough Shake and Roll, max score of Extra will shrink. Margin will be distributed to Flow and Acc score by 7:3.

func IsColorHit

func IsColorHit(actions [2]int, color int) bool

func IsOtherColorHit

func IsOtherColorHit(actions [2]int, color int) bool

func NewShakeSprites added in v0.3.1

func NewShakeSprites(note draws.Image) (sprites [2]draws.Sprite)

func ScaledBPM

func ScaledBPM(bpm float64) float64

It is proved that all BPMs are set into [min, max) by v*2 or v/2 if 2 * min >= max.

func VerdictDot

func VerdictDot(dot *Dot, actions [2]int, td int64) (marked int)

func VerdictNote

func VerdictNote(n *Note, actions [2]int, td int64) (j mode.Judgment, big bool)

func VerdictShake

func VerdictShake(shake *Note, actions [2]int, waitingColor int) (nextColor int)

Types

type Bar

type Bar struct {
	Floater
	Next *Bar
	Prev *Bar
}

func NewBars

func NewBars(transPoints []*mode.Dynamic, duration int64) (bs []*Bar)

type BarDrawer

type BarDrawer struct {
	Time   int64
	Bars   []*Bar
	Sprite draws.Sprite
}

Floating-type lane drawer.

func (BarDrawer) Draw

func (d BarDrawer) Draw(dst draws.Image)

func (*BarDrawer) Update

func (d *BarDrawer) Update(time int64)

type Chart

type Chart struct {
	mode.ChartHeader
	MD5      [16]byte
	Dynamics []*mode.Dynamic
	Notes    []*Note
	Rolls    []*Note
	Shakes   []*Note
	Dots     []*Dot // Ticks in a Roll note.
	Bars     []*Bar

	Level        float64
	ScoreFactors [3]float64
}

func LoadChart added in v0.6.0

func LoadChart(fsys fs.FS, name string) (c *Chart, err error)

LoadChart takes file path as input for starting with parsing. Chart data should not rely on the ChartInfo; users may have modified it.

func (Chart) BPMs

func (c Chart) BPMs() (main, min, max float64)

func (Chart) Difficulties

func (c Chart) Difficulties() []float64

Mods may change the duration of chart. Todo: implement actual calculating chart difficulties

func (Chart) Duration

func (c Chart) Duration() (last int64)

func (Chart) NoteCounts

func (c Chart) NoteCounts() (vs []int)

type DancerDrawer

type DancerDrawer struct {
	draws.Timer
	Time        int64
	Dancer      [4]draws.Animation
	Mode        int
	ModeEndTime int64 // It extends when notes are continuously missed.
}

func (DancerDrawer) Draw

func (d DancerDrawer) Draw(dst draws.Image)

func (*DancerDrawer) Update

func (d *DancerDrawer) Update(time int64, bpm float64, combo int, miss, hit, high bool)

type Dot

type Dot struct {
	Floater

	Next *Dot
	Prev *Dot
	// contains filtered or unexported fields
}

No consider situations that multiple rolls are overlapped.

func NewDots

func NewDots(rolls []*Note) (ds []*Dot)

func (Dot) Weight

func (d Dot) Weight() float64

type Floater

type Floater struct {
	Time  int64
	Speed float64
}

func (Floater) Position

func (f Floater) Position(time int64) float64

type JudgmentDrawer

type JudgmentDrawer struct {
	draws.Timer
	Animations [3][2]draws.Animation
	// contains filtered or unexported fields
}

func (JudgmentDrawer) Draw

func (d JudgmentDrawer) Draw(dst draws.Image)

func (*JudgmentDrawer) Update

func (d *JudgmentDrawer) Update(j mode.Judgment, big bool)

type KeyDrawer

type KeyDrawer struct {
	MaxCountdown int
	Field        draws.Sprite
	Keys         [4]draws.Sprite
	// contains filtered or unexported fields
}

func (KeyDrawer) Draw

func (d KeyDrawer) Draw(dst draws.Image)

func (*KeyDrawer) Update

func (d *KeyDrawer) Update(lastPressed, pressed []bool)

type Note

type Note struct {
	Floater
	Type     int
	Color    int
	Size     int
	Duration int64

	Tick int // The number of ticks in Roll or Shake.
	mode.Sample

	HitTick int // The number of ticks being hit.
	Next    *Note
	Prev    *Note
	// contains filtered or unexported fields
}

func NewNote

func NewNote(f any) (n *Note)

func NewNotes

func NewNotes(f any) (notes, rolls, shakes []*Note)

func (Note) Weight

func (n Note) Weight() float64

type NoteDrawer added in v0.2.3

type NoteDrawer struct {
	draws.Timer
	Time    int64
	Notes   []*Note
	Rolls   []*Note
	Shakes  []*Note
	Note    [4][2]draws.Sprite
	Overlay [2]draws.Animation
}

func (NoteDrawer) Draw added in v0.2.3

func (d NoteDrawer) Draw(dst draws.Image)

func (*NoteDrawer) Update added in v0.2.3

func (d *NoteDrawer) Update(time int64, bpm float64)

type RollDrawer

type RollDrawer struct {
	Time      int64
	Rolls     []*Note
	Dots      []*Dot
	Head      [2]draws.Sprite
	Tail      [2]draws.Sprite
	Body      [2]draws.Sprite
	DotSprite draws.Sprite
}

func (RollDrawer) Draw

func (d RollDrawer) Draw(dst draws.Image)

func (*RollDrawer) Update

func (d *RollDrawer) Update(time int64)

type ScenePlay

type ScenePlay struct {
	Chart *Chart
	mode.Timer
	audios.MusicPlayer
	input.KeyLogger
	KeyActions [2]int

	*mode.Dynamic

	StagedNote         *Note
	StagedDot          *Dot
	StagedShake        *Note
	LastHitTimes       [4]int64      // For judging big note.
	StagedJudgment     mode.Judgment // For judging big note.
	StagedJudgmentTime int64
	ShakeWaitingColor  int
	mode.Scorer

	DrumSound  [2][2][]byte
	Background mode.BackgroundDrawer
	Stage      StageDrawer
	Bar        BarDrawer
	Judgment   JudgmentDrawer
	Shake      ShakeDrawer
	Roll       RollDrawer
	Note       NoteDrawer
	Key        KeyDrawer
	Dancer     DancerDrawer
	Score      mode.ScoreDrawer
	Combo      mode.ComboDrawer
	Meter      mode.MeterDrawer
	// contains filtered or unexported fields
}

Todo: support custom hitsound?

func NewScenePlay

func NewScenePlay(fsys fs.FS, cname string, mods interface{}, rf *osr.Format) (s *ScenePlay, err error)

Todo: actual auto replay generator for gimmick charts Todo: support mods: show Piano's ScenePlay during Drum's ScenePlay

func (ScenePlay) DebugPrint

func (s ScenePlay) DebugPrint(screen draws.Image)

func (ScenePlay) Draw

func (s ScenePlay) Draw(screen draws.Image)

func (ScenePlay) Finish added in v0.3.1

func (s ScenePlay) Finish() any

func (*ScenePlay) MarkDot

func (s *ScenePlay) MarkDot(dot *Dot, marked int)

Roll affects only at Extra score.

func (*ScenePlay) MarkNote

func (s *ScenePlay) MarkNote(n *Note, j mode.Judgment, big bool)

func (*ScenePlay) MarkShake

func (s *ScenePlay) MarkShake(shake *Note, flush bool)

Shake affects only at Extra score.

func (*ScenePlay) PlayPause added in v0.3.1

func (s *ScenePlay) PlayPause()

func (*ScenePlay) SetMaxScores

func (s *ScenePlay) SetMaxScores()

func (*ScenePlay) SetSpeed

func (s *ScenePlay) SetSpeed()

Farther note has larger position. Tail's Position is always larger than Head's. Need to re-calculate positions when Speed has changed.

func (ScenePlay) Speed

func (s ScenePlay) Speed() float64

func (*ScenePlay) Update

func (s *ScenePlay) Update() any

func (*ScenePlay) UpdateDynamic added in v0.6.0

func (s *ScenePlay) UpdateDynamic()

func (*ScenePlay) UpdateKeyActions

func (s *ScenePlay) UpdateKeyActions()

type Settings added in v0.3.1

type Settings struct {
	MusicVolume float64

	// Logic settings
	KeySettings map[int][]string
	SpeedScale  float64
	HitPosition float64

	Reverse bool

	// Skin-independent settings
	FieldOpacity  float64
	FieldPosition float64
	FieldHeight   float64

	DancerPositionX float64
	DancerPositionY float64

	// Skin-dependent settings
	FieldInnerHeight float64
	JudgmentScale    float64
	DotScale         float64
	ShakeScale       float64
	DancerScale      float64
	ComboScale       float64
	ComboDigitGap    float64
	// contains filtered or unexported fields
}

func NewSettings added in v0.3.1

func NewSettings() Settings

func (*Settings) Load added in v0.3.1

func (s *Settings) Load(src Settings)

type ShakeDrawer

type ShakeDrawer struct {
	draws.Timer
	Time   int64
	Staged *Note
	Shake  [2]draws.Sprite
}

func (ShakeDrawer) Draw

func (d ShakeDrawer) Draw(dst draws.Image)

func (*ShakeDrawer) Update

func (d *ShakeDrawer) Update(time int64, staged *Note)

type Skin

type Skin struct {
	Field [2]draws.Sprite
	Hint  [2]draws.Sprite
	Bar   draws.Sprite

	// [2] at last element stands for a size.
	DrumSound [2][2][]byte // color, size
	Judgment  [3][2]draws.Animation
	Note      [4][2]draws.Sprite
	Head      [2]draws.Sprite
	Tail      [2]draws.Sprite
	Body      [2]draws.Sprite
	Dot       draws.Sprite
	Shake     [2]draws.Sprite
	Overlay   [2]draws.Animation

	Key      [4]draws.Sprite
	KeyField draws.Sprite
	Dancer   [4]draws.Animation

	Combo [10]draws.Sprite
	// contains filtered or unexported fields
}

Todo: resolve ambiguity between image and derived sprites Order of fields of Skin is roughly consistent with drawing order.

func (*Skin) Load added in v0.3.1

func (skin *Skin) Load(fsys fs.FS)

Calling fillBlank() right after returning Load won't apply User settings.

type StageDrawer

type StageDrawer struct {
	draws.Timer
	Highlight bool
	Field     [2]draws.Sprite
	Hint      [2]draws.Sprite
}

func (StageDrawer) Draw

func (d StageDrawer) Draw(dst draws.Image)

func (*StageDrawer) Update

func (d *StageDrawer) Update(highlight bool)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL