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
e287b0d22a
feat: larger detailed entities — 47 parts, hats, belts, ears
...
Entities are now ~3x larger and more detailed:
Player (47 parts, was 15):
- Hat: 3 top + 2 brim (dark purple)
- Head: 3x2 face (lavender skin)
- Belt: golden accent across torso
- Shirt: 3x2 torso + arms out to 3 cells each side
- Hands: 4 cells (2 per arm, pale lavender)
- Pants: 3 wide hips + 5 wide legs + split
- Boots: 3 cells + 2 foot tips (dark purple)
- half_w=4, half_h=6 (was 2.5x3.5)
Goblin (41 parts):
- Pointed ears (2 cells)
- Ragged shirt (green, darker shade)
- Bare feet (green skin, no boots)
- Loincloth (dark green)
Auto-constraints: all parts connected to all others (n^2)
- Simplified from manual constraint lists
- Works for any template shape
- Ragdoll will look natural — all parts hold together
macro_rules! p! for compact part definitions
117 tests, 0 failures
2026-06-21 10:34:28 +03:00
Emil
6504a619f6
feat: profile-view humanoid entities, purple player in clothes
...
Redesigned entity as side-profile silhouette (Noita-style):
O head (skin tone)
|
-|- shoulders with arms out
|
-|- arms lower
|
/|\ hips, legs split
/| boot boot boot
15 bodies (was 23), narrower profile shape:
- head: 2 cells (skin)
- torso: 3 cells (shirt/clothing color)
- arms: 4 cells (hands, 2 per side)
- hips: 1 cell (pants)
- legs: 3 cells (pants)
- boots: 3 cells
Player color scheme (purple wizard):
- skin: pale lavender (220,200,240)
- shirt: purple (140,80,200)
- pants: dark purple (90,50,150)
- boots: dark (60,35,100)
- hands: pale lavender (210,185,235)
Goblin: green skin, dark green rags
Corpse: desaturated grey-brown
109 tests, 0 failures
2026-06-21 10:20:09 +03:00
Emil
5cd1a5e197
feat: Noita-style humanoid entities with per-part colors
...
Redesigned entity from solid 5x5 block to humanoid silhouette:
Shape (23 bodies, was 27):
H H H (head, 3 wide)
H H H
A T T T A (shoulders + arms, 5 wide)
A T T T A
T T T (torso, 3 wide)
L R (legs, split with gap)
L R
Per-part colors (Noita-inspired):
- Player: head=bright yellow, torso=golden, arms=amber, legs=dark gold
- Goblin: head=bright green, torso=green, arms=olive, legs=dark green
- Corpse: desaturated browns
SubBody now has color: [u8; 4] field, set by build_humanoid.
All renderers (terminal, ascii, graphics) use b.color directly.
Fire effect: flickering orange overlay on burning entities.
half_w adjusted from 3.5 to 3.0, half_h from 2.5 to 3.5
(taller shape, narrower than old block).
109 tests, 0 failures
2026-06-21 10:13:22 +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
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