Replace per-node ball enemies with BallSystem (packed data + MultiMesh) #77

Merged
cammymoop merged 1 commit from feature/ball-system into master 2026-03-05 13:54:06 -06:00
Collaborator

Summary

  • New BallSystem node manages all ball enemies as packed data arrays (no CharacterBody2D nodes). Physics simulation runs in a custom GDScript loop.
  • Rendering via one MultiMeshInstance2D per ball type, writing transforms and colors directly to multimesh.buffer each frame.
  • New BallTypeConfig resource captures all per-type parameters. Four types (standard, small, big, chain) configured in test_scene_1.tscn.
  • Bomb logic, chain bomb fuse timer, contact damage to player, and weapon melee detection handled inside BallSystem per physics frame.
  • apply_explosion() API includes can_bomb flag for future use.
  • WaveSpawner routes spawning through BallSystem.spawn_ball(); player emergency bomb routes through BallSystem.apply_explosion().
  • Explosion and shard nodes pre-allocated into pools (80/256) and recycled instead of instantiated per-event.

Test plan

  • godot4 --headless --quit-after 100 exits clean
  • gdlint passes on all modified/new files
  • Balls spawn, bounce off walls and rocks, visible via MultiMesh
  • Player melee arms standard balls into bomb mode; bomb detonates on contact with another ball
  • Big ball splits into 3 small balls on player melee
  • Chain bomb starts fuse when hit by explosion, detonates after delay
  • Shards drop on ball death and award currency on collection
  • Explosion effects return to pool after lifetime
## Summary - New `BallSystem` node manages all ball enemies as packed data arrays (no CharacterBody2D nodes). Physics simulation runs in a custom GDScript loop. - Rendering via one `MultiMeshInstance2D` per ball type, writing transforms and colors directly to `multimesh.buffer` each frame. - New `BallTypeConfig` resource captures all per-type parameters. Four types (standard, small, big, chain) configured in test_scene_1.tscn. - Bomb logic, chain bomb fuse timer, contact damage to player, and weapon melee detection handled inside BallSystem per physics frame. - `apply_explosion()` API includes `can_bomb` flag for future use. - WaveSpawner routes spawning through `BallSystem.spawn_ball()`; player emergency bomb routes through `BallSystem.apply_explosion()`. - Explosion and shard nodes pre-allocated into pools (80/256) and recycled instead of instantiated per-event. ## Test plan - [x] `godot4 --headless --quit-after 100` exits clean - [x] `gdlint` passes on all modified/new files - [ ] Balls spawn, bounce off walls and rocks, visible via MultiMesh - [ ] Player melee arms standard balls into bomb mode; bomb detonates on contact with another ball - [ ] Big ball splits into 3 small balls on player melee - [ ] Chain bomb starts fuse when hit by explosion, detonates after delay - [ ] Shards drop on ball death and award currency on collection - [ ] Explosion effects return to pool after lifetime
- New BallSystem (systems/ball_system.gd): manages all ball state in
  PackedArrays, simulates physics (integration, arena bounce, rock
  deflection, speed cap) without Godot's physics engine. Renders via
  one MultiMeshInstance2D per ball type, writing transforms/colors
  directly to the buffer each frame.
- New BallTypeConfig resource (systems/ball_type_config.gd): all
  per-type parameters (physics, appearance, explosion, behavior flags).
- Four types configured inline in test_scene_1.tscn: standard, small,
  big (splits on melee), chain (fuse-triggered by explosions).
- Bomb logic: bombed balls detect proximity to other balls each frame
  (O(bombs×all), fine for current scale); chain bombs start a fuse
  timer and self-explode after a short delay.
- Contact damage to player and melee detection (weapon range transition
  from out→in) handled inside BallSystem per physics frame.
- apply_explosion() API accepts can_bomb flag for future use.
- WaveSpawner now calls BallSystem.spawn_ball() instead of instantiating
  scenes. Finds BallSystem via 'ball_system' group on _ready().
- Player emergency bomb routes through BallSystem.apply_explosion().
- explosion_effect.gd gains effect_ended signal for pool support;
  falls back to queue_free when no pool listener connected.
- collectable.gd gains on_recycle Callable; BallSystem shard pool uses
  this to return shards on collect instead of queue_freeing them.
- Explosion and shard nodes are pre-allocated into pools (80 / 256
  default) and recycled to avoid per-death instantiation overhead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cammymoop merged commit a9938fb266 into master 2026-03-05 13:54:06 -06:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cammymoop/semi-vibed-game!77
No description provided.