Commit Graph
9 Commits
Author SHA1 Message Date
Emil a5436897ed wip: current project state 2026-06-21 22:27:20 +03:00
Emil e50df7b51e feat: detailed characters + Noita-style mouse aiming
Character detail:
- Player: 68 body parts (was 42) — eyes, hair, cape, hat, gloves
- Goblin: 56 body parts (was 39) — red eyes, pointed ears, teeth, skin tones
- New body labels: eye, hair, cape, tooth, ear
- Updated preview_ascii label map for new part types

Mouse aiming (Noita-style):
- Track mouse position via CursorMoved events
- Track left-click via MouseInput events
- Left-click shoots projectile toward mouse cursor direction
- Player faces left/right based on mouse X relative to player screen X
- Keyboard shoot (hjkl) still works as fallback
- Player.facing_right field added
- WindowInput: mouse_x, mouse_y, mouse_left, shoot_mouse fields
- on_mouse_move(), on_mouse_button() handlers
- clear_keys() also clears mouse state on focus loss

All 171 tests + 14 scenarios pass.
2026-06-21 18:07:46 +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 3aa67140c8 feat: vector-based movement for responsive control and air strafing
Changed from physics-based (accumulate + damping) to vector-based:

- Horizontal velocity is SET directly, not accumulated
  - Press A → cvx = -0.5 (instant, no ramp-up)
  - Release → cvx = 0 (instant stop, no sliding)
  - No horizontal damping = precise control
- Air strafing: same horizontal speed in air as on ground
  - Can change direction mid-jump freely
- Vertical: gravity + minimal damping (0.99) for natural fall
  - Jump sets cvy directly, gravity pulls back
- move_speed 0.5 (was 0.3), max_vel 2.0 (was 1.0)
- Player: move_dir tracks current direction, stop_horizontal() clears velocity
- handle_input: calls stop_horizontal when no movement key held

109 tests, 0 warnings, 0 failures
2026-06-20 23:35:41 +03:00
Emil 61b5d551ae test: 109 Rust tests + 14 JSON scenarios, polish physics
Tests added:
- physics_materials.rs: 15 tests (fire, smoke, steam, grass, dirt, bone, wood, stone, lava temp)
- physics_interactions.rs: 12 tests (lava+water, fire spread, acid interactions, sand+water)
- player_controls.rs: 12 tests (move L/R, jump, double jump, rapid input, wait, continuous)
- collision_robust.rs: 10 tests (walls, ceiling, sliding, corridor, slope, dirt wall, unstick)
- ragdoll_death.rs: 7 tests (death transition, ragdoll fall, progressive damage, corpse)
- determinism.rs: 8 tests (same seed, replay exact, replay partial, recording, 100-tick)
- edge_cases.rs: 19 tests (boundary, stress 20 goblins, fill/clear/paint, gravity, camera)
- 6 new JSON scenarios (fire chain, lava pool, sand bury, entity fall, steam, acid wall)

Fixes:
- AABB resolve_aabb_y: add vertical overlap check (was pushing player down when jumping)
- AABB resolve_aabb_x: velocity-aware resolution (player was stuck against walls)
- check_on_ground: use fractional position check (was always true)
- jump_force 1.5 (was 0.8) for 27-body entity
- Gravity read from self.verlet (was from clone, SetGravity didn't work)
- u8 overflow in lava color (saturating_add)

109 Rust tests, 14 JSON scenarios, 0 warnings, 0 failures
2026-06-20 22:42:29 +03:00
Emil e96744b958 feat: rigid living entities, ragdoll corpses, fix WASD movement
- Entity: rigid body mode for alive entities (single object, no wobble)
  - Center position + velocity, bodies positioned from rest offsets
  - Collision: all 16 bodies checked, push applied to center
  - Movement: velocity applied to center, all bodies move together
- Entity: ragdoll mode for corpses (loose Verlet constraints)
  - kill() switches rigid->ragdoll, gives each body inherited velocity
  - Constraints go slack (stiffness=0), bodies fall independently
- Player: move_left/right now applies velocity to entity center (was: head only)
- Physics: lava heat conductivity 0.05 (was 0.5), initial temp 1500 (was 1200)
  Lava cooling threshold 400 (was 800), heat transfer rate 0.1 (was 0.5)
  Lava stays hot long enough for entities to take damage
- Tests: 28/28 passing, updated for new lava and rigid body behavior
2026-06-20 21:39:26 +03:00
Emil 9fe7137e45 feat: bigger characters (16 sub-bodies), wider terminal viewport
- Entity: 16 sub-bodies (was 7), radius 0.7 (was 0.4), full humanoid
  shape: head, shoulders, torso, arms, hips, legs, feet
- Terminal: viewport up to 250x80 (was 120x50), uses full terminal size
- Camera: uses renderer viewport dimensions instead of hardcoded values
- Physics: constraint correction clamped to 0.5 cells max, 8 substeps
  (was 4), gravity 0.04 (was 0.08), collision pass after each constraint
  iteration to prevent tunneling with larger bodies
- Player: move_speed 0.3, jump_force 1.2 for bigger body
- Spawn: 6 cells above surface (was 4) for taller body
2026-06-20 21:27: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