piano

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: 18 Imported by: 0

Documentation

Index

Constants

View Source
const (
	Normal = iota
	Head
	Tail
	Body // Todo: separate Body and other notes at Skin, Drawer?
)
View Source
const (
	BodyStyleStretch = iota
	BodyStyleAttach
)
View Source
const (
	LeftScratch  = 32
	RightScratch = 64
	ScratchMask  = ^(LeftScratch | RightScratch)
)

LeftScratch and RightScratch are bits for indicating scratch mode. For example, when key count is 40 = 32 + 8, it is 8-key with left scratch.

View Source
const DifficultyDuration int64 = 800

Variables

View Source
var (
	Kool = gosu.Judgment{Flow: 0.01, Acc: 1, Window: 20}
	Cool = gosu.Judgment{Flow: 0.01, Acc: 1, Window: 45}
	Good = gosu.Judgment{Flow: 0.01, Acc: 0.25, Window: 75}
	Bad  = gosu.Judgment{Flow: 0.01, Acc: 0, Window: 110} // Todo: Flow 0.01 -> 0?
	Miss = gosu.Judgment{Flow: -1, Acc: 0, Window: 150}
)
View Source
var (
	FieldDarkness float64 = 0.8
	FieldPosition float64 = screenSizeX * 0.5

	HitPosition float64 = screenSizeY * 0.90 // The bottom y-value of Hint,  not a middle or top.

	NoteHeigth float64 = screenSizeY * 0.05 // Applies to all notes

	ComboPosition    float64 = screenSizeY * 0.40
	JudgmentPosition float64 = screenSizeY * 0.66
)

Todo: Should NoteHeight be separated into NoteHeight, HeadHeight, TailHeight?

View Source
var (
	BodyStyle   int  = BodyStyleStretch
	ReverseBody bool = false

	ScoreScale    float64 = 0.65
	ComboScale    float64 = 0.75
	ComboDigitGap float64 = screenSizeX * -0.0008
	JudgmentScale float64 = 0.33
	HintHeight    float64 = screenSizeY * 0.04
)

Skin-dependent settings. Todo: make SkinScaleSettings struct?

View Source
var FingerMap = map[int][]int{
	0:  {},
	1:  {0},
	2:  {1, 1},
	3:  {1, 0, 1},
	4:  {2, 1, 1, 2},
	5:  {2, 1, 0, 1, 2},
	6:  {3, 2, 1, 1, 2, 3},
	7:  {3, 2, 1, 0, 1, 2, 3},
	8:  {4, 3, 2, 1, 1, 2, 3, 4},
	9:  {4, 3, 2, 1, 0, 1, 2, 3, 4},
	10: {4, 3, 2, 1, 0, 0, 1, 2, 3, 4},
}
View Source
var GeneralSkin struct {
	ComboSprites    [10]draws.Sprite
	JudgmentSprites []draws.Sprite
}
View Source
var Judgments = []gosu.Judgment{Kool, Cool, Good, Bad, Miss}
View Source
var ModePiano4 = gosu.ModeProp{
	Name:           "Piano4",
	Mode:           gosu.ModePiano4,
	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,
}
View Source
var ModePiano7 = gosu.ModeProp{
	Name:           "Piano7",
	Mode:           gosu.ModePiano7,
	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,
}
View Source
var NoteKindsMap = map[int][]NoteKind{
	0:  {},
	1:  {Mid},
	2:  {One, One},
	3:  {One, Mid, One},
	4:  {One, Two, Two, One},
	5:  {One, Two, Mid, Two, One},
	6:  {One, Two, One, One, Two, One},
	7:  {One, Two, One, Mid, One, Two, One},
	8:  {Tip, One, Two, One, One, Two, One, Tip},
	9:  {Tip, One, Two, One, Mid, One, Two, One, Tip},
	10: {Tip, One, Two, One, Mid, Mid, One, Two, One, Tip},
}
View Source
var NoteWidthsMap = map[int][3]float64{
	4:  {0.065, 0.065, 0.065},
	5:  {0.065, 0.065, 0.065},
	6:  {0.065, 0.065, 0.065},
	7:  {0.06, 0.06, 0.06},
	8:  {0.06, 0.06, 0.06},
	9:  {0.06, 0.06, 0.06},
	10: {0.06, 0.06, 0.06},
}
View Source
var Skins = make(map[int]Skin)
View Source
var SpeedScale float64 = 1.0

Functions

func ExposureTime

func ExposureTime(speed float64) float64

1 pixel is 1 millisecond.

func LoadSkin

func LoadSkin()

func NewChartInfo

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

func NewReplayListener

