piano

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Nov 28, 2022 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Index

Constants

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 (
	Normal = iota
	Head
	Tail
	Body // Todo: separate Body and other notes at Skin, Drawer?
)
View Source
const (
	TPS         = mode.TPS
	ScreenSizeX = mode.ScreenSizeX
	ScreenSizeY = mode.ScreenSizeY
)
View Source
const (
	BodyStyleStretch int = iota
	BodyStyleAttach
)

Generic function seems not allow to pass named type.

View Source
const DifficultyDuration int64 = 800
View Source
const Mode = 0 // ModePiano

Variables

View Source
var (
	Kool = mode.Judgment{Flow: 0.01, Acc: 1, Window: 20}
	Cool = mode.Judgment{Flow: 0.01, Acc: 1, Window: 45}
	Good = mode.Judgment{Flow: 0.01, Acc: 0.25, Window: 75}
	Bad  = mode.Judgment{Flow: 0.01, Acc: 0, Window: 110} // Todo: Flow 0.01 -> 0?
	Miss = mode.Judgment{Flow: -1, Acc: 0, Window: 150}
)
View Source
var (
	UserSettings = NewSettings()
	S            = &UserSettings
)
View Source
var (
	DefaultSkins = &Skins{Skins: make(map[int]*Skin)}
	UserSkins    = &Skins{Skins: make(map[int]*Skin)}
)
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 Judgments = []mode.Judgment{Kool, Cool, Good, Bad, Miss}
View Source
var KeyTypes = map[int][]KeyType{
	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},
}

Functions

func ExposureTime

func ExposureTime(speed float64) float64

1 pixel is 1 millisecond.

func NewReplayListener

