1
0
Fork 0
Code Issues Pull requests Projects Releases Packages Wiki Activity Actions Pages
Docs/topology of systems.html
2026-06-29 12:59:15 -04:00

216 lines
No EOL
9.1 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Infinite Web Game Engine - Architecture Manual</title>
<style>
:root {
--bg-color: #f4f4f9;
--text-color: #333;
--sidebar-bg: #2c3e50;
--sidebar-text: #ecf0f1;
--link-color: #3498db;
--code-bg: #e2e2e8;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
background-color: var(--bg-color);
color: var(--text-color);
line-height: 1.6;
}
/* Sidebar Styles */
nav {
width: 280px;
background-color: var(--sidebar-bg);
color: var(--sidebar-text);
height: 100vh;
position: fixed;
overflow-y: auto;
padding: 20px;
box-sizing: border-box;
}
nav h2 {
margin-top: 0;
font-size: 1.2rem;
border-bottom: 1px solid #455a64;
padding-bottom: 10px;
}
nav ul {
list-style: none;
padding: 0;
}
nav ul li {
margin-bottom: 10px;
}
nav ul li a {
color: var(--sidebar-text);
text-decoration: none;
font-size: 0.95rem;
display: block;
padding: 5px;
border-radius: 4px;
transition: background 0.2s;
}
nav ul li a:hover {
background-color: #34495e;
}
/* Main Content Styles */
main {
margin-left: 280px;
padding: 40px;
max-width: 900px;
box-sizing: border-box;
}
section {
margin-bottom: 50px;
background: #fff;
padding: 30px;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
}
h1 {
border-bottom: 2px solid var(--link-color);
padding-bottom: 10px;
margin-top: 0;
}
h2 {
color: #2c3e50;
margin-top: 0;
}
h3 {
color: #34495e;
}
code {
background-color: var(--code-bg);
padding: 2px 5px;
border-radius: 4px;
font-family: "Courier New", Courier, monospace;
font-size: 0.9em;
}
pre {
background-color: #2d2d2d;
color: #ccc;
padding: 15px;
border-radius: 6px;
overflow-x: auto;
}
pre code {
background-color: transparent;
color: inherit;
padding: 0;
}
</style>
</head>
<body>
<nav>
<h2>Engine Manual</h2>
<ul>
<li><a href="#overview">1. Overview & Separation of Concerns</a></li>
<li><a href="#tech-stack">2. Tech Stack</a></li>
<li><a href="#ecs">3. Entity-Component-System (ECS)</a></li>
<li><a href="#world-chunks">4. Infinite World & Chunk Management</a></li>
<li><a href="#plugins">5. The "Pop-In" Plugin System</a></li>
<li><a href="#react-pixi-bridge">6. React & PixiJS Bridge</a></li>
</ul>
</nav>
<main>
<h1>Infinite Web Game Engine Architecture</h1>
<p>A comprehensive guide to building a modular, data-driven 2D game engine designed for infinite, chunk-based worlds using HTML5, JavaScript, React, and PixiJS.</p>
<section id="overview">
<h2>1. Overview & Separation of Concerns</h2>
<p>To keep the engine scalable and highly modular, the architecture relies on strict separation between three core pillars:</p>
<ul>
<li><strong>The Core Engine (PixiJS):</strong> The bedrock. Handles rendering, math, and the Entity-Component-System (ECS). It is entirely agnostic to game logic and only knows about raw data.</li>
<li><strong>The Editor (React):</strong> A specialized UI layer that sits on top of the engine. Its primary job is <em>Serialization</em>—allowing visual arrangement of resources and saving them as JSON data.</li>
<li><strong>The Runtime (Game):</strong> The lightweight entry point. It boots the Engine, parses the JSON data exported by the Editor, and executes the game loop.</li>
</ul>
</section>
<section id="tech-stack">
<h2>2. Tech Stack</h2>
<p>The chosen technologies leverage the speed of WebGL and the dynamic nature of JavaScript:</p>
<ul>
<li><strong>Rendering & Viewport:</strong> <code>PixiJS</code> (Handles the core canvas game loop and batching)</li>
<li><strong>Editor UI:</strong> <code>React</code> (Manages the complex state of the editor interface, scene graphs, and asset browsers)</li>
<li><strong>Modularity:</strong> Native ES Modules (<code>import()</code>)</li>
<li><strong>Data & Serialization:</strong> standard JSON</li>
</ul>
</section>
<section id="ecs">
<h2>3. Entity-Component-System (ECS) & Memory</h2>
<p>To avoid JavaScript Garbage Collection (GC) stutters, the engine uses a <strong>Data-Oriented Design</strong>.</p>
<ul>
<li><strong>Entities:</strong> Plain integer IDs (e.g., <code>Entity 45</code>).</li>
<li><strong>Components:</strong> Stored in flat TypedArrays (like <code>Float32Array</code>) rather than standard JS objects. This keeps memory contiguous and blazing fast for the CPU.</li>
<li><strong>Systems:</strong> Functions that iterate over these flat arrays to update game state.</li>
</ul>
</section>
<section id="world-chunks">
<h2>4. Infinite World & Chunk Management</h2>
<p>The world is based on a 32x32 infinite grid. Because you cannot hold an infinite world in memory, data is dynamically loaded and unloaded.</p>
<h3>Chunk Storage Map</h3>
<p>World data is stored in a JavaScript <code>Map</code> using a string coordinate hash as the key. This allows the world to expand infinitely in any direction, including negative coordinates.</p>
<pre><code>// Example hash key format: "chunkX,chunkY" -> "-1,4"
const chunkMap = new Map();
function getChunkKey(worldX, worldY) {
const chunkX = Math.floor(worldX / (32 * 32));
const chunkY = Math.floor(worldY / (32 * 32));
return `${chunkX},${chunkY}`;
}
</code></pre>
<h3>Rendering Object Pool</h3>
<p>To maintain performance, PixiJS objects are never created or destroyed on the fly. The engine uses an <strong>Object Pool</strong>.</p>
<ol>
<li>Pre-allocate enough Pixi <code>Container</code> objects to cover the screen plus a buffer.</li>
<li>When a chunk leaves the screen, clear its children, return the container to the pool, and save its raw tile data to the <code>chunkMap</code>.</li>
<li>When a new chunk enters, grab an idle container from the pool and populate it with sprites.</li>
</ol>
</section>
<section id="plugins">
<h2>5. The "Pop-In" Plugin System</h2>
<p>Libraries (like procedural generation or specialized AI) can simply be dropped into a folder and instantly recognized.</p>
<p>This is achieved using native ES Dynamic Imports. Plugins hook into the engine's <strong>Event Bus</strong> and chunk lifecycles.</p>
<h3>Example: Procedural Generation Hook</h3>
<pre><code>// plugins/BiomeGenerator.js
export const plugin = {
id: "procedural-biomes",
init(engine) {
// Hook into the core engine's chunk creation event
engine.chunks.on('chunk_created', (chunk) => {
this.generateTerrain(chunk);
});
},
generateTerrain(chunk) {
// Populate the 32x32 grid with noise data
}
};
</code></pre>
</section>
<section id="react-pixi-bridge">
<h2>6. React & PixiJS Communication Bridge</h2>
<p>React (State) and PixiJS (Render Loop) must remain strictly decoupled to protect performance.</p>
<p>They communicate entirely via a lightweight <strong>Event Bus</strong> or <strong>Command Pattern</strong>:</p>
<ul>
<li><strong>React to PixiJS:</strong> React emits events based on user input. For example, selecting a tile in the editor emits <code>EDITOR_BRUSH_CHANGED</code>. The Pixi loop listens and updates its internal placement state.</li>
<li><strong>PixiJS to React:</strong> Pixi emits throttled state events. For example, as the camera pans, it emits <code>CAMERA_MOVED</code>. React listens to this and updates the coordinate UI in the sidebar without re-rendering the game canvas.</li>
</ul>
</section>
</main>
</body>
</html>