See it running
The short version
- Built solo in Godot 4.6 over ~3 months — a skill-based tower defense where you ARE the weapon.
- Drag-to-aim combat: every shot has weight and a real trajectory, not auto-fired towers.
- Economy loop makes every action a sink — spending coins on arrows vs. saving is the core tension.
- Signal-decoupled HUD: removing a node never crashes the game; enemies share one enemy_base.
- Honest gap: all enemies still use a placeholder sprite — art hurts first impressions more than systems.
- Live and playable on itch.io.
What it does
- Drag-to-aim combat, feel the weight of every throw
- 9 enemy types: Grunt, Knight, Runner, Shield Bearer, Archer, Bomber, Healer, Splitter, Giant
- 5 unlockable weapons: Rock, Bow, Knife, Axe, Spear, each with unique physics
- Economy-driven ammo: every arrow costs coins, tension between spending and saving
- 15 scaling waves, wave events (Double Coins / Armored / Fast), hold-to-buy upgrades
The thought
What if tower defense rewarded player skill instead of tower placement? In Obsidio you manually aim and fire every projectile, so the arc, the weight, and the cost of each shot matter. The fantasy is simple: you are the weapon, not a manager watching a battlefield.
Mechanics
You don't place towers, you are the tower. Drag to aim a projectile, watch the dotted trajectory preview, then release to fire. Five weapons, each with its own physics: the Rock bounces freely, the Bow costs coins and eases into its draw, and the Knife, Axe, and Spear are direct throws. Fire Arrows (unlockable) add a burn damage-over-time effect. Enemies are introduced gradually and each behaves differently: Shield Bearers block frontal hits (forcing arc shots), Healers buff nearby allies, Splitters divide on death, and Giants take three wall hits.
Systems
The run is a 15-wave campaign. Break times shrink as you progress (15s → 5s), spawns are weighted-random with per-type caps, and groups enter in staggered waves (frontline → mid → back → vanguard). An economy loop drives the tension: kills and wave clears pay coins, and everything is a sink, wall repair, upgrades, arrows, weapon unlocks. You are always choosing whether to spend now or save for later. After wave 9, wave events kick in (Double Coins / Armored / Fast). Best wave, kills, and bonus arrows are saved via ConfigFile, and a seed system is already wired for a future daily-challenge mode.
Under the hood
I kept the codebase decoupled so a feature can be ripped out without taking the game down. The HUD is pure signals, buttons.gd owns all HUD logic and emits typed events (upgrade_wall_pressed, buy_arrow_pressed, button_hover_changed) that main.gd and player.gd subscribe to, so removing a node never crashes the game. Three autoloads carry the infrastructure: global_var (game state, economy constants, seeds, save/load), PersistentScene (circular-wipe transitions), and ObjectPool (recycles projectiles and coins to avoid spawn spikes). Enemies share an enemy_base.gd, movement, attack state machine, death pipeline, armor, coin drops, health bars, and override behavior per type. Projectiles extend ProjectileBase, adding Line2D trails, ground-sticking, hit-stop (Engine.time_scale = 0 for 0.05s), and pooled damage numbers.
Controls
How it came together
Prototype
First drag-to-aim throw in Godot, a single bouncing rock and a dummy target. The "you are the weapon" fantasy clicked.
Core combat
Enemy base state machine, trajectory preview, and the 5-weapon physics set. Hit-stop and pooled damage numbers landed feel.
Economy loop
Coins as a universal sink, arrows, upgrades, wall repair. Constant spend-vs-save tension replaced free firing.
Campaign & waves
15-wave curve, weighted spawn groups, and wave events (Double Coins / Armored / Fast) after wave 9.
Polish & ship
Signal-architected HUD, ConfigFile save/load, circular-wipe transitions. Shipped live on itch.io with an active devlog.
What I would do differently
Next up: unique enemy sprites to replace the current placeholders, boss waves at 5/10/15, and a meta-progression campsite between runs. The presentation-layer split (UI and audio as siblings of the game world) is the pattern I would carry into every future project.