drum

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2022 License: Apache-2.0 Imports: 20 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 (
	LeftBlue = iota
	LeftRed
	RightRed
	RightBlue
)
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 PositionMargin = 100

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               = gosu.Judgment{Flow: 0.01, Acc: 1, Window: 25}
	Good               = gosu.Judgment{Flow: 0.01, Acc: 0.25, Window: 60}
	Miss               = gosu.Judgment{Flow: -1, Acc: 0, Window: 100}
	DotHitWindow int64 = 25
)

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

View Source
var (
	FieldDarkness float64 = 0.7
	FieldPosition float64 = screenSizeY * 0.4115
	FieldHeight   float64 = screenSizeY * 0.26

	HitPosition float64 = screenSizeX * 0.1875

	DancerPositionX float64 = screenSizeX * 0.1
	DancerPositionY float64 = screenSizeY * 0.175
)

Default values are derived from osu!taiko. Todo: generalize Dancer for all modes?

View Source
var (
	FieldInnerHeight float64 = FieldHeight * 0.95
	JudgmentScale    float64 = 0.75 // 1.25
	DotScale         float64 = 0.5
	ShakeScale       float64 = 1
	DancerScale      float64 = 0.75 // 0.6
	ComboScale       float64 = 0.75 // 1.25
	ComboDigitGap    float64 = screenSizeX * -0.001
)

Skin-dependent settings.

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 DefaultSampleNames = [2][2]string{
	{"red-regular", "red-big"},
	{"blue-regular", "blue-big"},
}
View Source
var JudgmentCountKinds = []string{
	"Cools", "Goods", "Misses",
	"CoolPartials", "GoodPartials",
	"TickHits", "TickDrops",
}
View Source
var Judgments = []gosu.Judgment{Cool, Good, Miss}
View Source
var KeySettings = map[int][]input.Key{
	4: {input.KeyD, input.KeyF, input.KeyJ, input.KeyK},
}

var KeySettings = [4]input.Key{input.KeyD, input.KeyF, input.KeyJ, input.KeyK}

View Source
var ModeDrum = gosu.ModeProp{
	Name:           "Drum",
	Mode:           gosu.ModeDrum,
	ChartInfos:     make([]gosu.ChartInfo, 0),
	Results:        make(map[[16]byte]gosu.Result),
	LastUpdateTime: time.Time{},

	LoadSkin:   LoadSkin,
	SpeedScale: &SpeedScale,

	NewChartInfo: NewChartInfo,
	NewScenePlay: NewScenePlay,
	ExposureTime: ExposureTime,
	KeySettings:  KeySettings,
}

var SpeedKeyHandler = gosu.NewSpeedKeyHandler(&SpeedScale)

View Source
var SpeedScale float64 = 1.0

Functions

func ExposureTime

func ExposureTime(speedScale float64) float64

1 pixel is 1 millisecond. Todo: Separate NoteHeight / 2 at piano mode

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 LoadSkin

func LoadSkin()

Todo: embed default skins to code for preventing panic when files are missing

func NewChartInfo

func NewChartInfo(cpath string) (info gosu.ChartInfo, err error)

func NewReplayListener

func NewReplayListener(f *osr.Format, timer *gosu.Timer) func() []bool

ReplayListener supposes closure function is called every 1 ms. ReplayListener supposes the first the time of replay data is 0ms and no any inputs. Todo: Make sure to ReplayListener time is independent of Game's update tick

func NewScenePlay

func NewScenePlay(cpath string, rf *osr.Format) (scene gosu.Scene, err error)

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

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 SwitchDirection

func SwitchDirection()

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 gosu.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 []*gosu.TransPoint, 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(screen *ebiten.Image)

func (*BarDrawer) Update

func (d *BarDrawer) Update(time int64)

type Chart

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

	Level        float64
	ScoreFactors [3]float64
}

func NewChart

func NewChart(cpath string) (c *Chart, err error)

NewChart 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 {
	AnimationDrawers [4]draws.AnimationDrawer
	AnimationEndTime int64 // For Yes and No.
	Mode             int
}

func (DancerDrawer) AnimationFinish

func (d DancerDrawer) AnimationFinish() bool

AnimationFinish infers if Dancer is ready to change its mode.

func (DancerDrawer) Draw

func (d DancerDrawer) Draw(screen *ebiten.Image)

func (*DancerDrawer) Update

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

type Dot

type Dot struct {
	Floater
	// Showtime int64 // Dot will appear at Showtime.
	Marked int
	Next   *Dot
	Prev   *Dot
}

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.BaseDrawer
	Sprites [2][3]draws.Sprite
	// contains filtered or unexported fields
}

