Gå videre til hovedindholdet

Building Swarm Entropy: From Rock-Paper-Scissors to Neon Auto-Battler

 

Building Swarm Entropy:

From Rock-Paper-Scissors to Neon Auto-Battler



What started as a simple coding experiment quickly spiraled into absolute neon chaos.

I set out to build a simple rock-paper-scissors simulation in a single HTML file: Leaf beats Water, Water beats Fire, Fire beats Leaf. Throw 60 units onto an HTML5 Canvas, make them chase each other, and see who wins.

But as the engine took shape, the scope exploded. I introduced flocking algorithms, rigid-body physics, class-based combat (Snipers, Healers, Shields), environmental hazards like wormholes, and game-breaking powers.

The result is Swarm Entropy: a zero-dependency, vanilla JavaScript auto-battler. Here is a look at how the game plays, and a deep dive into the custom engine running under the hood.



The Game: Chaos on the Grid

In Swarm Entropy, you don't directly control your units. You act as a commander: you pick your army, draft a game-breaking power, and release them onto the grid.

The battles are broken into two phases:

  1. Rallying: Units scramble to find their allies, forming tight defensive clusters.

  2. Battle: The gloves come off. Predators hunt their prey, while the prey frantically scatter.

To prevent infinite loops of units just chasing each other in circles, the arena is rigged with hazards. Mud pits slow units to a crawl, Wormholes teleport them across the map, and every few seconds, a massive Lightning Strike instantly vaporizes a random unit.

If a battle goes on long enough that only two armies remain, the game enters Sudden Death. The Rock-Paper-Scissors rules break down, and the "Prey" turns around to fight back, dealing 50% damage to their natural predators. It makes for some incredible underdog victories!



Under the Hood: Building the Engine

Writing a game engine from scratch in a single file means you have to get creative with performance and physics. Here are the three pillars that make Swarm Entropy tick.



1. Swarm Intelligence (Boids Algorithm)

The units don't use complex pathfinding like A*. Instead, they rely on steering behaviors inspired by Craig Reynolds' "Boids" algorithm. Every frame, each unit calculates its velocity based on three simple desires:

  • Cohesion: Move toward the center of mass of nearby allies.

  • Separation: Don't bump into your friends.

  • Flee/Steer: Run away from predators, charge toward prey.

By blending these forces together, the units organically form formations, kite enemies, and execute flanking maneuvers without any hard-coded logic.

JavaScript
// A simplified look at the steering logic
function steer(targetX, targetY, weight) {
  const dx = targetX - u.x;
  const dy = targetY - u.y;
  const dist = Math.hypot(dx, dy);
  
  if (dist < 0.5) return; // Prevent division by zero
  
  // Add weighted velocity towards the target
  fx += (dx / dist) * weight; 
  fy += (dy / dist) * weight;
}

// Snipers want to stay exactly at optimal firing range
const diff = currentDistance - optimalDistance;
if (diff > 0) {
    steer(enemy.x, enemy.y, 2.5); // Move closer
} else {
    flee(enemy.x, enemy.y, 3.2); // Too close! Back up!
}

2. The "Black Hole" Bug & Mass-Based Physics

Early in development, I noticed a game-breaking bug: The Fire Army was losing 90% of its matches, regardless of what powers were used.

It turned out to be a physics flaw. When resolving collisions, my knockback math was blindly pushing Unit A away from Unit B. But because of the way the arrays were structured, Fire units were accidentally getting pushed into their enemies instead of bouncing off them. They were getting sucked into a continuous-damage black hole!

To fix this, I rewrote the collision resolution to calculate kinetic knockback based on overlapping radii and physical mass. This not only fixed the bug but allowed me to introduce Juggernauts—massive units with 15x the mass that send standard units flying across the screen like bowling pins.

JavaScript
// Calculating overlap between two colliding circles
const overlap = (radA + radB) - dist;

if (overlap > 0) {
  const nx = dx / dist; // Normal vector X
  const ny = dy / dist; // Normal vector Y
  
  // Calculate relative mass
  const totalMass = massA + massB;
  const push = KNOCKBACK_FORCE * (overlap / (radA + radB));
  
  // Apply proportional momentum to both units
  a.vx -= nx * push * (massB / totalMass); 
  a.vy -= ny * push * (massB / totalMass);
  b.vx += nx * push * (massA / totalMass); 
  b.vy += ny * push * (massA / totalMass);
}



3. Zero-Cost Permanent Splatter (The Off-Screen Canvas)

I wanted the battlefield to feel the impact of the war. When a unit dies, it leaves a permanent, glowing neon splatter on the ground. However, telling the HTML Canvas to draw 500+ individual splatters 60 times a second would instantly tank the browser's framerate.