func NewReplayListener(f *osr.Format, keyCount int, 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: add Mods

func SwitchDirection

func SwitchDirection()

func Verdict

func Verdict(noteType int, a input.KeyAction, td int64) gosu.Judgment

Types

type Bar

type Bar struct {
	Time     int64 // For easier debugging.
	Position float64
	Next     *Bar
	Prev     *Bar
}

func NewBars

func NewBars(transPoints []*gosu.TransPoint, duration int64) (bs []*Bar)

type BarDrawer

type BarDrawer struct {
	Cursor   float64
	Farthest *Bar
	Nearest  *Bar
	Sprite   draws.Sprite
}

Bars are fixed. Lane itself moves, all bars move as same amount.

func (BarDrawer) Draw

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

func (*BarDrawer) Update

func (d *BarDrawer) Update(cursor float64)

type Chart

type Chart struct {
	gosu.ChartHeader
	MD5         [16]byte
	KeyCount    int
	TransPoints []*gosu.TransPoint
	Notes       []*Note
	Bars        []*Bar

	Level        float64
	ScoreFactors [3]float64
}

Level, ScoreFactors, MD5 will not exported to file.

func NewChart

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

Position is for calculating note and bar's sprite positions efficiently. Positions of notes and bars at time = 0 are calculated in advance. In every Update(), only current cursor's Position is calculated. Notes and bars are drawn based on the difference between their positions and cursor's.

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

func (Chart) NoteCountString

func (c Chart) NoteCountString() string

func (Chart) NoteCounts

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

type JudgmentDrawer

type JudgmentDrawer struct {
	draws.BaseDrawer
	Sprites  []draws.Sprite
	Judgment gosu.Judgment
}

func NewJudgmentDrawer

func NewJudgmentDrawer() (d JudgmentDrawer)

func (JudgmentDrawer) Draw

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

func (*JudgmentDrawer) Update

func (d *JudgmentDrawer) Update(worst gosu.Judgment)

type KeyDrawer

type KeyDrawer struct {
	MinCountdown   int
	Countdowns     []int
	KeyUpSprites   []draws.Sprite
	KeyDownSprites []draws.Sprite
	// contains filtered or unexported fields
}

KeyDrawer draws KeyDownSprite at least for 30ms, KeyUpSprite otherwise. KeyDrawer uses MinCountdown instead of MaxCountdown.

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 {
	Time     int64
	Duration int64
	Type     int
	Key      int
	Position float64 // Scaled x or y value.
	gosu.Sample
	Marked bool
	Next   *Note
	Prev   *Note // For accessing to Head from Tail.
}

func NewNote

func NewNote(f any, keyCount int) (ns []*Note)

func NewNotes

func NewNotes(f any, keyCount int) (ns []*Note)

Brilliant idea: Make SpeedScale scaled by MainBPM.

func (Note) Weight

func (n Note) Weight() float64

Weight is for Tail's variadic weight based on its length. For example, short long note does not require much strain to release. Todo: fine-tuning with replay data

type NoteDrawer

type NoteDrawer struct {
	Cursor   float64
	Farthest *Note
	Nearest  *Note
	Sprites  [4]draws.Sprite
}

Notes are fixed. Lane itself moves, all notes move same amount.

func (NoteDrawer) Draw

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

Draw from farthest to nearest to make nearer notes priorly exposed.

func (NoteDrawer) DrawLongBody

func (d NoteDrawer) DrawLongBody(screen *ebiten.Image, tail *Note)

DrawLongBody draws scaled, corresponding sub-image of Body sprite.

func (*NoteDrawer) Update

func (d *NoteDrawer) Update(cursor float64)

Farthest and Nearest are borders of displaying notes. All in-screen notes are confirmed to be drawn when drawing from Farthest to Nearest.

type NoteKind

type NoteKind int
const (
	One NoteKind = iota
	Two
	Mid
	Tip = Mid
)

type ScenePlay

type ScenePlay struct {
	Chart *Chart
	gosu.Timer
	gosu.MusicPlayer
	// gosu.EffectPlayer
	gosu.KeyLogger

	*gosu.TransPoint
	SpeedScale float64
	Cursor     float64
	Staged     []*Note
	gosu.Scorer

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

	NoteDrawers    []NoteDrawer
	KeyDrawer      KeyDrawer
	JudgmentDrawer JudgmentDrawer

	ScoreDrawer gosu.ScoreDrawer
	ComboDrawer gosu.NumberDrawer
	MeterDrawer gosu.MeterDrawer
}

ScenePlay: struct, PlayScene: function

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

func (s *ScenePlay) MarkNote(n *Note, j gosu.Judgment)

Extra primitive in Piano mode is a count of Kools. Todo: no getting Flow when hands off the long note

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 (s ScenePlay) Time() int64 { return s.Timer.Time() }

func (*ScenePlay) Update

func (s *ScenePlay) Update() any

Todo: apply other values of TransPoint (Volume has finished so far) Todo: keep playing music when making SceneResult

func (*ScenePlay) UpdateCursor

func (s *ScenePlay) UpdateCursor()

Supposes one current TransPoint can increment cursor precisely.

func (*ScenePlay) UpdateTransPoint

func (s *ScenePlay) UpdateTransPoint()

type Skin

type Skin struct {
	ScoreSprites [10]draws.Sprite
	SignSprites  [3]draws.Sprite

	ComboSprites    [10]draws.Sprite
	JudgmentSprites []draws.Sprite // Todo: slice -> array?

	KeyUpSprites   []draws.Sprite
	KeyDownSprites []draws.Sprite
	NoteSprites    []draws.Sprite
	HeadSprites    []draws.Sprite
	TailSprites    []draws.Sprite
	BodySprites    []draws.Sprite

	FieldSprite draws.Sprite
	HintSprite  draws.Sprite
	BarSprite   draws.Sprite // Seperator of each bar (aka measure)
}

Todo: should each skin has own skin settings? Order of fields in Skin is focused on readability.

type StageDrawer

type StageDrawer struct {
	FieldSprite draws.Sprite
	HintSprite  draws.Sprite
}

func (StageDrawer) Draw

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

Todo: might add some effect on StageDrawer

Jump to

Keyboard shortcuts

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