Quick Start
Let’s create a simple game that displays a moving sprite. This will introduce you to the core concepts of ESEngine.
Create a New Project
-
Create your project directory
Terminal window mkdir my-gamecd my-gamenpm init -y -
Install dependencies
Terminal window npm install esenginenpm install -D esbuild typescript -
Create src/main.ts
import {type ESEngineModule,createWebApp,defineSystem,Schedule,Commands,Query,Res,Time,LocalTransform,Sprite,Camera} from 'esengine';export async function main(Module: ESEngineModule): Promise<void> {const app = createWebApp(Module);// Startup system - runs once at the beginningapp.addSystemToSchedule(Schedule.Startup, defineSystem([Commands()],(cmds) => {// Create cameracmds.spawn().insert(Camera, {projectionType: 1,orthoSize: 400,isActive: true}).insert(LocalTransform, {position: { x: 0, y: 0, z: 10 }});// Create a spritecmds.spawn().insert(Sprite, {color: { x: 1, y: 0.5, z: 0.2, w: 1 },size: { x: 100, y: 100 }}).insert(LocalTransform, {position: { x: 0, y: 0, z: 0 }});}));// Update system - runs every frameapp.addSystemToSchedule(Schedule.Update, defineSystem([Res(Time), Query(LocalTransform, Sprite)],(time, query) => {for (const [entity, transform, sprite] of query) {// Move sprite in a circletransform.position.x = Math.sin(time.elapsed) * 100;transform.position.y = Math.cos(time.elapsed) * 100;}}));app.run();} -
Add build script to package.json
{"scripts": {"build": "esbuild src/main.ts --bundle --format=esm --outfile=build/main.js"}} -
Build your game
Terminal window npm run build
Understanding the Code
App and Systems
ESEngine uses a system-based architecture. Systems are functions that run at specific points in the game loop:
// Create the app with WASM moduleconst app = createWebApp(Module);
// Add a system to a scheduleapp.addSystemToSchedule(Schedule.Update, defineSystem( [/* parameters */], (/* injected params */) => { // Game logic here }));
// Start the game loopapp.run();Schedule Types
| Schedule | When it runs |
|---|---|
Startup | Once at the beginning |
Update | Every frame |
PostUpdate | After Update, every frame |
FixedUpdate | At fixed time intervals |
System Parameters
Systems declare what data they need, and it gets injected automatically:
defineSystem( [Commands(), Res(Time), Query(LocalTransform, Sprite)], (cmds, time, query) => { // cmds: spawn/despawn entities // time: elapsed time, delta time // query: iterate entities with components })Components
Components are data attached to entities. ESEngine provides builtin components:
| Component | Description |
|---|---|
LocalTransform | Position, rotation, scale |
Sprite | 2D sprite rendering |
Camera | Camera settings |
Velocity | Movement velocity |
Creating Entities
Use Commands to spawn entities and attach components:
cmds.spawn() .insert(Sprite, { color: { x: 1, y: 0, z: 0, w: 1 } }) .insert(LocalTransform, { position: { x: 100, y: 100, z: 0 } }) .id(); // Returns the entity IDQuerying Entities
Use Query to iterate entities with specific components:
for (const [entity, transform, sprite] of query) { transform.position.x += 1;}