Files
another-boids-in-rust/www/index.html
Robert Garrett 6329d000f5
All checks were successful
check / stable / fmt (push) Successful in 21s
check / nightly / doc (push) Successful in 2m24s
check / ubuntu / stable / features (push) Successful in 2m27s
check / ubuntu / 1.87.0 (push) Successful in 2m18s
Use compressed WASM for even smaller webroot size
2025-11-15 15:14:20 -06:00

128 lines
4.1 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
background-color: hsl(100, 10%, 60%);
color: hsl(0, 0%, 15%);
}
h1 {
background-color: rgb(72, 97, 72);
text-align: center;
margin: auto;
padding: 0.5em;
}
canvas {
margin-top: 1em;
margin-left: auto;
margin-right: auto;
display: block;
outline-color: hsl(100, 100%, 15%);
outline-style: outset;
border-radius: 8px;
background-color: rgb(40%, 40%, 40%);
}
main {
margin-left: auto;
margin-right: auto;
width: 70%;
}
table {
margin-bottom: 10px;
border-collapse: collapse;
}
th, td {
border: 1px solid;
padding: 0.1em 0.3em;
}
</style>
</head>
<body style="margin: 0px;">
<h1>
Another Boids in Rust
</h1>
<canvas id="boids-canvas" width="1280" height="720"></canvas>
<main>
<article>
<h2>Description</h2>
<p>
This is my implementation of the Boids flocking algorithm. It is written in Rust, built on the Bevy game engine, and compiled to WASM to run in the browser.
</p>
<p>
The algorithm consists of just 3 rules:
<ul>
<li><strong>Separation</strong> - Boids steer apart to avoid colliding.</li>
<li><strong>Alignment</strong> - Boids fly in the same direction as their neighbors.</li>
<li><strong>Cohesion</strong> - Boids clump together so as not to fly off alone.</li>
</ul>
From these rules, the flocking behavior emerges naturally.
</p>
<p>
My version of this program has some extra rules governing speed. In short: things below some threshold are sped
up, and things above are slowed down. This is to keep an appropriate amount of kinetic energy in the system.
Since the boids start in a circle with the same speed, the sum of all velocity vectors is <code>vec2(0, 0)</code>.
Technically, floating-point rounding errors would likely mean the system always has some energy, but never
enough for an interesting simulation.
</p>
</article>
<article>
<h3>Controls</h3>
<table>
<thead>
<tr>
<th scope="col">Input</th>
<th scope="col">Effect</th>
</tr>
</thead>
<tr>
<td>Mouse</td>
<td>The scanner circle is attached to the mouse cursor. Move it to scan boids within the radius.</td>
</tr>
<tr>
<td>Left mouse button</td>
<td>Put scanner into center-of-mass mode</td>
</tr>
<tr>
<td>Right mouse button</td>
<td>Put scanner into average velocity mode. (There's a window focus bug. This button doesn't work quite right!)</td>
</tr>
</table>
</article>
<article>
<h3>Misc</h3>
<table>
<tr>
<td>Source code</td>
<td><a href=https://github.com/DerVerrater/another-boids-in-rust>https://github.com/DerVerrater/another-boids-in-rust</a></td>
</tr>
<tr>
<td>License</td>
<td><a href="https://www.gnu.org/licenses/agpl-3.0.txt">AGPL-3.0-only</a></td>
</tr>
<tr>
<td>Program Version</td>
<!-- This version text is completely unchecked. I'll need to do something about that. -->
<td><code>v0.5.0</code></td>
</tr>
</table>
</article>
</main>
<script type="module">
import init from './boids.js'
let compressed = await fetch("./boids_bg.wasm.gz")
let wasm_stream = compressed.body.pipeThrough(new DecompressionStream("gzip"))
let blob = await new Response(wasm_stream).blob();
init(await blob.arrayBuffer()).catch((error) => {
if (!error.message.startsWith("Using exceptions for control flow, don't mind me. This isn't actually an error!")) {
throw error;
}
});
</script>
</body>
</html>