This is a Godot 4 + GDScript prototype for a lane-based “守城自动战斗” experience. It focuses on data-driven gameplay, fast iteration, and zero-art placeholders (simple shapes + text UI). The code aims to stay readable so you can extend or rebalance the system quickly.
- Open the folder in Godot 4.x.
- Make sure
main.tscnis the startup scene (also configured inproject.godot). - Press Play.
That is enough to simulate all 10 waves including the boss wave and upgrade flow.
- Enemies spawn 800 units away from the wall and advance at 30 units/s for melee (20 for archers) so you get more breathing room.
- The battlefield is split into 20 narrow lanes, so projectiles and enemies are visually separated.
- Every wave lasts 20 seconds; after waves 1–9 you receive a 3-choice upgrade dialog. Selecting an option instantly resumes the game and starts the next wave.
- Wave 10 adds the boss. Victory triggers when all waves are cleared and no enemies remain. Defeat triggers if the wall HP (starts at 1000) reaches 0.
- The UI header shows wall HP, current wave, and status. Upgrade cards are text-buttons; results (victory/defeat) surface via a center label.
- General: Fires arrows every 0.5s from the center lane. Upgrades: +pierce, +multishot (0.8x damage per additional arrow), or +damage (1.6x).
- Ice Mage: Unlocked via upgrade. Fires once every 5s; shards freeze on hit (1s). Upgrades: +pierce (0.8x damage) or add an AoE freeze radius (+50 per upgrade).
- Fire Mage: Unlocked via upgrade. Fires once every 4.2s; hits trigger a point explosion (target takes full damage, nearby units take 50%). Upgrades: +damage (1.6x) or +radius (+50).
- Lightning Mage: Unlocked via upgrade. Strikes nearest targets every 2s (prefers distinct targets). Upgrades: +targets (0.8x damage) or +damage (1.6x).
- Rolling Boulders: Disabled by default; unlock via upgrade to start spawning every 4s. Roll up lanes, hitting enemies with a 0.2s reuse cooldown per target. Upgrades: +damage (1.6x) or +count (+1 boulder, each 0.8x damage).
Damage scaling uses the rule base_damage * 0.8^penalty_stacks * 1.6^bonus_stacks automatically.
data/config.json holds everything relevant:
world: timing, lane geometry, spawn distance, wall HP.waves: enemy count progression and composition rules (archer/brute unlocks + boss wave).enemies: HP, speed, attack profile per enemy archetype.towers: fire rates, damage, projectiles, freeze radius, etc.projectiles: visual radius/colors (currently only used for drawing hints).upgrades: the pool handed to the upgrade UI.
Alter values here to rebalance without touching scripts. For example, change wave_interval, tweak individual enemy HP, or add new upgrades. Scripts read the file at startup and adapt automatically.
- Scene graph:
Main (Node2D)→ scriptGameManager.- Child containers for Enemies, Projectiles, Effects, Boulders, Towers.
Spawnerhandles timed enemy/boulder creation.UpgradeSystempicks upgrade cards;UIRootrenders text UI & buttons (pause-mode safe during upgrade selection).
- Order of operations each frame:
- Towers/projectiles/boulders deal damage.
- Dead enemies are removed.
- Survivors advance / attack the wall (respecting freeze & attack cadence).
- Wall HP updates; victory/defeat checks run last.
- Projectiles and boulders are lightweight pooled nodes; no physics bodies are used—just manual math and simple collision checks.
- Shapes are drawn with
_draw()to keep the asset footprint zero.
- Run the game and observe waves spawn every ~20s.
- Confirm archers stop ~200 units from the wall and shoot.
- Trigger an upgrade and verify the choice immediately modifies behavior (e.g., General multishot visibly adds arrows and reduces per-arrow damage).
- Let enemies hit the wall to ensure wall HP UI updates and defeat triggers at 0.
- Clear all waves, including the boss, to validate the victory message.
- Adjust a few
config.jsonvalues (e.g., wave counts, damage numbers) and reload to confirm changes apply.
- Hook up SFX/VFX or replace primitive drawings with art assets.
- Add save/load for upgrade selections or meta-progression.
- Expand enemy/tower rosters by extending existing base classes.