func NewReplayListener(f *osr.Format, keyCount int, timer *mode.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 Verdict

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

Types

type Bar

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

func NewBars

func NewBars(transPoints []*mode.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(dst draws.Image)

func (*BarDrawer) Update

func (d *BarDrawer) Update(cursor float64)

type Chart

type Chart struct {
	mode.ChartHeader
	MD5  [16]byte
	Mods interface{}

	KeyCount    int // The number of physical keys.
	KeyMode     int // Scratch mode value may add after applying mods.
	TransPoints []*mode.TransPoint
	Notes       []*Note
	Bars        []*Bar

	Level        float64
	ScoreFactors [3]float64
}

Level, ScoreFactors, MD5 will not exported to file.

func NewChart

func NewChart(fsys fs.FS, name 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 (c Chart) NoteCounts() (vs []int) {
	vs = make([]int, 2)
	for _, n := range c.Notes {
		if n.Type == Tail {
			continue
		}
		vs[n.Type]++
	}
	return
}

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

type FieldDrawer added in v0.2.4

type FieldDrawer struct {
	Sprite draws.Sprite
}

func (FieldDrawer) Draw added in v0.2.4

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

type HintDrawer added in v0.2.4

type HintDrawer struct {
	Sprite draws.Sprite
}

func (HintDrawer) Draw added in v0.2.4

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

type HitLightingDrawer added in v0.2.4

type HitLightingDrawer struct {
	draws.Timer
	Sprites draws.Animation
}

func (HitLightingDrawer) Draw added in v0.2.4

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

func (*HitLightingDrawer) Update added in v0.2.4

func (d *HitLightingDrawer) Update(hit bool)

HitLightingDrawer draws when Normal is Hit or Tail is Release.

type HoldLightingDrawer added in v0.2.4

type HoldLightingDrawer struct {
	draws.Timer
	Sprites draws.Animation
	// contains filtered or unexported fields
}

func (HoldLightingDrawer) Draw added in v0.2.4

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

func (*HoldLightingDrawer) Update added in v0.2.4

func (d *HoldLightingDrawer) Update(pressed bool)

type JudgmentDrawer

type JudgmentDrawer struct {
	draws.Timer
	Sprites  []draws.Animation
	Judgment mode.Judgment
}

func NewJudgmentDrawer

func NewJudgmentDrawer(sprites []draws.Animation) (d JudgmentDrawer)

func (JudgmentDrawer) Draw

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

func (*JudgmentDrawer) Update

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

type KeyDrawer

type KeyDrawer struct {
	draws.Timer
	Sprites [2]draws.Sprite
	// contains filtered or unexported fields
}

func (KeyDrawer) Draw

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

KeyDrawer draws for a while even when pressed off very shortly.

func (*KeyDrawer) Update

func (d *KeyDrawer) Update(pressed bool)

type KeyLightingDrawer added in v0.2.4

type KeyLightingDrawer struct {
	draws.Timer
	Sprite draws.Sprite
	Color  color.NRGBA
	// contains filtered or unexported fields
}

func (KeyLightingDrawer) Draw added in v0.2.4

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

KeyLightingDrawer draws for a while even when pressed off very shortly.

func (*KeyLightingDrawer) Update added in v0.2.4

func (d *KeyLightingDrawer) Update(pressed bool)

type KeyType added in v0.3.1

type KeyType int
const (
	One KeyType = iota
	Two
	Mid
	Tip // = Mid
)

type Note

type Note struct {
	Time     int64
	Duration int64
	Type     int
	Key      int
	Position float64 // Scaled x or y value.
	mode.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 {
	draws.Timer
	Cursor   float64
	Farthest *Note
	Nearest  *Note
	Sprites  [4]draws.Animation
	// contains filtered or unexported fields
}

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

func (NoteDrawer) Draw

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

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

func (NoteDrawer) DrawBody added in v0.2.3

func (d NoteDrawer) DrawBody(dst draws.Image, tail *Note)

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

func (*NoteDrawer) Update

func (d *NoteDrawer) Update(cursor float64, holding bool)

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

type ScenePlay

type ScenePlay struct {
	Chart *Chart
	mode.Timer
	audios.MusicPlayer
	audios.SoundPlayer
	input.KeyLogger

	*mode.TransPoint

	Cursor float64
	Staged []*Note
	mode.Scorer

	Background   mode.BackgroundDrawer
	Field        FieldDrawer
	Bar          BarDrawer
	Note         []NoteDrawer
	Keys         []KeyDrawer
	KeyLighting  []KeyLightingDrawer
	Hint         HintDrawer
	HitLighting  []HitLightingDrawer
	HoldLighting []HoldLightingDrawer
	Judgment     JudgmentDrawer
	Score        mode.ScoreDrawer
	Combo        mode.ComboDrawer
	Meter        mode.MeterDrawer
	// contains filtered or unexported fields
}

ScenePlay: struct, PlayScene: function The skin may be applied some custom settings: on/off some sprites

func NewScenePlay

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

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

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

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

func (*ScenePlay) PlayPause added in v0.3.1

func (s *ScenePlay) PlayPause()

func (ScenePlay) PlaySample added in v0.3.1

func (s ScenePlay) PlaySample(n *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() float64

func (*ScenePlay) Update

func (s *ScenePlay) Update() any

func (*ScenePlay) UpdateCursor

func (s *ScenePlay) UpdateCursor()

func (*ScenePlay) UpdateTransPoint

func (s *ScenePlay) UpdateTransPoint()

type Settings added in v0.3.1

type Settings struct {
	VolumeMusic float64

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

	TailExtraTime float64
	ReverseBody   bool

	// Skin-independent settings
	NoteWidths       map[int][4]float64 // Fourth is a Scratch note.
	NoteHeigth       float64            // Applies to all types of notes.
	BodyStyle        int
	FieldPosition    float64
	ComboPosition    float64
	JudgmentPosition float64
	ScratchColor     [4]uint8

	FieldOpaque       float64
	KeyLightingColors [4][4]uint8

	HitLightingOpaque  float64
	HoldLightingOpaque float64

	// Skin-dependent settings
	ComboScale    float64
	ComboDigitGap float64
	JudgmentScale float64
	HintHeight    float64
	LightingScale float64
	// contains filtered or unexported fields
}

func NewSettings added in v0.3.1

func NewSettings() Settings

Fields which types are map should be explicitly make new map.

func (*Settings) Load added in v0.3.1

func (s *Settings) Load(src Settings)

type Skin

type Skin struct {
	// Independent of key number
	DefaultBackground draws.Sprite
	Score             [13]draws.Sprite // number + sign(. , %)
	Combo             [10]draws.Sprite // number only
	Judgment          [5]draws.Animation
	// Dependent of key number
	Bar          draws.Sprite
	Hint         draws.Sprite
	Field        draws.Sprite
	Note         [][4]draws.Animation
	Key          [][2]draws.Sprite
	KeyLighting  []draws.Sprite
	HitLighting  []draws.Animation
	HoldLighting []draws.Animation
}

type Skins

type Skins struct {
	Skins map[int]*Skin // Key is KeyMode: scratch mode + key count

	Combo    [10]draws.Image // number only
	Judgment [5][]draws.Image
	// Bar: generated per skin
	Hint draws.Image

	Note         [4][4][]draws.Image // Key type, note type
	Key          [2]draws.Image
	KeyLighting  draws.Image
	HitLighting  []draws.Image
	HoldLighting []draws.Image
	// contains filtered or unexported fields
}

Each piano's sub mode has different skin. Fields starting with lowercase are derived from mode package.

func (*Skins) Load added in v0.3.1

func (skins *Skins) Load(fsys fs.FS)

Jump to

Keyboard shortcuts

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