Add some lofivor notes
This commit is contained in:
parent
aa3a9653bb
commit
974253b262
2 changed files with 150 additions and 58 deletions
93
TODO.md
93
TODO.md
|
|
@ -1,72 +1,49 @@
|
|||
# lockstep artillery - build roadmap
|
||||
# lofivor - build roadmap
|
||||
|
||||
## phase 1: foundation
|
||||
survivor-like optimized for weak hardware. finding the performance ceiling first, then building the game.
|
||||
|
||||
- [x] set up build.zig with raylib-zig dependency
|
||||
- [x] create fixed-point math module (Fixed struct, add/sub/mul/div)
|
||||
- [x] create trig lookup tables (sin/cos at comptime)
|
||||
- [x] basic window opens with raylib
|
||||
## phase 1: sandbox stress test
|
||||
|
||||
## phase 2: single-player simulation
|
||||
- [ ] create sandbox.zig (separate from existing game code)
|
||||
- [ ] entity struct (x, y, vx, vy, color)
|
||||
- [ ] flat array storage for entities
|
||||
- [ ] spawn entities at random screen edges
|
||||
- [ ] update loop: move toward center, respawn on arrival
|
||||
- [ ] render: filled circles (4px radius, cyan)
|
||||
- [ ] metrics overlay (entity count, frame time, update time, render time)
|
||||
- [ ] controls: +/- 100, shift +/- 1000, space pause, r reset
|
||||
|
||||
- [x] define GameState, Player, Projectile structs
|
||||
- [x] terrain generation (fixed pattern for now)
|
||||
- [x] cannon aiming (angle adjustment with keys)
|
||||
- [x] power adjustment
|
||||
- [x] fire projectile
|
||||
- [x] projectile physics (gravity, movement)
|
||||
- [x] terrain collision detection
|
||||
- [x] player hit detection
|
||||
- [x] turn switching after shot resolves
|
||||
## phase 2: find the ceiling
|
||||
|
||||
## phase 3: rendering
|
||||
- [ ] test on i5-6500T / HD 530 @ 1280x1024
|
||||
- [ ] record entity count where 60fps breaks
|
||||
- [ ] identify bottleneck (CPU update vs GPU render)
|
||||
- [ ] document findings
|
||||
|
||||
- [x] draw terrain as connected line segments
|
||||
- [x] draw players as geometric shapes
|
||||
- [x] draw cannon angle indicator
|
||||
- [x] draw power meter
|
||||
- [x] draw projectile with trail (last N positions)
|
||||
- [x] implement bloom shader (blur.fs)
|
||||
- [x] render-to-texture pipeline for glow effect
|
||||
- [x] explosion effect (expanding circle)
|
||||
## phase 3: optimization experiments
|
||||
|
||||
## phase 4: local two-player
|
||||
based on phase 2 results:
|
||||
|
||||
- [ ] split keyboard input (player 1: wasd+space, player 2: arrows+enter)
|
||||
- [ ] verify determinism by running two simulations side-by-side
|
||||
- [ ] add checksum verification
|
||||
- [ ] if render-bound: batch rendering, instancing
|
||||
- [ ] if cpu-bound: SIMD, struct-of-arrays, multithreading
|
||||
- [ ] re-test after each change
|
||||
|
||||
## phase 5: networking
|
||||
## phase 4: add collision
|
||||
|
||||
- [ ] UDP socket wrapper (bind, send, receive)
|
||||
- [ ] define packet format (INPUT, SYNC, PING, PONG)
|
||||
- [ ] host mode: listen for connection, send initial SYNC
|
||||
- [ ] guest mode: connect, receive SYNC, start simulation
|
||||
- [ ] input exchange each frame
|
||||
- [ ] handle packet loss (resend on timeout)
|
||||
- [ ] checksum exchange and desync detection
|
||||
- [ ] latency display
|
||||
- [ ] spatial partitioning (grid or quadtree)
|
||||
- [ ] projectile-to-enemy collision
|
||||
- [ ] measure new ceiling with collision enabled
|
||||
|
||||
## phase 6: polish
|
||||
## phase 5: game loop
|
||||
|
||||
- [ ] wind indicator
|
||||
- [ ] health bars
|
||||
- [ ] win/lose screen
|
||||
- [ ] rematch option
|
||||
- [ ] sound effects (optional, breaks no-dependency purity)
|
||||
- [ ] player entity (keyboard controlled)
|
||||
- [ ] enemy spawning waves
|
||||
- [ ] player attacks / projectiles
|
||||
- [ ] enemy death on hit
|
||||
- [ ] basic game feel
|
||||
|
||||
## known pitfalls to watch
|
||||
## future
|
||||
|
||||
- [ ] don't use floats in simulation
|
||||
- [ ] don't iterate hashmaps
|
||||
- [ ] don't use @sin/@cos - use lookup tables
|
||||
- [ ] always process inputs in same order (player 0 then player 1)
|
||||
- [ ] serialize terrain heights as fixed-point, not float
|
||||
|
||||
## stretch goals
|
||||
|
||||
- [ ] destructible terrain (explosion removes pixels)
|
||||
- [ ] multiple weapon types
|
||||
- [ ] rollback netcode (predict, rewind, replay on correction)
|
||||
- [ ] replay file save/load
|
||||
- [ ] web build via emscripten
|
||||
- [ ] different enemy types
|
||||
- [ ] player upgrades
|
||||
- [ ] actual game design (after we know the constraints)
|
||||
|
|
|
|||
115
docs/plans/2025-12-14-sandbox-design.md
Normal file
115
docs/plans/2025-12-14-sandbox-design.md
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# lofivor sandbox - stress test design
|
||||
|
||||
a minimal harness for finding entity count ceilings on weak hardware before designing game systems.
|
||||
|
||||
## goals
|
||||
|
||||
**purpose:** answer "how many simple entities can we update and render at 60fps?"
|
||||
|
||||
**target hardware:**
|
||||
- primary: intel i5-6500T + HD 530 (thinkcentre m900) @ 1280x1024
|
||||
- secondary: windows laptop for dev iteration
|
||||
|
||||
**what it does:**
|
||||
- spawns colored circles that drift toward screen center
|
||||
- manual controls to add/remove entities in real-time
|
||||
- on-screen metrics: entity count, frame time (ms), update time, render time
|
||||
- circles respawn at random edge when reaching center
|
||||
|
||||
**what it doesn't do (yet):**
|
||||
- no collision detection
|
||||
- no player input beyond entity count controls
|
||||
- no game logic, damage, spawning waves
|
||||
- no particles or visual effects
|
||||
|
||||
**success criteria:**
|
||||
- locked 60fps with some meaningful entity count (finding that number is the goal)
|
||||
- clear breakdown of where frame time goes (CPU update vs GPU render)
|
||||
- stable enough to leave running while tweaking counts
|
||||
|
||||
## data structures
|
||||
|
||||
```zig
|
||||
const Entity = struct {
|
||||
x: f32,
|
||||
y: f32,
|
||||
vx: f32,
|
||||
vy: f32,
|
||||
color: u32,
|
||||
};
|
||||
```
|
||||
|
||||
simple flat array of entities. no ECS, no spatial partitioning, no indirection. measuring the baseline - fancy structures come later.
|
||||
|
||||
**memory budget:** 20 bytes per entity. 10k entities = 200KB (fits in L2 cache on skylake).
|
||||
|
||||
## update loop
|
||||
|
||||
```
|
||||
for each entity:
|
||||
x += vx
|
||||
y += vy
|
||||
if distance_to_center < threshold:
|
||||
respawn at random edge
|
||||
recalculate vx, vy toward center
|
||||
```
|
||||
|
||||
~5 float ops per entity per frame. no collision, no branching beyond respawn check.
|
||||
|
||||
**velocity:** on spawn, compute normalized direction to center, multiply by constant speed, store vx/vy.
|
||||
|
||||
## rendering
|
||||
|
||||
each frame:
|
||||
1. clear screen (dark background #0a0a12)
|
||||
2. draw all entities as filled circles (4px radius)
|
||||
3. draw metrics overlay
|
||||
|
||||
**entity color:** cyan (#00ffff) - bright against dark background
|
||||
|
||||
**metrics overlay (top-left):**
|
||||
```
|
||||
entities: 5000
|
||||
frame: 12.4ms
|
||||
update: 8.2ms
|
||||
render: 4.1ms
|
||||
```
|
||||
|
||||
## controls
|
||||
|
||||
| key | action |
|
||||
|-----|--------|
|
||||
| `=` / `+` | add 100 entities |
|
||||
| `-` | remove 100 entities |
|
||||
| `shift + =` | add 1000 entities |
|
||||
| `shift + -` | remove 1000 entities |
|
||||
| `space` | pause update loop (render continues) |
|
||||
| `r` | reset to 0 entities |
|
||||
|
||||
pause isolates render cost from update cost.
|
||||
|
||||
## what we're measuring
|
||||
|
||||
**key questions:**
|
||||
1. what's the entity ceiling at 60fps? (where frame time crosses 16.6ms)
|
||||
2. is it CPU-bound or GPU-bound? (compare update vs render time)
|
||||
3. where does it fall apart? (gradual degradation or sudden cliff?)
|
||||
|
||||
**hypotheses to test:**
|
||||
- HD 530 might struggle with thousands of individual draw calls (GPU-bound)
|
||||
- if CPU-bound, update loop needs SIMD or better memory access
|
||||
- skylake's 4 cores are untouched - parallelism is a future lever
|
||||
|
||||
## next steps based on results
|
||||
|
||||
| bottleneck | next experiment |
|
||||
|------------|-----------------|
|
||||
| render (draw calls) | batch rendering - instancing, sprite batches |
|
||||
| update (CPU) | SIMD, struct-of-arrays layout, multithreading |
|
||||
| both equally | optimize either for gains |
|
||||
|
||||
## stretch measurements
|
||||
|
||||
- memory bandwidth (cache-bound?)
|
||||
- draw call count vs batched draws
|
||||
- fixed-point vs float update cost comparison
|
||||
Loading…
Reference in a new issue