160 lines
5.4 KiB
Go
160 lines
5.4 KiB
Go
package parameter
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
// Core game grid and timing
|
|
const (
|
|
// GameRenderUpdate is the frontend frame interval (~60fps). Beat
|
|
// quantization is owned by the engine; this only paces UI wakeups
|
|
GameRenderUpdate = 16 * time.Millisecond
|
|
|
|
// GameDeltaZBase is the level-1 inter-chord interval. GameDeltaZStep
|
|
// shortens it per level down to the GameDeltaZMin floor
|
|
GameDeltaZBase = 500 * time.Millisecond
|
|
GameDeltaZStep = 20 * time.Millisecond
|
|
GameDeltaZMin = 300 * time.Millisecond
|
|
|
|
// PlayerRowResetChords chords at whatever tempo is running, so a pattern's
|
|
// landing chord is invariant across levels and across a Boost.
|
|
// 3 * GameDeltaZBase == the previous 1500ms; level 1 is unchanged.
|
|
// Lane (X) shifts are persistent and never auto-reset
|
|
PlayerRowResetChords = 3
|
|
|
|
// ItemFadeDuration is the burn-out span of a consumed positive item.
|
|
// Kept under GameDeltaZMin/BoostSpeedFactor so the effect always completes inside one
|
|
// chord and reads as consumption, not as the strip scrolling
|
|
ItemFadeDuration = 140 * time.Millisecond
|
|
|
|
// ItemFlashFraction is the leading white-flash portion of the burn-out
|
|
ItemFlashFraction = 0.25
|
|
|
|
// TransitionDuration is the level-clear interlude length
|
|
TransitionDuration = 2000 * time.Millisecond
|
|
|
|
// Song length ceiling
|
|
GamePlayIndexZMax = 256
|
|
|
|
// Chord dimensions
|
|
GamePlayIndexYMax = 3
|
|
GamePlayIndexXMax = 3
|
|
|
|
// Player spawn position (grid center)
|
|
GamePlayIndexYStart = GamePlayIndexYMax / 2
|
|
GamePlayIndexXStart = GamePlayIndexXMax / 2
|
|
)
|
|
|
|
// Song generation
|
|
const (
|
|
// SongBaseLength + (level-1)*SongLengthPerLevel chords per level,
|
|
// capped at GamePlayIndexZMax
|
|
SongBaseLength = 72
|
|
SongLengthPerLevel = 12
|
|
|
|
// Guaranteed empty chords at song edges (grace-in, clean finish)
|
|
GenIntroRest = 6
|
|
GenOutroRest = 4
|
|
|
|
// Rest gap between pattern chains: GenRestBase shrinks by one per level
|
|
// down to GenRestMin
|
|
GenRestBase = 7
|
|
GenRestMin = 2
|
|
|
|
// Patterns chained back-to-back per burst
|
|
GenChainBase = 1
|
|
GenChainMax = 5
|
|
|
|
// Chance of a single empty chord between chained patterns
|
|
GenBreatherProbability = 0.5
|
|
)
|
|
|
|
// Lookahead observation window. Window width covers every wall band; band
|
|
// geometry and trap threshold are parameterized here
|
|
const (
|
|
// PositionLookaheadWindow is how many upcoming chords (starting at the
|
|
// current one, distance 0) are scanned per grid position.
|
|
// Hard ceiling: game.TileLookaheadMaxWindow (wall bitmask width)
|
|
PositionLookaheadWindow = 10
|
|
|
|
// Wall proximity bands. Band 0 is the arrived wall (distance 0); bands
|
|
// 1..WallBandCount-1 each span WallBandSize chords. Band index selects
|
|
// border fill density and color
|
|
WallBandSize = 3
|
|
WallBandCount = 4
|
|
|
|
// TrapGapMax is the largest reopen gap still flagged as a trap: a lane
|
|
// that clears for <= this many chords before another wall shuts it
|
|
TrapGapMax = 2
|
|
|
|
// ConsumeRingSize bounds the consumed-note ring the frontends read
|
|
// for burn-out. A magnet sweep can consume up to
|
|
// GamePlayIndexYMax*GamePlayIndexXMax*PositionLookaheadWindow notes; on
|
|
// overflow the oldest burn-out is dropped (visual-only degradation)
|
|
ConsumeRingSize = 64
|
|
|
|
// MorphWindow is the chord-distance over which a non-wall Value's color
|
|
// interpolates from distant to arrived
|
|
MorphWindow = 4
|
|
)
|
|
|
|
// Player effects granted by items. Both survive a level change and are cleared on restart
|
|
const (
|
|
// BoostDuration is the wall-clock lifetime of a Boost. A second pickup
|
|
// refreshes the deadline, it does not extend it
|
|
BoostDuration = 10 * time.Second
|
|
|
|
// BoostSpeedFactor divides the inter-chord interval while a Boost runs.
|
|
// Integer divisor: the boosted interval stays exact. A slow effect would
|
|
// multiply in the same place
|
|
BoostSpeedFactor = 2
|
|
|
|
// BoostWarnRemaining is the Boost tail over which the HUD countdown blinks.
|
|
// Expiry inside a wall band kills on the next beat; the player
|
|
// needs the lead time to leave the lane
|
|
BoostWarnRemaining = 2 * time.Second
|
|
|
|
// ShieldCharges is the charge count a Shield pickup arms. Each charge
|
|
// absorbs one negative contact; charges never expire and do not stack
|
|
ShieldCharges = 1
|
|
)
|
|
|
|
// The burn-out must finish inside the tightest beat — the level floor divided by the Boost factor.
|
|
// Also proves the boosted interval is > 0, which bounds the Update beat loop
|
|
const _ = uint(GameDeltaZMin/BoostSpeedFactor - ItemFadeDuration)
|
|
|
|
// Compile-time: the window must reach the far edge of the last band
|
|
const _ = uint(PositionLookaheadWindow - (WallBandSize*(WallBandCount-1) + 1))
|
|
|
|
// Tile geometry derives from the strip. PositionLookaheadWindow is
|
|
// the only knob; width follows so the strip is 1:1 with the interior
|
|
const (
|
|
RenderMarginX = 1
|
|
RenderMarginY = 1
|
|
|
|
// RenderHeaderRows is the chrome above the grid (LEVEL / ENERGY).
|
|
// No footer, no title
|
|
RenderHeaderRows = 1
|
|
|
|
// One interior column per lookahead chord, plus the two border columns
|
|
RenderNoteWidth = PositionLookaheadWindow + 2
|
|
RenderNoteHeight = 5
|
|
|
|
RenderGapX = 2
|
|
RenderGapY = 1
|
|
|
|
// Fixed interior row offsets, relative to the tile top border
|
|
RenderRowTimer = 1
|
|
RenderRowDist = 2
|
|
RenderRowStrip = 3
|
|
|
|
// Distance row: "gDD gDD" — glyph + chord-distance, positive group then negative group
|
|
RenderDistDigits = 2
|
|
RenderDistCols = 2*(1+RenderDistDigits) + 1
|
|
|
|
// RenderBlinkPeriod is the half-cycle of the nearest-item blink. The
|
|
// distance-row group of the tile(s) holding the grid-wide nearest
|
|
// positive/negative occurrence alternates between two colors at this rate
|
|
RenderBlinkPeriod = 120 * time.Millisecond
|
|
)
|