Commit Graph
9 Commits
Author SHA1 Message Date
Emil a5436897ed wip: current project state 2026-06-21 22:27:20 +03:00
Emil 357db17c2f feat: GPU optimization — lighting, viewport CA, benchmark mode, 531 FPS
- Resolution: 8x8 world cells, 2x2 UI cells (UI_SCALE=4)
- GPU lighting: vertex-shader computed, light source list buffer (max 64)
  instead of O(N×R²) grid scan, O(N×S) per cell
- Viewport-aware CA: iterate only active chunks, not all 250×250
- Flat array entity/item/shadow maps instead of HashMaps
- Flat 128-entry ASCII atlas array instead of HashMap lookup
- Partial grid upload: viewport + 30-cell margin only
- Pre-allocated viewport arrays in renderer structs (zero alloc/frame)
- Skip CPU lighting for GPU modes (pass None)
- Benchmark mode: --mode benchmark with per-subsystem timing
- GpuLightSource struct, light_count in push constants
- gather_sources_in_range() for viewport-scoped source gathering

Benchmark (600 ticks, release):
  Graphics: 531 FPS (was 386, +38%), render 1013us (was 1699us, -40%)
  ASCII:    402 FPS (was 313, +28%), render 1502us (was 2346us, -36%)

All 171 tests + 14 scenarios pass.
2026-06-21 16:09:45 +03:00
Emil 68fe0b87dd refactor: code cleanup — dead code, warnings, duplication
Dead code removed (21 methods, 4 fields, 3 constants):
- Cell: MaterialId::ALL, MaterialId::from_u8 (unsafe transmute)
- Grid: get_mut, clear, fill_rect, swap, dump_region, next buffer field
- Entity: move_center, EntityManager::iter_mut
- Player: move_dir field, entity_mut
- VerletSolver: step, SubBody::add_vel, SubBody::apply_force
- CellularAutomaton: tick_count
- InputHandler: release_all, poll, Action::None
- WindowInput: clear
- GameSession: perform_action_and_step, is_recording, grid_mut
- ReplayPlayer: from_recording
- Material: empty()
- VulkanRenderer: tick_count field
- MaterialBrush: name()

Warnings fixed:
- Remove unused MaterialRegistry imports from renderers
- Remove unused reg variables in terminal/vulkan/graphics
- Remove unused water_surface in game.rs
- Remove unused p/y_death in tests
- Remove unused qf_slice in graphics.rs

Duplication eliminated:
- main.rs: run_ascii_mode + run_graphics_mode → generic run_gpu_mode<R: GpuRenderer>
  ~140 lines of duplicated event loop code removed
- GpuRenderer trait unifies VulkanRenderer and GraphicsRenderer API

Unsafe code fixed:
- rand_u8: static mut + unsafe → AtomicU8 + fetch_add (thread-safe)

Module cleanup:
- world/mod.rs: removed all unused re-exports
- physics/mod.rs: removed all unused re-exports
- entity/mod.rs: removed unused Entity/EntityId re-exports

Result: ~6500 → ~5964 lines, 0 non-deprecation warnings, 109 tests pass
2026-06-21 01:36:25 +03:00
Emil 6d98c09ece fix: request keyboard enhancement flags for proper Release events
Root cause of both issues: terminals don't send Release events by
default. When pressing W while holding A, terminal stops repeating A
(but doesn't send Release), so A times out and strafing breaks.
On key release, 400ms timeout means 400ms of extra movement.

Fix: PushKeyboardEnhancementFlags(REPORT_EVENT_TYPES) in terminal init.
This asks the terminal to send proper Press/Release/Repeat events for
ALL keys, not just special ones.

With Release events:
- Key release is instant (no 400ms timeout delay)
- Pressing W doesn't cancel A's held state (terminal sends Release
  only when A is actually released)
- A/D strafing works while W is held

Fallback: if terminal doesn't support enhancement flags (old xterm),
got_release flag stays false and 150ms timeout is used. Once any
Release event is received, all keys switch to Release-based mode
(infinite timeout, rely on actual Release events).

109 tests, 0 warnings, 0 failures
2026-06-20 23:48:03 +03:00
Emil 61e2cf1544 fix: dual-timeout held keys to fix terminal initial repeat delay
Root cause: terminals wait 300-500ms after initial Press before
sending the first Repeat event. With 60ms timeout, the key was
released during this gap, causing step-pause-accelerate pattern.

Fix: two timeout phases:
- After Press (no Repeat seen yet): 400ms timeout
  Covers terminal's initial repeat delay, key stays held
- After first Repeat: 80ms timeout
  Repeats arrive every ~30ms, 80ms is safe margin
  Quick release detection once repeating starts

Result: smooth continuous movement from first keypress, no gap
2026-06-20 23:43:31 +03:00
Emil 9458d265f0 fix: background input thread for responsive non-blocking input
Problem: event::poll(0ms) once per frame missed events between frames,
causing laggy/missed input. Terminal key repeat timing was unpredictable.

Fix: dedicated input thread that blocks on event::read() and pushes
all events to an mpsc channel. Game loop drains channel with try_iter()
each frame — gets every event without blocking, zero missed inputs.

- InputHandler::start() spawns background thread
- InputHandler::stop() cleans up on game exit
- try_iter() collects all accumulated events per frame
- Removed 16ms sleep (no longer needed, input doesn't block)
- Hold timeout reduced to 60ms (events arrive more reliably now)
- 109 tests, 0 warnings, 0 failures
2026-06-20 23:41:33 +03:00
Emil e1eb9cc7cd fix: terminal input - timeout-based held keys, press-only jump
Terminals don't send Release events for most keys, so held keys
stayed active forever. Two problems:

1. W = infinite jump: Jump was in held_actions, fired every tick
   while held. check_on_ground returned true immediately after
   landing, causing auto-bounce.
   Fix: Jump fires only on initial Press event (jump_pressed flag),
   not on Repeat or held state.

2. A ignores D: When both A and D were held, both applied velocity
   and cancelled out. But terminal never sends Release for A, so
   D couldn't take over.
   Fix: Left/Right are mutually exclusive — most recently pressed
   key wins (compares last_seen timestamps).

3. Held key timeout: Keys expire after 80ms without a Repeat event,
   simulating Release for terminals that don't send it.

109 tests, 0 warnings, 0 failures
2026-06-20 23:30:37 +03:00
Emil 00c6b3bf87 fix: held-key input model for smooth movement
Problem: terminal key repeat sends one event, then pauses ~500ms,
then floods repeats. This caused stop-then-accelerate movement.

Fix: track held keys (Press/Release events), apply movement every
tick based on held state, not per-event. Jump still fires once per
press. Paint and quit are one-shot actions.

- InputHandler: held: Vec<HeldKey> tracks Left/Right/Jump/Camera
- update(): drains all pending events, updates held state
- held_actions(): returns active movement actions per tick
- handle_input: applies held actions every frame
- Camera pan reduced to 2/tick (was 5) for smoothness
- 109 tests, 0 warnings, 0 failures
2026-06-20 23:28:11 +03:00
Emil 68f6292c4d feat: Verbatim MVP - terminal renderer, cellular automaton, Verlet physics
- World: 250x250 grid with 14 materials (sand, water, lava, stone, wood, etc.)
- Physics: cellular automaton for materials + Verlet solver for entities
- Entity: multi-cell humanoid (7 sub-bodies with distance constraints)
- Render: terminal renderer with ANSI colors and diff-based updates
- Game loop: fixed 60Hz timestep with accumulator pattern
- Input: WASD movement, number keys for material painting
2026-06-20 18:21:26 +03:00