The solution? An off-screen canvas.

I created a secondary canvas that never gets added to the DOM. When a unit dies, I paint the splatter onto that invisible canvas exactly once. Then, in the main render loop, I just take a single "photograph" of that off-screen canvas and draw it as the background.

JavaScript
// 1. Setup an invisible canvas in memory
let splatterCanvas = document.createElement('canvas');
let splatterCtx = splatterCanvas.getContext('2d');

// 2. Draw to it ONLY when someone dies
function addSplatter(x, y, color) {
  splatterCtx.beginPath();
  splatterCtx.arc(x, y, radius, 0, Math.PI * 2);
  splatterCtx.fillStyle = color;
  splatterCtx.fill();
}

// 3. In the main 60FPS loop, just draw the cached image once!
function render() {
  ctx.fillRect(0, 0, width, height); // Draw dark background
  ctx.drawImage(splatterCanvas, 0, 0); // Draw the permanent splatter layer
  // ... draw living units on top
}


Conclusion

Building Swarm Entropy was an incredible exercise in managing complexity within a single file. Watching the Boids algorithms interact with the class mechanics (like Shields intercepting predators while Healers cower in the back) creates genuinely emergent storytelling.

It proves you don't always need a massive game engine like Unity or Godot to build something chaotic, beautiful, and deeply fun. Sometimes, all you need is a <canvas> tag, a lot of math and a Pro Subscription to Google Gemini - that helped immensely with creation of this game ;) 

[ LINK TO THE SWARM ENTROPY - https://marcdahl.dk/swarm.html ]

Kommentarer

Populære opslag fra denne blog

Bound in Ash and Bone: Unearthing 'The Ghouls Almanac'

I am thrilled to finally unveil my latest passion project: The Ghouls Almanac: A Grim Chronicle of the Wasteland . Created with the help of my loving wife and son  —with dark, intricate illustrations conjured alongside Google Gemini —this isn't just an art book. It is a forbidden scripture of the atomic age, written in the style of a post-apocalyptic Necronomicon . If you are a fan of the Fallout universe, you know the stories. But you have never seen them told like this. The Ghouls Almanac is a visceral, mythic retelling of the events of Fallout 1 , Fallout 2 , and Fallout 3 , chronicled by the one soul who lived to see it all: Harold . Before he became the Oasis—a living cathedral of timber and vine —he was the ancient wanderer who witnessed the fall of the Master and the flight of the Enclave . Through Harold's rotting, immortal eyes, the history of the wasteland is documented not as a sci-fi adventure, but as a dark, twisted gospel of flesh, steel, and survival: The Iron ...

A Peek Behind the Scenes of the Wasteland: Download the Unique Fallout Story 'The Stranger Is Not Real'

Have you ever wondered who the man in the trench coat really is? Every time you're in a pinch in Fallout, he appears out of the blue, fires his .44 Magnum, and vanishes into thin air. But where does he go? And what does he actually think about the bizarre things you do in the wasteland? Now you have the chance to find out. In the recently released, fan-made book "The Stranger Is Not Real," we have created a completely unique and entertaining take on the Fallout universe. And the best part? You can download it right now. A Noir Diary from the Edge of Reality "The Stranger Is Not Real" is a brilliant deconstruction of video game logic, told as a hardboiled and cynical noir detective story. We follow the game's most iconic guardian angel—The Mysterious Stranger—through his personal, worn-out logbook entries. Through a series of "cases," our tired narrator slowly begins to realize that he is stuck in an absurd, digital loop. He is forced by a humming i...

The Mythical 1-50: Reclaiming a Missing Piece of 90s Eastern European Childhood

If you grew up in Eastern Europe or a post-Soviet state in the 1990s, you don’t need me to explain what a piece of Turbo gum meant. It wasn't just chewing gum. In a world still shaking off the grayness of the Soviet era, that bright yellow, rock-hard piece of chemical-smelling taffy was a brick of condensed, Western exoticism. But let’s be honest: no one bought it for the gum. We bought it for the treasure hidden inside. We bought it for the wrappers (or "vkladyshi / вкладыши," if you will). The Gateway to a World of Horsepower For us, those wrappers were our first encyclopedias of automotive desire. In a reality where the roads were dominated by Ladas, Zhigulis, and the occasional aging Volga, Turbo wrappers offered us a vibrant, full-color portal to a magical world of Ferraris, Lamborghinis, and Porsches. We didn't just collect them. We traded them, gambled them in playground games involving vigorous hand-slapping, and tacked them to our bedroom walls. We memorized ...