aboutsummaryrefslogtreecommitdiffstats
path: root/requirements
diff options
context:
space:
mode:
authorVaino Kauppila <vaino@vke.fi>2026-07-02 22:58:25 +0300
committerVaino Kauppila <vaino@vke.fi>2026-07-02 23:47:07 +0300
commitcd0c08dc7ce754473178ad3f32f7740a1dddc1eb (patch)
tree589c676b41d6f3d322ea5ce339ddb0811f29ec31 /requirements
downloadforts_clone-cd0c08dc7ce754473178ad3f32f7740a1dddc1eb.tar.gz
forts_clone-cd0c08dc7ce754473178ad3f32f7740a1dddc1eb.zip
Initial import: LibreForts (M0-M5 in progress)
Open-source Forts clone: custom C++20 engine + data-driven (Lua) 2D physics artillery RTS. - Building: node/strut graph on a stiff mass-spring solver (canon Forts model), triangulation rigidity, axial + 30-degree angle-stress breaking, cascading collapse, fire (DoT + spread), ground destroys debris. - Weapons (M4): cannon (ballistic) + laser (beam/ignite) with select-and-aim-in- arc UX; splash / beam damage; bg-brace passthrough. - Devices + economy (M5): reactors + win/loss + restart, mines/turbines/battery, metal deposits, storage caps, per-shot energy cost. - Data-driven via Lua/sol2 with a layered mod loader; enemy-fort scenario mod. - Renderer: SDL3 + textures + ImGui dev UI. stb_image + ImGui vendored. - Assets: CC0 placeholders only; real game art loaded at runtime from the user's own install via forts: paths (bring-your-own; nothing copyrighted committed). See README.md / CLAUDE.md and research/ + requirements/ for detail.
Diffstat (limited to 'requirements')
-rw-r--r--requirements/milestones.org186
-rw-r--r--requirements/v0.1-core.org338
2 files changed, 524 insertions, 0 deletions
diff --git a/requirements/milestones.org b/requirements/milestones.org
new file mode 100644
index 0000000..9aa5a5a
--- /dev/null
+++ b/requirements/milestones.org
@@ -0,0 +1,186 @@
+#+TITLE: Forts Clone v0.1 -- Milestones
+#+AUTHOR: Forts Clone Project
+#+DATE: 2025-06-19
+#+OPTIONS: toc:3 num:t
+
+* Overview
+
+v0.1 is split into 7 milestones. Each milestone delivers something you can
+run and test. Milestones are sequential -- each builds on the previous.
+
+* M0: Scaffolding & Build Environment [DONE]
+SCHEDULED: <2025-06-19>
+CLOSED: <2025-06-19>
+
+Goal: Container builds, SDL3 window opens, clears to a color.
+
+- [X] Containerfile with all dependencies pre-built
+- [X] meson.build at project root, compiles and links SDL3 + Box2D + all deps
+- [X] =src/main.cpp= -- SDL3 creates a window, clears to dark blue-gray
+- [X] Camera: 2D orthographic, pan (arrows/middle-drag), zoom (scroll)
+- [X] Input system: polling keyboard/mouse state
+- [X] Podman build + run workflow
+
+Notes:
+- Pivoted from bgfx to SDL3 renderer for M0. bgfx init fails silently on this
+ system (EGL-only Linux backend, GLX removed upstream). SDL3 OpenGL renderer
+ works perfectly. Revisit bgfx later in the project.
+- Header collision: -I/usr/local/include/bx caused sys/types.h to find
+ bx/endian.h instead of glibc endian.h. Fixed by using single
+ -I/usr/local/include with qualified <bx/...> includes.
+
+* M1: Rendering & Physics Foundations [DONE]
+SCHEDULED: <2025-06-19>
+CLOSED: <2025-06-19>
+
+Goal: See physics bodies rendered as colored rectangles against terrain.
+
+- [X] Box2D v3 integration -- world, gravity, fixed timestep at 60Hz
+- [X] Static terrain body (ground plane + platform)
+- [X] Dynamic bodies falling and landing (proof of physics->render)
+- [X] SDL3 sprite rendering (colored quads, world-to-screen transform)
+- [X] Fixed-timestep accumulator pattern (physics at 60Hz, render at display rate)
+- [X] Camera pan/zoom with proper defaults (zoom 10, centered on action)
+
+Notes:
+- Box2D v3.0.0 has broken CMake (FetchContent pulls GLFW unconditionally).
+ Built from v3.1.1 directly (gcc -c src/*.c + ar rcs).
+- b2ShapeDef.friction moved to b2ShapeDef.material.friction in v3.
+- b2Rot is { float c, s; } (cos/sin), angle via std::atan2(rot.s, rot.c).
+
+* ARCHITECTURE NOTE: Building physics is a mass-spring system (the canon Forts model)
+
+The locked stack specified Box2D (weld/distance joints, b2DestructionListener)
+for the building structure. Instead the building system is a custom *stiff
+damped mass-spring solver* (=src/game/build_graph.*=) — the same model the
+shipped game uses (see =research/forts-data-reference.org=). It maps directly
+onto Forts' node/edge graph and onto its data.
+
+- Node = point mass with velocity; foundation nodes are pinned at the ground.
+- Strut = a damped Hookean spring (F = k.dx + c.v), per-material stiffness.
+ Integrated semi-implicit with OVERSAMPLES (14) substeps for stiff-spring
+ stability (Forts uses the same oversampling).
+- Rigidity is GEOMETRIC (triangulation); a lone strut is a free-hinging pin
+ joint. It SNAPS on (a) axial deformation past per-material MaxCompression/
+ MaxExpansion, or (b) the 30-degree angle-stress rule for un-triangulated
+ struts — both taken from the shipped game's constants.
+- Box2D is retained (=src/engine/physics.*=) but idle; foundation for M4
+ projectiles / terrain collision.
+
+Consequence: multiplayer determinism now rests on our own solver, not Box2D's
+cross-platform guarantees (revisit before netcode work).
+
+* LUA / MODDING: materials are now data-driven (sol2) [DONE for materials]
+
+Lua (sol2 3.5) is up. Materials are no longer hard-coded — they load at startup
+from =data/materials.lua= via =load_materials()= (=src/game/data.*=), into a
+runtime =BuildGraph::materials= vector. The layered loader works:
+
+1. =ScriptEngine= (=src/engine/script.*=) wraps a sol2 state, runs files with
+ errors caught (a bad mod can't crash the game).
+2. Base =data/materials.lua= defines the global =Materials= array + helpers
+ (=FindMaterial=, =IndexOfMaterial=).
+3. Every mod under =data/mods/<name>/= with a =materials.lua= is applied on top
+ in (Priority, name) order; mods mutate the shared =Materials= table.
+ (=data/mods/example-recolour-wood/= ships as a live demo.)
+
+Runtime data path is relative to CWD (run from the repo root). NEXT for Lua:
+extend the same loader to weapons/devices/projectiles tables (lands with M4),
+and a mod-selection step instead of "apply everything in data/mods/".
+
+* M2: Building System [MOSTLY DONE]
+
+Goal: Click to place struts on the map. They have physics, connect into a
+graph, and form structures.
+
+- [X] Build mode: number keys 1-3 select material (wood / bg-brace / rope)
+- [X] Strut placed as a mass-spring node/edge + colored quad, stress-tinted
+ (red under compression, blue under tension)
+- [X] Anchored building only: a drag must START from an existing node or the
+ ground (foundation) — no growing structure out of thin air
+- [X] Click-drag single strut; endpoints snap onto existing nodes
+- [X] Drag-build (extrude): sweep an edge into a box with node-merging and an
+ auto diagonal brace; free (non-perpendicular) drag angle
+- [X] Build-grace radial timer on un-triangulated struts (temporary rigid hold)
+- [X] Building costs: placing a piece deducts metal + energy
+- [X] Simple HUD: resource bars + current-material indicator
+- [ ] Resource system: Metal (mines on deposits) + Energy (wind turbines)
+ -- DEFERRED to M5 (needs the reactor / game-loop context). For now metal
+ and energy are fixed starting pools that only deplete.
+
+* M3: Structural Destruction [MOSTLY DONE]
+ (swapped with weapons -- destruction goes hand-in-hand with M2 building)
+
+Goal: Overloaded structures snap and collapse; debris that falls is destroyed.
+This is the purely-structural half of Forts destruction (no weapons yet).
+
+- [X] Axial failure: deformation past per-material MaxCompression/MaxExpansion
+ (wood +/-10%, asymmetric per material) — canon, read straight off the
+ spring length (not a reconstructed force)
+- [X] Angle-stress failure: an un-triangulated strut snaps once it rotates past
+ ~30 deg from its built angle (Forts' rule; replaces the old dangle timer)
+- [X] Cascading collapse: a snapped support redistributes load and overloads
+ neighbours, which snap in turn (emergent, not a scripted event)
+- [X] Ground destroys falling debris: any non-foundation node that sinks below
+ the ground surface is removed (+ explosion puff), taking its edges with it
+- [X] Disconnection -> fall -> destroy: a chunk that loses its path to a
+ foundation simply falls under gravity and dies on the ground
+- [X] Materials: wood, background bracing, ropes (tension-only)
+- [ ] Per-strut HP pool (separate from stress) -- belongs with M4 weapon damage
+- [ ] Fire (damage-over-time, strut-to-strut spread) -- M4
+
+* M4: Weapons & Damage
+ (swapped with destruction)
+
+Goal: Place and fire all three weapons. They feed the M3 graph via two damage
+models (per-strut HP and radius splash) plus fire.
+
+- [ ] Per-strut HP pool, depleted by weapon hits (independent of stress)
+- [ ] Cannon: click-drag angle/power, Box2D ballistic projectile, splash
+ damage with linear radius falloff, knockback impulse, ~25% fire chance
+- [ ] Laser: click-drag beam; stops at wood, passes bg-brace/ropes; 100% ignite
+- [ ] Flak: auto-target incoming shells within an arc; hitscan/fast projectile
+- [ ] Direct vs splash delivery: foreground struts block direct fire;
+ background bracing is passed through by direct hits but takes splash + fire
+- [ ] Fire system: ignition flag, damage-over-time, spread along the graph,
+ burns background bracing faster (the counter to the bg-brace trick)
+
+* M5: Reactor, Resources & Game Loop
+
+Goal: There's a reactor to destroy, and a real economy to build it with.
+
+- [ ] Reactor entity -- large block, HP bar
+- [ ] Player reactor on left, dummy reactor on right
+- [ ] Reactor takes damage from direct hits, fire, falling/collision
+- [ ] Win condition: destroy reactor HP OR disconnect it from its foundation
+ (collapse) -- two distinct victory paths
+- [ ] Resource system (deferred from M2): mines on metal deposits, wind
+ turbines for energy, generation rates, "can't build when broke"
+- [ ] Win/lose condition + restart (R key)
+
+* M6: Dummy Fort & Map
+
+Goal: The dummy fort on the right is a hand-crafted target. The map has metal
+deposits and a complete layout.
+
+- [ ] Dummy fort pre-built structure (reactor, wood walls, bg-brace, ropes)
+- [ ] Map layout: terrain with metal deposits on both sides
+- [ ] Player starting area: reactor + small starter shell + nearby deposits
+- [ ] Visual polish: distinct colors for materials, simple sky backdrop
+
+* M7: Polish & Controls
+
+Goal: Everything feels good. Controls are responsive. Visuals are clear.
+
+- [ ] Repair tool: right-click damaged piece, pay resources to restore HP
+- [ ] Recycle: shift+click to remove piece, recover partial resources
+- [X] Camera feel: pan (arrows / middle-drag), scroll zoom (basic; edge-scroll TBD)
+- [ ] Visual feedback: damage states, fire glow
+- [X] Build UX: ghost/extrusion previews, hover highlights, build-grace timers
+- [ ] Edge cases: zero resources enforcement, etc.
+
+* Dependency Graph
+
+#+begin_src text
+M0 -- M1 -- M2 -- M3 -- M4 -- M5 -- M6 -- M7
+#+end_src
diff --git a/requirements/v0.1-core.org b/requirements/v0.1-core.org
new file mode 100644
index 0000000..ce3d99c
--- /dev/null
+++ b/requirements/v0.1-core.org
@@ -0,0 +1,338 @@
+#+TITLE: Forts Clone v0.1 — Core Requirements
+#+AUTHOR: Forts Clone Project
+#+DATE: 2025-06-19
+#+OPTIONS: toc:3 num:t
+
+* Purpose
+
+v0.1 exists to prove the core loop: build a fort, place weapons, and destroy
+an enemy reactor through physics-based structural damage. No multiplayer.
+No AI. No commanders. Just the fundamental building↔physics↔destruction
+feedback loop working end-to-end.
+
+* Resources
+
+Two resources only. No tech tree — everything is available from the start.
+
+** Metal
+- Gathered via Mines placed on metal deposits in the terrain
+- Deposits are fixed nodes on the map — a mine on a deposit produces metal at
+ a constant rate
+- Metal is consumed when placing building pieces and weapons
+- If you run out of metal, you cannot build
+
+** Energy
+- Generated by Wind Turbines placed on your fort
+- Turbine output scales with:
+ - Height above terrain (higher = more energy)
+ - Lack of obstruction around the turbine (clear air = more energy)
+- Energy is consumed when placing building pieces and weapons
+- If you run out of energy, you cannot build
+
+* Building Materials
+
+** Wood (Normal Bracing)
+- Primary structural building material
+- Opaque: projectiles CANNOT pass through it
+- Guns cannot shoot through wood bracing — it blocks line of fire for both
+ the player and hypothetically for enemies
+- Has HP — takes damage from cannon shells, lasers, and fire
+- Flammable: can be set on fire by laser or cannon (chance-based)
+- When HP reaches zero, the piece is destroyed
+- When a load-bearing piece is destroyed, connected pieces may collapse
+ (Box2D joint destruction → cascade)
+- Costs: metal + energy (exact values TBD during implementation)
+- Appears as a solid plank/beam visually
+
+** Background Bracing
+- Structural building material — provides support just like wood
+- Translucent/façade: structures behind it are visually hidden from the
+ opponent (in v0.1, this is mostly cosmetic since there is no opponent)
+- Projectiles pass THROUGH background bracing — it does NOT block shots
+- Guns CAN shoot through background bracing (it doesn't block line of fire)
+- Has HP — takes damage from cannon shells and lasers
+- Flammable: fire-spreading weapons (laser, cannon) set fire to it
+- When HP reaches zero, the piece is destroyed
+- When destroyed, any structures it was hiding become visible
+- Costs: metal + energy (likely cheaper than wood since it doesn't block
+ projectiles — TBD)
+- Appears as a visually distinct, lighter/more transparent plank
+
+** Ropes
+- Tension element connecting two points
+- Provides structural stability — keeps structures from tipping over
+- Does NOT block projectiles (they pass through ropes)
+- Has HP (low compared to wood)
+- Vulnerable to: fire (can burn through), cannon splash damage
+- If a rope is destroyed, the structure it was stabilizing may collapse
+ (tension is released → connected bodies may fall)
+- Implemented via Box2D =b2DistanceJoint=
+- Costs: metal + energy (cheap per segment — ropes are primarily for
+ structural engineering, not defense)
+- Appears as a thin line/cable visually
+
+** Material Property Summary
+
+| Property | Wood Bracing | Background Bracing | Ropes |
+|-----------------------+--------------+-------------------+-------------|
+| Blocks projectiles | ✅ Yes | ❌ No | ❌ No |
+| Blocks line of fire | ✅ Yes | ❌ No | ❌ No |
+| Provides structure | ✅ Yes | ✅ Yes | ✅ Tension |
+| Flammable | ✅ Yes | ✅ Yes | ✅ Yes |
+| HP (relative) | High | Medium | Low |
+| Hides structures | ❌ No | ✅ Yes | ❌ No |
+
+* Weapons
+
+** Cannon (Artillery)
+- Type: arcing projectile (affected by gravity)
+- Aiming: player sets angle and power, fires on click
+- Projectile: cannon shell with ballistic trajectory
+ - Travels in an arc (Box2D body under gravity)
+ - On impact: deals damage in a small splash radius
+ - Knockback: applies force to bodies near impact point
+ - Structural damage: can break joints near impact
+- Chance to set fire: ~20-30% chance on impact to ignite the struck piece
+ (fire then spreads to connected flammable materials)
+- Firing rate: slow (e.g., 1 round per 2-3 seconds)
+- Good against: structures, wooden walls
+- Counter: Flak gun can shoot down cannon shells in flight
+- Costs: metal + energy to build the cannon device on your fort
+
+** Flak Gun
+- Type: point-defense, hitscan or very fast projectile
+- Aiming: automatic or manual? (TBD — auto-targeting incoming projectiles in
+ a cone/radius, or player aims at incoming shells)
+- Purpose: shoots down incoming cannon shells before they impact
+- Cannot damage buildings (or does very little building damage)
+- Firing rate: moderate/high (needs to be able to intercept cannon shells)
+- Placement matters: must have line of sight to incoming projectiles
+ (cannot shoot through wood bracing, CAN shoot through background bracing
+ and ropes)
+- Costs: metal + energy to build
+
+** Laser
+- Type: Line-of-Sight beam weapon
+- Aiming: player draws a line from the laser turret to target point
+- The beam traces through:
+ - Empty space: passes freely
+ - Background bracing: passes through (doesn't block)
+ - Ropes: passes through
+ - Wood bracing: blocked — beam stops at first wood piece hit
+- Damage: low continuous damage to whatever piece it hits (or low damage
+ per tick while beam is active)
+- Fire starter: 100% chance to set the struck piece on fire (if flammable)
+ — this is the laser's primary purpose
+- Beam duration: fires for a short burst (e.g., 0.5-1 second) then goes on
+ cooldown
+- Cannot penetrate normal wood — the beam stops at the first wood surface
+- Good against: starting fires in enemy structures, burning through ropes
+ and background bracing, igniting key support pieces
+- Costs: metal + energy to build
+
+** Weapon Summary
+
+| Weapon | Damage | Fire? | Blocks Projectiles? | Penetrates Bg. Bracing? |
+|----------+--------+-------+---------------------+--------------------------|
+| Cannon | High | ~25% | Flak can intercept | Yes (arcing shot) |
+| Flak Gun | Low | No | N/A (defensive) | Yes (hitscan within arc) |
+| Laser | Low | 100% | N/A (stops at wood) | Yes (beam passes through)|
+
+* Reactor
+
+- The win/loss condition for both the player and the dummy fort
+- A large, relatively fragile device placed at the core of each fort
+- Has HP — when HP reaches zero, that side loses
+- Can be damaged by:
+ - Direct cannon shell hits
+ - Fire reaching the reactor (spread from burning connected pieces)
+ - Falling/collision damage if the reactor's supports are destroyed and
+ it falls
+- Player's reactor starts at a fixed position on the left side of the map
+- Dummy reactor starts at a fixed position on the right side of the map
+- Visually distinct — glows, pulses, or is marked clearly
+- Costs: free (starts pre-placed on the map)
+
+* Fire System
+
+- Fire starts when:
+ - Laser hits a flammable piece (100% ignition chance)
+ - Cannon shell impacts a flammable piece (~20-30% ignition chance)
+- Once ignited, a piece burns:
+ - Takes damage over time (HP decreases per tick)
+ - Fire spreads to adjacent connected flammable pieces (via Box2D joint
+ graph — check neighboring bodies)
+ - Burning pieces produce visual fire particles and smoke
+ - Ropes burn faster than wood (lower HP, fire kills them quickly)
+- Fire does NOT spread through empty space — only along joint connections
+ between flammable bodies
+- A piece destroyed by fire releases its joints, potentially causing
+ structural collapse
+- Fire can reach and damage the reactor if connected through flammable
+ structure
+- Extinguish? Not in v0.1 — once something is burning, it burns until
+ destroyed. (Future: repair tool extinguishes fire.)
+
+* Physics
+
+- Box2D v3 simulation at fixed timestep (60Hz)
+- Every building piece (wood, background bracing) is a =b2Body= (dynamic)
+- Terrain/map geometry is =b2Body= (static)
+- Joints:
+ - Weld joints connect adjacent building pieces (rigid attachment)
+ - Distance joints represent ropes (maintain fixed distance between two
+ anchor points)
+- Gravity: standard downward gravity (~9.8 m/s² in world units)
+- Projectiles: dynamic =b2Body= with initial velocity, affected by gravity
+- Impact forces: cannon shells apply =b2Body::ApplyLinearImpulse= to nearby
+ bodies on detonation
+- Joint breaking: when a body is destroyed (HP reaches zero), its attached
+ joints are destroyed → connected bodies may fall
+- =b2DestructionListener= triggers game-side logic (spawn debris particles,
+ mark connected bodies for stability check, fire spread check)
+- Structural collapse emerges naturally from the physics — if enough
+ supports are destroyed, structures fall
+
+* Map
+
+** Layout
+- 2D side-view
+- Fixed-size playfield (e.g., 200m wide × 100m tall in world units)
+- Left side: player's starting area
+ - Player reactor pre-placed at a fixed position
+ - Small starter structure around the reactor (a few wood planks forming
+ a basic shell)
+ - 2-3 metal deposits near the player's side
+- Right side: dummy enemy fort
+ - Dummy reactor pre-placed at a fixed position
+ - Pre-built fort structure around the reactor (wood bracing walls, some
+ background bracing panels hiding the reactor, a few rope supports)
+ - Intended as a target to shoot at — the dummy has enough structure to
+ demonstrate the physics/destruction/fire systems
+ - 2-3 metal deposits near the enemy side
+- Terrain: simple ground plane with some unevenness/hills
+- Metal deposits: visible ore nodes embedded in terrain
+
+** Visual Style
+- Simple, functional — colored rectangles/sprites for building pieces
+- Distinct colors for: wood (brown), background bracing (lighter brown/
+ beige, semi-transparent), ropes (dark line), metal deposits (gray/silver),
+ reactor (glowing red/orange)
+- Sky/gradient background (simple)
+- This is v0.1 — programmer art is fine. Aesthetics can wait.
+
+* Game Mode: Target Practice (v0.1)
+
+** Setup
+- Single player on the left side
+- Dummy fort on the right side (pre-built, no AI, no player controlling it)
+- The dummy does NOT: build, shoot back, repair, or take any action
+- The dummy fort is a static structure — it just sits there
+
+** Player Actions
+- Build: place wood, background bracing, and ropes on your fort
+ - Drag to place beams/planks (TBD: exact building UX)
+ - Click points to connect ropes
+- Place weapons: build cannon, flak gun, and laser on your fort
+ - Weapons are placed like building pieces but have an aim direction
+- Aim & Fire:
+ - Cannon: click and drag to set angle/power, release to fire
+ - Laser: click and drag to draw beam path, fires along line
+ - Flak gun: active passively? Or player aims at incoming shells?
+ (TBD — simplest v0.1 approach: flak automatically shoots at cannon
+ shells within its arc/range)
+- Manage resources: build mines on deposits, build wind turbines for energy
+- Repair: damaged structures can be repaired for a resource cost
+ (TBD: repair tool or automatic?)
+
+** Win Condition
+- Destroy the dummy reactor
+ - Reduce its HP to zero via direct hits, fire, or structural collapse
+
+** Lose Condition
+- Your own reactor is destroyed
+ - In v0.1 with no enemy AI, this can only happen if you damage your own
+ reactor (unlikely) or your fort collapses onto it (possible if built
+ poorly)
+
+** No Win/Lose Condition (Stretch)
+- The game simply continues — there's no victory screen yet. When a reactor
+ dies, it explodes/dissolves visually. Press R to restart.
+
+* Camera & Controls
+
+** Camera
+- 2D orthographic projection via bgfx
+- Camera pans with mouse (drag middle-mouse or scroll to edge)
+- Zoom with scroll wheel (zoom in/out to see details or full battlefield)
+- Default view: centered on the map, showing both forts
+
+** Controls (Mouse + Keyboard)
+| Action | Input |
+|-------------------+------------------------------|
+| Pan camera | Middle-mouse drag or arrow keys |
+| Zoom | Scroll wheel |
+| Select build mode | Number keys (1=wood, 2=bg.brace, 3=rope, 4=cannon, 5=flak, 6=laser) |
+| Place piece | Click (in build mode) |
+| Cancel build | Right-click or Escape |
+| Aim weapon | Click (in weapon mode) |
+| Fire weapon | Release after aim, or click |
+| Repair | Right-click on damaged piece |
+| Recycle/delete | Shift+click on piece |
+| Restart | R key |
+
+* What is Explicitly OUT of Scope for v0.1
+
+- Multiplayer (no networking needed)
+- AI opponents (dummy fort is entirely passive)
+- Commanders
+- Tech tree
+- Damage types beyond fire + kinetic (no EMP, no shields)
+- Particle effects beyond basic fire/smoke
+- Sound (can be added but not required — focus on gameplay)
+- UI beyond basic resource counters and build mode indicators
+- Save/load
+- Replays
+- Mod loading (Lua infrastructure can be in engine but no mods to load yet)
+- Menu system (just drop into the game on launch)
+- Win/loss screens (reactor explodes, press R to restart)
+
+* Development Priorities (Build Order)
+
+1. Windowing + rendering (SDL3 + bgfx — get a triangle on screen)
+2. 2D sprite batcher on bgfx (colored quads for building pieces)
+3. Box2D world + basic bodies (static terrain, dynamic plank)
+4. Build mode: click to place a plank (creates Box2D body + renders sprite)
+5. Resource system (mines, turbines, metal/energy counters)
+6. Multiple connected pieces (weld joints, structural integrity)
+7. Ropes (distance joints, tension visualization)
+8. Cannon + projectile physics (spawn shell, ballistic arc, impact)
+9. Flak gun (shoot down cannon shells)
+10. Laser (line trace, fire ignition)
+11. Fire system (HP-over-time, spread along joints, visual feedback)
+12. Reactor + win/loss check
+13. Dummy fort (pre-built target structure on the right side)
+14. Camera (pan, zoom)
+15. Repair + recycle
+16. Polish pass (visual clarity, controls feel, edge cases)
+
+* Open Design Questions (Resolve During Implementation)
+
+- [ ] Building UX: drag-to-place beams? Click start + end points? Grid snap
+ or freeform?
+- [ ] Cannon aiming: click on your cannon + click target point? Or angle/
+ power slider?
+- [ ] Flak gun behavior: fully automatic within an arc? Or player manually
+ targets incoming shells?
+- [ ] Laser duration: continuous beam while holding click? Or fixed-duration
+ burst?
+- [ ] Resource rates: how much metal per mine per second? How much energy per
+ turbine? (Tune during playtesting)
+- [ ] Piece HP values: how many cannon hits to destroy wood? Background
+ bracing? Ropes?
+- [ ] Building piece sizes: fixed sizes (1m, 2m, 4m beams)? Or freeform drag?
+- [ ] Does fire spread upward preferentially? (Heat rises — fire climbing up
+ a structure is more dangerous than fire going down)
+- [ ] Can you build pieces that intersect? Or is placement blocked by existing
+ bodies?
+- [ ] Repair cost: proportional to missing HP? Flat cost?