Documentation
¶
Index ¶
- Constants
- Variables
- func BPMs(transPoints []*TransPoint, duration int64) (main, min, max float64)
- func Level(c interface{ ... }) (float64, [3]float64)
- func LoadReplays(replayRoot string) ([]*osr.Format, error)
- func NewBackground(fsys fs.FS, name string) draws.Sprite
- func Normalize[V Number](v *V, min, max V)
- func NormalizeKeys(names []string) []string
- type BackgroundDrawer
- type Chart
- type ChartHeader
- type ComboDrawer
- type Judgment
- type MeterDrawer
- type MeterMark
- type Number
- type Result
- type Sample
- type ScoreDrawer
- type Scorer
- type Settings
- type Skin
- type Timer
- type TransPoint
Constants ¶
const ( DecayFactor = 0.95 LevelPower = 1.15 LevelScale = 0.02 )
Todo: find the best SliceDuration value
const ( Flow = iota Acc Extra Total )
Total score consists of 3 scores: Flow, Acc, and Kool rate score. Flow score is calculated with sum of Flow. Flow once named as Karma. Acc score is calculated with sum of Acc of judgments. Extra score is calculated with a sum of Extra primitive. Flow recovers fast when its value is low, vice versa: math.Pow(x, a); a < 1 Acc and Extra score increase faster as each parameter approaches to max value: math.Pow(x, b); b > 1
const ( // Currently, TPS should be 1000 or greater. // TPS supposed to be multiple of 1000, since only one speed value // goes passed per Update, while unit of TransPoint's time is 1ms. // TPS affects only on Update(), not on Draw(). // Todo: add lower TPS support TPS = 1000 // ScreenSize is a logical size of in-game screen. ScreenSizeX = 1600 ScreenSizeY = 900 )
const ( Default = iota User Play // For skin. Refreshes on every play. )
const ( ScoreDot = iota ScoreComma ScorePercent )
const Wait = 1800
Variables ¶
var ( ColorKool = color.NRGBA{0, 170, 242, 255} // Blue ColorCool = color.NRGBA{85, 251, 255, 255} // Skyblue ColorGood = color.NRGBA{51, 255, 40, 255} // Lime ColorBad = color.NRGBA{244, 177, 0, 255} // Yellow ColorMiss = color.NRGBA{109, 120, 134, 255} // Gray )
var ( UserSettings = NewSettings() S = &UserSettings )
var ( DefaultSkin = &Skin{} UserSkin = &Skin{} )
var ( ToTick = times.ToTick ToTime = times.ToTime )
var DefaultMaxScores = [4]float64{
7 * 1e5,
3 * 1e5,
1 * 1e5,
11 * 1e5,
}
var MeterMarkColors = []color.NRGBA{
{255, 255, 255, 192},
{213, 0, 242, 192},
{252, 83, 6, 255},
}
Todo: refactor MeterDrawer code
Functions ¶
func BPMs ¶
func BPMs(transPoints []*TransPoint, duration int64) (main, min, max float64)
BPM with longest duration will be main BPM. When there are multiple BPMs with same duration, larger one will be main BPM.
func Level ¶
No need to define interface{} called ChartAnalyzer: https://go.dev/play/p/PtgBkwKZFhP
func LoadReplays ¶
Todo: Make own ScenePlay for calculating score from input replay file Todo: implement non-playing score simulator NewScenePlayCalc(Chart, Mods, *osr.Format); Update returns PlayToResultArgs {} if finished.
func NormalizeKeys ¶
Types ¶
type BackgroundDrawer ¶
Order of fields of drawer: updating fields, others fields, sprites
func (BackgroundDrawer) Draw ¶
func (d BackgroundDrawer) Draw(dst draws.Image)
func (d *BackgroundDrawer) Update() { if v := UserSettings.BackgroundBrightness; d.Brightness != v { d.Brightness = v } }
type ChartHeader ¶
type ChartHeader struct { SetID int64 // Compatibility for osu. ID int64 MusicName string MusicUnicode string Artist string ArtistUnicode string MusicSource string ChartName string Charter string HolderID int64 PreviewTime int64 MusicFilename string // Filename is fine to use (cf. Filepath) ImageFilename string VideoFilename string VideoTimeOffset int64 Mode int SubMode int }
ChartHeader contains non-play information. Changing ChartHeader's data will not affect integrity of the chart. Mode-specific fields are located to each Chart struct.
func NewChartHeader ¶
func NewChartHeader(f any) (c ChartHeader)
func (ChartHeader) WindowTitle ¶
func (c ChartHeader) WindowTitle() string
type ComboDrawer ¶
type ComboDrawer struct { draws.Timer DigitWidth float64 // Use number 0's width. DigitGap float64 Combo int Bounce float64 Sprites [10]draws.Sprite }
Todo: add combo *int and skip passing combo value?
func (ComboDrawer) Draw ¶
func (d ComboDrawer) Draw(dst draws.Image)
ComboDrawer's Draw draws each number at constant x regardless of their widths.
func (*ComboDrawer) Update ¶
func (d *ComboDrawer) Update(combo int)
Each number has different width. Number 0's width is used as standard.
type Judgment ¶
type MeterDrawer ¶
type MeterDrawer struct { MaxCountdown int Marks []MeterMark Meter draws.Sprite Anchor draws.Sprite Unit draws.Sprite }
func NewMeterDrawer ¶
func NewMeterDrawer(js []Judgment, colors []color.NRGBA) (d MeterDrawer)
Anchor is a unit sprite constantly drawn at the middle of meter. Todo: should w and h be math.Ceil()?
func (*MeterDrawer) AddMark ¶
func (d *MeterDrawer) AddMark(offset int, colorType int)
func (MeterDrawer) Draw ¶
func (d MeterDrawer) Draw(dst draws.Image)
func (*MeterDrawer) Update ¶
func (d *MeterDrawer) Update()
type Result ¶
type Result struct { MD5 [16]byte // MD5 for raw chart file. md5.Size = 16 PlayedTime time.Time // Finish time of playing. ScoreFactors [3]float64 // Retrieved from the chart. Scores [4]float64 JudgmentCounts []int MaxCombo int }
Todo: SceneResult. keep playing music when at SceneResult. Todo: implement Replay
type ScoreDrawer ¶
type ScoreDrawer struct { DigitGap float64 ZeroFill int Score draws.Delayed Sprites []draws.Sprite // contains filtered or unexported fields }
func NewScoreDrawer ¶
func NewScoreDrawer(sprites []draws.Sprite) ScoreDrawer
func (ScoreDrawer) Draw ¶
func (d ScoreDrawer) Draw(dst draws.Image)
NumberDrawer's Draw draws each number at the center of constant-width bound.
func (*ScoreDrawer) Update ¶
func (d *ScoreDrawer) Update(score float64)
type Scorer ¶
type Scorer struct { Flow float64 Combo int Primitives [3]float64 // Sum of aquired primitive. Ratios [3]float64 Weights [3]float64 // Works as current max value of note weights. MaxWeights [3]float64 // Works as Upper bound. ScoreFactors [3]float64 Scores [4]float64 ScoreBounds [4]float64 MaxScores [4]float64 JudgmentCounts []int MaxCombo int }
func (*Scorer) BreakCombo ¶
func (s *Scorer) BreakCombo()
func (*Scorer) SetMaxScores ¶
type Settings ¶
type Settings struct { VolumeMusic float64 VolumeSound float64 Offset int64 BackgroundBrightness float64 MeterUnit float64 // number of pixels per 1ms MeterHeight float64 ScoreScale float64 ScoreDigitGap float64 }
Struct as a type of settings value is discouraged. Unmatched fields will not be touched, feel free to pre-fill default values. Todo: alert warning message to user when some lines are failed to be decoded Todo: BackgroundBrightness -> Brightness Todo: Brightness first, then Offset
func NewSettings ¶
func NewSettings() Settings
type Skin ¶
In narrow meaning, Skin stands for a set of Sprites. In wide meaning, Skin also includes a set of sounds. Package defaultskin has a set of sounds.
type Timer ¶
type TransPoint ¶
type TransPoint struct { Time int64 BPM float64 Speed float64 Meter int NewBeat bool // NewBeat draws a bar. Volume float64 // Range is [0, 1]. Highlight bool Position float64 Next *TransPoint Prev *TransPoint }
func NewTransPoints ¶
func NewTransPoints(f any) []*TransPoint
First BPM is used as temporary main BPM. No two TransPoints have same Time.
func (TransPoint) BeatDuration ¶
func (tp TransPoint) BeatDuration() float64
func (*TransPoint) FetchByTime ¶
func (tp *TransPoint) FetchByTime(time int64) *TransPoint