Your First Game
In this guide you will create a spinning green triangle from scratch. You write the three pieces a YAGE game is built from: a component that holds the behaviour, an entity type that puts the triangle together, and a scene that spawns it. The finished example is under 50 lines of TypeScript.
The Full Code
Section titled “The Full Code”import { Component, Engine, Entity, Scene, Transform, Vec2 } from "@yagejs/core";import { GraphicsComponent, RendererPlugin, CameraEntity } from "@yagejs/renderer";import { DebugPlugin } from "@yagejs/debug";
class Spin extends Component { private readonly transform = this.sibling(Transform); private readonly speed: number; constructor(speed = 2) { super(); this.speed = speed; } update(dt: number): void { this.transform.rotate(this.speed * dt); }}
class Triangle extends Entity { setup(params: { position: Vec2 }): void { this.add(new Transform({ position: params.position })); this.add( new GraphicsComponent().draw((g) => { g.poly([0, -45, 40, 35, -40, 35]).fill({ color: 0x22c55e }); }), ); this.add(new Spin()); }}
class HelloWorldScene extends Scene { readonly name = "hello-world";
onEnter() { this.spawn(CameraEntity, { position: new Vec2(400, 300) }); this.spawn(Triangle, { position: new Vec2(400, 300) }); }}
const engine = new Engine({ debug: true });engine.use(new RendererPlugin({ width: 800, height: 600, backgroundColor: 0x0a0a0a,}));engine.use(new DebugPlugin());await engine.start();engine.scenes.push(new HelloWorldScene());Step-by-Step Walkthrough
Section titled “Step-by-Step Walkthrough”1. Imports
Section titled “1. Imports”import { Component, Engine, Entity, Scene, Transform, Vec2 } from "@yagejs/core";import { GraphicsComponent, RendererPlugin, CameraEntity } from "@yagejs/renderer";import { DebugPlugin } from "@yagejs/debug";Componentis the base class every custom behaviour extends.Engineis the entry point that orchestrates plugins and the game loop.Entityis the base class for entity types, such as the triangle.Sceneis the base class for defining game scenes.Transformstores an entity’s position, rotation, and scale.Vec2is a 2D vector used throughout the engine.GraphicsComponentdraws shapes via the PixiJS v8 graphics API.RendererPluginsets up the PixiJS v8 rendering pipeline.CameraEntityis the camera — spawn it in your scene. It exposesfollow(),shake(),zoomTo(),bounds, and more directly.DebugPluginenables the FPS counter, entity inspector, and dev overlays.
2. A Custom Component — Spin
Section titled “2. A Custom Component — Spin”class Spin extends Component { private readonly transform = this.sibling(Transform); private readonly speed: number; constructor(speed = 2) { super(); this.speed = speed; } update(dt: number): void { this.transform.rotate(this.speed * dt); }}Spin grabs its sibling Transform component and rotates it every frame.
The update(dt) method receives the delta time in seconds, so the triangle
turns 2 radians per second at any frame rate.
Game logic in YAGE lives in components like this one. Entities and scenes
have no update() method of their own.
3. An Entity Type — Triangle
Section titled “3. An Entity Type — Triangle”class Triangle extends Entity { setup(params: { position: Vec2 }): void { this.add(new Transform({ position: params.position })); this.add( new GraphicsComponent().draw((g) => { g.poly([0, -45, 40, 35, -40, 35]).fill({ color: 0x22c55e }); }), ); this.add(new Spin()); }}An entity is a container for components. Triangle extends Entity and
builds itself in setup(), which runs when a scene spawns it. The params
argument holds what the spawn call passes in, here the position.
setup() attaches three components to the entity:
Transform— places the triangle at the position fromparams.GraphicsComponent— draws a green triangle using three vertices defined as a flat[x, y, ...]array.Spin— the custom behaviour that rotates the triangle every frame.
Every Triangle you spawn gets the same three components.
4. Setting Up the Scene
Section titled “4. Setting Up the Scene”class HelloWorldScene extends Scene { readonly name = "hello-world";
onEnter() { this.spawn(CameraEntity, { position: new Vec2(400, 300) }); this.spawn(Triangle, { position: new Vec2(400, 300) }); }}HelloWorldScene extends Scene and implements onEnter(), which runs when
the scene becomes active. onEnter() spawns the entities the scene starts
with. The triangle’s behaviour stays in Spin, not in the scene.
this.spawn(CameraEntity, { ... }) creates the camera as an entity in the
scene. Setting the camera position to (400, 300) shifts the world origin to
the top-left corner of the default 800 × 600 viewport. The triangle is then
spawned at world position (400, 300) and lands in the middle of the screen.
By default the camera is at (0, 0) which puts world origin at the centre
of the viewport — see Camera → Coordinate Convention
in the Rendering guide for the full explanation.
5. Setting Up the Engine
Section titled “5. Setting Up the Engine”const engine = new Engine({ debug: true });engine.use(new RendererPlugin({ width: 800, height: 600, backgroundColor: 0x0a0a0a,}));engine.use(new DebugPlugin());await engine.start();engine.scenes.push(new HelloWorldScene());new Engine({ debug: true })creates the engine with debug mode enabled.engine.use()registers plugins — here the renderer and debug overlay.engine.start()initialises all plugins and starts the game loop.engine.scenes.push()pushes a scene onto the scene stack.
6. Spawning an Entity
Section titled “6. Spawning an Entity”this.spawn(Triangle, { position: new Vec2(400, 300) });this.spawn() creates an entity of the given class and passes the second
argument to its setup(). TypeScript checks that argument against the
setup() parameter, so a missing field is a compile error. The debug tools
list the entity under its class name, Triangle. CameraEntity is spawned
the same way: it is an entity type that @yagejs/renderer provides.
An entity that exists once and has no behaviour of its own, such as a
background, does not need a class. Pass spawn() a name instead, and add the
components to the entity it returns:
const background = this.spawn("background");background.add(new Transform());background.add( new GraphicsComponent().draw((g) => { g.rect(0, 0, 800, 600).fill({ color: 0x111827 }); }),);Anything you spawn more than once, or that has behaviour, is an entity class
like Triangle.
Running It
Section titled “Running It”Start your dev server (e.g. npx vite) and open the page in a browser. You
should see a green triangle spinning smoothly on a dark background with the
debug overlay in the corner.
Next Steps
Section titled “Next Steps”- Add keyboard input with
@yagejs/inputto control the triangle. - Swap the shape for a sprite using
SpriteComponentfrom@yagejs/renderer. - Read Entity Subclasses for more on entity
types and
setup(). - Read Project Structure to understand the full package layout.
Coding agents: fetch https://yage.dev/llms.txt first and prefer the Markdown references it links over these HTML pages. This page's Markdown counterpart is /llms/quick-start.md.