Source Code
src/pages/projects/ecosim.rs
use leptos::*;
use leptos_meta::{Meta, Title};
use super::data::ALL_PROJECTS;
#[component]
pub fn Ecosim() -> impl IntoView {
let project = ALL_PROJECTS
.iter()
.find(|p| p.slug == "ecosim")
.unwrap();
let skills_view = project
.skills
.iter()
.map(|&s| view! { <li>{s}</li> })
.collect::<Vec<_>>();
view! {
<Title text="Ecosim – Peter Pinto"/>
<Meta name="description" content="A planet-scale ecosystem simulator built on Bevy, with procedural generation, hierarchical simulation, and a deterministic multiplayer architecture."/>
<div class="page">
<span class="eyebrow">"Projects"</span>
<h1>"Eco" <em style="font-style:italic; color: var(--accent)">"sim"</em></h1>
<p class="lead">
"A planet-scale ecosystem simulator. The goal: model populations of plants, animals,
and microorganisms from global climate patterns down to individual organism behaviour —
and let players intervene at any level."
</p>
<ul class="skills-list" style="margin-top: 1.5rem;">
{skills_view}
</ul>
<hr class="divider"/>
// ── Vision ────────────────────────────────────────────
<section class="project-section">
<span class="eyebrow">"Concept"</span>
<h2>"What It Is"</h2>
<p>
"Ecosim is the umbrella application that ties together a set of purpose-built
libraries — procedural planet generation, orbital camera, GPU shaders, and
input binding — into a single runnable game. The simulation is designed
around several gameplay modes:"
</p>
<ol class="project-steps">
<li>
<strong>"Plague Inc-style"</strong>
" — control an invasive species and spread it across the globe"
</li>
<li>
<strong>"From Scratch"</strong>
" — seed a barren planet and guide an ecosystem to stability"
</li>
<li>
<strong>"Competitive"</strong>
" — race another player to accumulate the most biomass"
</li>
</ol>
</section>
<hr class="divider"/>
// ── Architecture ──────────────────────────────────────
<section class="project-section">
<span class="eyebrow">"Architecture"</span>
<h2>"Bevy ECS"</h2>
<p>
"The application is built on "
<a href="https://bevyengine.org" target="_blank" rel="noopener noreferrer" class="prose-link">"Bevy 0.18"</a>
", a data-driven game engine based on an Entity Component System. Game state
is managed through a type-safe state machine: a top-level "
<code class="inline-code">"AppState"</code>
" (Startup → MainMenu → InGame → Shutdown) with a nested "
<code class="inline-code">"GameState"</code>
" (Playing ↔ Paused). Invalid transitions are unrepresentable by design —
you cannot call "
<code class="inline-code">"pause()"</code>
" unless the game is already in the Playing sub-state."
</p>
</section>
<hr class="divider"/>
// ── Determinism ───────────────────────────────────────
<section class="project-section">
<span class="eyebrow">"Design Principle"</span>
<h2>"Determinism First"</h2>
<p>
"Every subsystem is designed to be a pure function of its inputs, with all
randomness fed through seeded RNGs. This makes multiplayer possible without a
dedicated authoritative server — both clients run the same simulation, and
a single binary serves as either a peer or a headless dedicated server
depending on startup flags."
</p>
<p style="margin-top: 1rem;">
"A "
<code class="inline-code">"DETERMINISM_ANALYSIS.md"</code>
" file lives at the root of the simulation crate, tracking every known
source of nondeterminism (Bevy query order, floating-point variance,
HashMap iteration) and the mitigation applied to each."
</p>
</section>
<hr class="divider"/>
// ── Build ─────────────────────────────────────────────
<section class="project-section">
<span class="eyebrow">"Build"</span>
<h2>"Targets & Profiles"</h2>
<p>
"The dev profile uses the Cranelift codegen backend for near-instant
recompilation, with dependencies compiled by LLVM so hot-reload stays
fast without sacrificing dependency performance. The release profile
enables full LTO and codegen-unit merging for maximum runtime speed.
A dedicated WASM release profile strips debug info and optimises for
binary size, targeting deployment in the browser via "
<code class="inline-code">"wasm-bindgen"</code>
"."
</p>
</section>
<hr class="divider"/>
// ── Status ────────────────────────────────────────────
<section class="project-section">
<span class="eyebrow">"Status"</span>
<h2>"Foundation Complete"</h2>
<p>
"The underlying libraries — procedural planet generation, camera, input binding,
and GPU shaders — are all functional. The game application has a working state
machine, plugin architecture, and build pipeline. The next phase is writing the
gameplay systems that connect them, building on a solid, tested foundation
rather than prototyping and rewriting later."
</p>
</section>
</div>
}
}