48 lines
1.4 KiB
Go
48 lines
1.4 KiB
Go
package render
|
|
|
|
import (
|
|
"time"
|
|
|
|
"symph/game"
|
|
"symph/parameter"
|
|
"symph/types"
|
|
)
|
|
|
|
// FadeGrid projects the engine's consumed-note ring onto strip coordinates for
|
|
// one frame: burn-out progress per (y, x, chord-distance). Entries outside the
|
|
// window or past ItemFadeDuration are dropped. A consumed cell at distance 0
|
|
// scrolls off on the next beat; the fade is shorter than the tightest beat, so
|
|
// it always resolves before the strip shifts
|
|
type FadeGrid struct {
|
|
value [parameter.GamePlayIndexYMax][parameter.GamePlayIndexXMax][game.TileLookaheadMaxWindow]types.Value
|
|
t [parameter.GamePlayIndexYMax][parameter.GamePlayIndexXMax][game.TileLookaheadMaxWindow]float64
|
|
}
|
|
|
|
func (f *FadeGrid) Refresh(s *game.GameState, now time.Time) {
|
|
*f = FadeGrid{}
|
|
for _, c := range s.Consumed() {
|
|
if c.Value == types.ValueNone {
|
|
continue
|
|
}
|
|
age := now.Sub(c.At)
|
|
if age < 0 || age >= parameter.ItemFadeDuration {
|
|
continue
|
|
}
|
|
d := c.Z - s.CurrentPlayIndexZ
|
|
if d < 0 || d >= game.TileLookaheadMaxWindow {
|
|
continue
|
|
}
|
|
f.value[c.Y][c.X][d] = c.Value
|
|
f.t[c.Y][c.X][d] = float64(age) / float64(parameter.ItemFadeDuration)
|
|
}
|
|
}
|
|
|
|
// At reports the item burning out at a strip cell and its progress in [0,1)
|
|
func (f *FadeGrid) At(y, x, d int) (types.Value, float64, bool) {
|
|
if d < 0 || d >= game.TileLookaheadMaxWindow {
|
|
return types.ValueNone, 0, false
|
|
}
|
|
v := f.value[y][x][d]
|
|
return v, f.t[y][x][d], v != types.ValueNone
|
|
}
|