func (JudgmentDrawer) Draw

func (d JudgmentDrawer) Draw(screen *ebiten.Image)

func (*JudgmentDrawer) Update

func (d *JudgmentDrawer) Update(j gosu.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(screen *ebiten.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.
	gosu.Sample

	Marked  bool
	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 NoteDarwer

type NoteDarwer struct {
	Time           int64
	Notes          []*Note
	Rolls          []*Note
	Shakes         []*Note
	NoteSprites    [2][4]draws.Sprite
	OverlayDrawers [2]draws.AnimationDrawer
}

func (NoteDarwer) Draw

func (d NoteDarwer) Draw(screen *ebiten.Image)

func (*NoteDarwer) Update

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

type RollDrawer

type RollDrawer struct {
	Time        int64
	Rolls       []*Note
	Dots        []*Dot
	HeadSprites [2]draws.Sprite
	BodySprites [2]draws.Sprite
	TailSprites [2]draws.Sprite
	DotSprite   draws.Sprite
}

func (RollDrawer) Draw

func (d RollDrawer) Draw(screen *ebiten.Image)

func (*RollDrawer) Update

func (d *RollDrawer) Update(time int64)

type ScenePlay

type ScenePlay struct {
	Chart *Chart
	gosu.Timer
	// time int64 // Just a cache.
	gosu.MusicPlayer
	SoundEffectBytes [2][2][]byte // No custom hitsound at Drum mode.
	gosu.KeyLogger
	KeyActions [2]int

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

	// Skin may be applied some custom settings: on/off some sprites
	Skin
	BackgroundDrawer gosu.BackgroundDrawer
	StageDrawer      StageDrawer
	BarDrawer        BarDrawer
	JudgmentDrawer   JudgmentDrawer

	ShakeDrawer ShakeDrawer
	RollDrawer  RollDrawer
	NoteDrawer  NoteDarwer

	KeyDrawer    KeyDrawer
	DancerDrawer DancerDrawer
	ScoreDrawer  gosu.ScoreDrawer
	ComboDrawer  gosu.NumberDrawer
	MeterDrawer  gosu.MeterDrawer
}

func (ScenePlay) CurrentSpeed

func (s ScenePlay) CurrentSpeed() float64

func (ScenePlay) DebugPrint

func (s ScenePlay) DebugPrint(screen *ebiten.Image)

func (ScenePlay) Draw

func (s ScenePlay) Draw(screen *ebiten.Image)

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 gosu.Judgment, big bool)

func (*ScenePlay) MarkShake

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

Shake affects only at Extra score.

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()

func (*ScenePlay) Update

func (s *ScenePlay) Update() any

func (*ScenePlay) UpdateKeyActions

func (s *ScenePlay) UpdateKeyActions()

func (*ScenePlay) UpdateTransPoint

func (s *ScenePlay) UpdateTransPoint()

type ShakeDrawer

type ShakeDrawer struct {
	Time         int64
	Staged       *Note
	BorderSprite draws.Sprite
	ShakeSprite  draws.Sprite
}

func (ShakeDrawer) Draw

func (d ShakeDrawer) Draw(screen *ebiten.Image)

func (*ShakeDrawer) Update

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

type Skin

type Skin struct {
	FieldSprite     draws.Sprite
	HintSprites     [2]draws.Sprite
	BarSprite       draws.Sprite
	JudgmentSprites [2][3]draws.Sprite

	NoteSprites       [2][4]draws.Sprite
	HeadSprites       [2]draws.Sprite
	TailSprites       [2]draws.Sprite
	OverlaySprites    [2][]draws.Sprite
	BodySprites       [2]draws.Sprite
	DotSprite         draws.Sprite
	ShakeBorderSprite draws.Sprite
	ShakeSprite       draws.Sprite

	KeySprites     [4]draws.Sprite
	KeyFieldSprite draws.Sprite
	DancerSprites  [4][]draws.Sprite
	ScoreSprites   [10]draws.Sprite
	ComboSprites   [10]draws.Sprite
}

Order of fields of Skin is roughly consistent with drawing order. https://osu.ppy.sh/wiki/en/Skinning/osu%21taiko

var DefaultSkin Skin

type StageDrawer

type StageDrawer struct {
	Hightlight  bool
	FieldSprite draws.Sprite
	HintSprites [2]draws.Sprite
}

func (StageDrawer) Draw

func (d StageDrawer) Draw(screen *ebiten.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