๐ŸŽฎ Retro Style, Modern Code, and Maximum Fun in 320×240 Pixels


๐Ÿ‘‹ Welcome, Pixel Warriors!

This blog post walks you through building a tiny but powerful Tower Defense (TD) game using only HTML, CSS, and JavaScript. No engines, no frameworks โ€” just pure retro-style coding magic. ๐Ÿง™โ€โ™‚๏ธโœจ

Weโ€™ll break down the full game system, based on our own Micro TD game โ€” a 320×240 canvas battlefield with enemies, towers, waves, and pixel projectiles. Think Game & Watch meets Command & Conquer.

Even if youโ€™re new to game development, this is a perfect starter project to learn how games tick, track, and explode! ๐Ÿ’ฅ


๐Ÿ”ง Step 1: Set Up the HTML Skeleton

We start with a simple HTML layout:

html

<div class="micro-td-wrapper">

<canvas id=“microTDCanvas” width=“320” height=“240”></canvas>

</div>

 

๐Ÿ“ Dev Notes:

  • Use <canvas> for low-level 2D drawing

  • Keep the resolution intentionally small (320×240) for that crunchy pixel aesthetic

  • Wrap the canvas in a styled <div> for borders, shop UI, and overlays

๐Ÿ“ฆ CSS adds polish:

css

.micro-td-wrapper {

border: 1px solid #333;

background: #000;

}

.micro-td-canvas {

background: #111;

image-rendering: pixelated;

}

 

๐Ÿง  Pro Tip: Use image-rendering: pixelated; to make things feel retro on modern screens.


๐ŸŽฏ Step 2: Design the Map and Pathfinding

Your battlefield is made of tiles:

js

const TILE_SIZE = 16;

const MAP_WIDTH = canvas.width / TILE_SIZE;

const MAP_HEIGHT = canvas.height / TILE_SIZE;

 

You manually define a path:

js

const path = [];

for (let y = 1; y < MAP_HEIGHT1; y++) {

map[y][5] = 1; // vertical path

path.push({ x: 5 * TILE_SIZE + TILE_SIZE/2, y: y * TILE_SIZE + TILE_SIZE/2 });

}

 

๐Ÿ‘ฃ What This Does:

  • Creates a fixed “enemy road”

  • Enemies follow the path tile by tile

  • You can later randomize or curve the path for challenge!


๐Ÿงฑ Step 3: Place Towers with Clicks

When the player clicks:

js

canvas.addEventListener('click', e => {

if (map[y][x] === 0 && gold >= TOWER_COST) {

towers.push({ x, y, cooldown: 0 });

gold -= TOWER_COST;

}

});

 

๐Ÿช› Add polish:

  • Prevent building on paths (map[y][x] !== 1)

  • Subtract gold when placing

  • Show tower info on hover with mousemove events

๐Ÿ’ก Try This: Add different tower types later with cooldowns, beam modes, or AoE damage.


๐Ÿ‘พ Step 4: Spawn Enemies with Waves

Each wave adds more enemies, with variety:

js

function spawnEnemy() {

if (wave % 10 === 0) spawnBoss();

else if (wave > 3 && Math.random() < fastChance) spawnFastEnemy();

else spawnNormalEnemy();

}

 

๐Ÿง  Balance Notes:

  • Bosses show up every 10 waves ๐Ÿ’€

  • Fast enemies dodge bullets, but can be โ€œslowedโ€

  • Each wave adds difficulty over time

๐Ÿ” Use a timer to delay the next wave, and show a โ€œWave Starting!โ€ message for extra drama!


๐Ÿน Step 5: Towers Shoot Automatically

Every frame, towers check for nearby enemies:

js

for (let tower of towers) {

if (enemyInRange) {

projectiles.push({ x, y, target, speed, damage });

tower.cooldown = 1;

}

}

 

๐Ÿ“ฆ Features to Try:

  • Cooldown timers so towers donโ€™t spam

  • Radius highlights

  • Tower upgrades (increase damage or range)

  • Add a beam tower with damage ramping ๐Ÿ”ฅ


๐Ÿ’ฃ Step 6: Projectiles and Damage

Bullets fly toward targets and hit when close:

js

if (dist < 4) {

target.hp -= damage;

p.hit = true;

}

 

๐Ÿน Extra Fun:

  • Add โ€œslowโ€ effects to fast enemies

  • Animate small explosions or color flashes

  • Show health bars above enemies

๐Ÿ“ˆ Game feel tip: Add a sound, screen shake, or popup for enemy kills!


๐ŸŒ€ Step 7: Game Loop

We use requestAnimationFrame():

js

function gameLoop(ts) {

const dt = (ts – last) / 1000;

update(dt);

draw();

requestAnimationFrame(gameLoop);

}

 

๐Ÿ”ง Maintain a stable FPS:

  • Time delta dt allows smooth animations

  • Towers, bullets, and enemies all tick at the same rate

  • Stop the loop if health <= 0 and display “GAME OVER” ๐ŸŽฎ


๐Ÿ›’ Add a Shop System (Optional)

You can style a little shop UI beside the canvas:

html

<div id="microTDShop">

<strong>Towers</strong><br>

Base Tower: Cost 30<br>

Damage: 0.8<br>

Radius: 48

</div>

 

โšก Upgrade Ideas:

  • Add โ€œBuy Beam Towerโ€ button

  • Show tower stats dynamically

  • Deduct gold when clicked


๐ŸŒŸ Bonus Ideas & Next Steps

Want to take this Micro TD to the next level? Here are some ideas:

๐Ÿง  Advanced Features:

  • Multiple tower types: Sniper, Beam, Splash

  • Procedural paths or map layouts

  • Dynamic difficulty scaling (enemy resistance, faster waves)

  • Sound FX (pew pew! ๐Ÿ’ฅ)

๐ŸŽจ Polish:

  • Pixel font + retro GUI

  • Background music and ambient jungle FX

  • Particle systems for projectiles and explosions

๐ŸŒ Deployment:

  • Export as a .zip or upload to itch.io

  • Embed into your personal portfolio site as a fun playable project


โœ… Summary

With just a few hundred lines of clean JavaScript, you’ve now got:

  • ๐Ÿงฑ A full grid-based map system

  • ๐Ÿ‘พ Enemies that path intelligently

  • ๐Ÿน Towers that shoot with range and timing

  • ๐Ÿ’ฅ Projectiles with collision and effects

  • ๐Ÿ” Endless waves, difficulty scaling, and juicy upgrades