Home · Architecture · Combat · Extensions · Known gaps · Source index
World and Entities
World ownership
World in src/world.rs is the single mutable root:
| Field group | Contents |
|---|---|
| Screen/progression | state, player |
| Actors/effects | singleton tower; vectors of enemies, projectiles, pools, animations |
| Content | weapon, enemy, damage, and status registries |
| Services | uniform grid, deterministic rng |
| Timing/space | now, wave_timer, arena |
| Identity | private monotonic next_id |
Entity IDs start at zero and increment on world spawning, animation commands, and replication. IDs are not reused. despawn searches both enemy and projectile vectors; pools and animations do not use that generic path.
Coordinate model
The arena data model is 800×800, while drawing offsets the arena by (50,50) in a 900×900 window. Tower constants place it at (450,450). Wall collision tests projectile coordinates against 0..800, and waves spawn at (0,400), while the visible arena border is 50..850.
This means simulation and rendering do not consistently share one coordinate space. The tower is visually central because its constants include the offset, but the logical arena center would be (400,400). Enemy movement also seeks (450,450). Treat this as a live coordinate mismatch, not an intentional camera transform.
Tower
Tower in src/tower.rs stores position, aim angle, cooldown, a HashMap<WeaponID,u32> loadout, unused tower mods, and hit/DoT DPS meters. It starts with Impact and Poison Coating at tier 1.
Weapon behaviors are not persistent objects on the tower. Every shot iterates (weapon ID, tier), asks WeaponRegistry for fresh boxed projectile behaviors, sorts them by priority, and attaches them to the projectile. A crate pick increments the selected ID's tier.
Enemy and corpse
Enemy in src/enemy.rs contains:
- Runtime identity, position, velocity, radius, HP/max HP, tier, and XP.
- Registry
EnemyID, death animation kind, draw function. - Damage resistance map keyed by
DamageID. - Status and enemy behavior trait-object vectors.
- Last lethal
Sourcefor attribution.
apply_damage computes each damage-kind contribution, applies damage × (1 - resistance), subtracts HP, and records the source when HP is no longer positive. Resistances are not clamped: values above 1 heal by producing negative damage, and negative resistance amplifies damage.
Corpse is a cheap snapshot used after death. It carries ID, position, kind, tier, XP, VFX kind, killer, radius, and overkill HP without retaining behavior objects.
Projectile
Projectile in src/world.rs has identity, position, velocity, birth/lifetime, source, radius, and ordered projectile behaviors. Cloning a projectile deep-clones every boxed behavior through object-safe clone glue. with_vel exists for shot shaping but is currently unwired because no live on_fire dispatch occurs.
Ground pool
GroundPool in src/pool.rs is position, radius, TTL, source, and a vector of pool behaviors. Constructors exist for acid and slow. Pools can be spawned directly or through commands, but are unwired at runtime: step_world never calls pool_pass, TTL is never decremented, no removal path exists, and the concrete acid/slow hooks do not apply effects.
Animation
Animation in src/animations.rs stores duration, elapsed time, position, a one-variant AnimationTypes, and ID. The only effect is the misspelled EnemeyDeathAnimation, rendered as a fading blue circle. Animations are assigned IDs when their spawn command applies and are removed after elapsed time reaches duration.
Player and screens
Player holds level, current XP, private next threshold, pending level_ups, and a PlayerStatus. XP thresholds use round(10 × 1.6^level) and can cross multiple levels in one grant.
| Screen/status | Meaning |
|---|---|
Screen::Playing |
Simulation and normal view; simulation also runs in the other screen |
Screen::WeaponCrate |
Three offered IDs and cursor |
PlayerStatus::None |
Crates may auto-open |
ManuallyClosed |
Suppresses automatic reopen; pending credits remain |
ToOpen |
Declared but never set or read meaningfully |
Picking spends one pending level-up and immediately rolls another crate if credits remain. Closing spends nothing. Pressing Space while playing calls the guarded open method.
Not an ECS
Although hecs appears in Cargo.toml, no source module imports it. Entity lookup is linear by ID, vector retention handles removal, and the spatial grid accelerates enemy proximity/collision queries only.
Home · Architecture · Combat · Extensions · Known gaps · Source index