v0.1.0 initial commit
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
package parameter
|
||||
|
||||
// Row-reset funnels, drawn in the inter-tile gap row of the player lane.
|
||||
// Drop = jump expiry (falling to the base row), Rise = slide expiry.
|
||||
// %s is the countdown; formatted width must not exceed RenderNoteWidth
|
||||
const (
|
||||
DropFunnelFormat = `\\ %s //`
|
||||
RiseFunnelFormat = `// %s \\`
|
||||
)
|
||||
|
||||
// Inbound — chords until the lane shuts.
|
||||
// Clear — chords until the lane reopens.
|
||||
// Open — the wall run reaches the window edge; the value is a lower bound.
|
||||
// Trap — the lane reopens for <= TrapGapMax chords before shutting again;
|
||||
// flagged on both the inbound and the clear timer
|
||||
const (
|
||||
TimerInboundPrefix = '▼'
|
||||
TimerClearPrefix = '▲'
|
||||
TimerOpenSuffix = '+'
|
||||
TimerTrapSuffix = '!'
|
||||
)
|
||||
|
||||
// StripEmptyChar is lookahead strip rail cell — a chord with no content at this position
|
||||
const StripEmptyChar = '·'
|
||||
|
||||
// ItemFadeChars is the glyph tail of a consumed item's burn-out. Stage 0
|
||||
// keeps the item glyph; later stages collapse it into the rail cell
|
||||
var ItemFadeChars = [...]rune{'+', StripEmptyChar}
|
||||
|
||||
// UnknownChar is placeholder for a Value with no authored visual.
|
||||
// Keeps NoteVisual total so an unrendered kind is visible rather than eating an item slot
|
||||
const UnknownChar = '?'
|
||||
|
||||
// MutedText marks the host audio gate in the header. ASCII, so it
|
||||
// renders in both atlases
|
||||
const MutedText = "MUTE"
|
||||
|
||||
// QuadrantChars provides 2x2 sub-cell resolution for TrueColor mode
|
||||
// Bitmap encoding: bit0=UL, bit1=UR, bit2=LL, bit3=LR
|
||||
// Layout: [UL][UR]
|
||||
//
|
||||
// [LL][LR]
|
||||
var QuadrantChars = [16]rune{
|
||||
' ', // 0000 - empty
|
||||
'▘', // 0001 - upper-left
|
||||
'▝', // 0010 - upper-right
|
||||
'▀', // 0011 - upper half
|
||||
'▖', // 0100 - lower-left
|
||||
'▌', // 0101 - left half
|
||||
'▞', // 0110 - anti-diagonal
|
||||
'▛', // 0111 - UL + UR + LL
|
||||
'▗', // 1000 - lower-right
|
||||
'▚', // 1001 - diagonal
|
||||
'▐', // 1010 - right half
|
||||
'▜', // 1011 - UL + UR + LR
|
||||
'▄', // 1100 - lower half
|
||||
'▙', // 1101 - UL + LL + LR
|
||||
'▟', // 1110 - UR + LL + LR
|
||||
'█', // 1111 - full block
|
||||
}
|
||||
|
||||
// Half256Chars provides vertical half-cell resolution for 256-color mode.
|
||||
// Unicode block characters, CP437-equivalent visuals, naked-TTY compatible
|
||||
// Bitmap encoding: bit0=top, bit1=bottom
|
||||
var Half256Chars = [4]rune{
|
||||
' ', // 00 - empty
|
||||
'\u2580', // 01 - top half only (▀)
|
||||
'\u2584', // 10 - bottom half only (▄)
|
||||
'\u2588', // 11 - both halves (█)
|
||||
}
|
||||
|
||||
// Horizontal256Chars provides horizontal half-cell characters.
|
||||
// Reserved for future horizontal sub-pixel support
|
||||
var Horizontal256Chars = [2]rune{
|
||||
'\u258C', // ▌ - left half
|
||||
'\u258E', // ▐ - right half
|
||||
}
|
||||
|
||||
// Density256Chars provides intensity variants for trail and glow effects,
|
||||
// ordered lowest to highest density. Also indexes wall proximity bands
|
||||
var Density256Chars = [4]rune{
|
||||
'\u2591', // ░ - light shade (25%)
|
||||
'\u2592', // ▒ - medium shade (50%)
|
||||
'\u2593', // ▓ - dark shade (75%)
|
||||
'\u2588', // █ - full block (100%)
|
||||
}
|
||||
|
||||
// Single-line box drawing characters
|
||||
const (
|
||||
BorderSingleHorizontal = '─' // U+2500
|
||||
BorderSingleVertical = '│' // U+2502
|
||||
BorderSingleTopLeft = '┌' // U+250C
|
||||
BorderSingleTopRight = '┐' // U+2510
|
||||
BorderSingleBottomLeft = '└' // U+2514
|
||||
BorderSingleBottomRight = '┘' // U+2518
|
||||
BorderSingleVerticalRight = '├' // U+251C
|
||||
BorderSingleVerticalLeft = '┤' // U+2524
|
||||
BorderSingleHorizontalDown = '┬' // U+252C
|
||||
BorderSingleHorizontalUp = '┴' // U+2534
|
||||
BorderSingleCross = '┼' // U+253C
|
||||
)
|
||||
|
||||
// Double-line box drawing characters
|
||||
const (
|
||||
BorderDoubleHorizontal = '═' // U+2550
|
||||
BorderDoubleVertical = '║' // U+2551
|
||||
BorderDoubleTopLeft = '╔' // U+2554
|
||||
BorderDoubleTopRight = '╗' // U+2557
|
||||
BorderDoubleBottomLeft = '╚' // U+255A
|
||||
BorderDoubleBottomRight = '╝' // U+255D
|
||||
BorderDoubleVerticalRight = '╠' // U+2560
|
||||
BorderDoubleVerticalLeft = '╣' // U+2563
|
||||
BorderDoubleHorizontalDown = '╦' // U+2566
|
||||
BorderDoubleHorizontalUp = '╩' // U+2569
|
||||
BorderDoubleCross = '╬' // U+256C
|
||||
)
|
||||
@@ -0,0 +1,159 @@
|
||||
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
|
||||
)
|
||||
Reference in New Issue
Block a user