Skip to content

Installation

Prerequisites

  • Node.js and npm (or your preferred package manager)
  • TypeScript knowledge -- SAGE is written in TypeScript and expects you to use it
  • A bundler like Vite (recommended), Webpack, or similar

Install Packages

SAGE requires BabylonJS, its loaders, and Havok as peer dependencies. @skewedaspect/sage-core is a dependency of @skewedaspect/sage, and game code that augments the event map or uses the provided behaviors imports from it directly:

bash
npm install @skewedaspect/sage @skewedaspect/sage-core @babylonjs/core @babylonjs/havok @babylonjs/loaders

If you are building a Vue application, also install the Vue integration package:

bash
npm install @skewedaspect/sage-vue

TypeScript Configuration

Make sure your tsconfig.json includes these settings:

json
{
    "compilerOptions": {
        "target": "ES2023",
        "module": "ESNext",
        "moduleResolution": "bundler",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "lib": ["ESNext", "DOM", "DOM.Iterable"]
    }
}

Quick Start: Spinning Cube

The fastest way to verify your setup is to get a cube on screen and spinning. This uses SAGE's createGameEngine() factory and BabylonJS directly for scene setup.

HTML

Create an index.html with a full-viewport canvas:

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SAGE - Hello Cube</title>
    <style>
        html, body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }
        #gameCanvas {
            width: 100%;
            height: 100%;
            touch-action: none;
        }
    </style>
</head>
<body>
    <canvas id="gameCanvas"></canvas>
    <script type="module" src="./src/main.ts"></script>
</body>
</html>

Game Code

Create src/main.ts:

typescript
import { createGameEngine } from '@skewedaspect/sage';
import {
    ArcRotateCamera,
    Color3,
    Color4,
    HemisphericLight,
    MeshBuilder,
    StandardMaterial,
    Vector3,
} from '@babylonjs/core';

async function main() : Promise<void>
{
    const canvas = document.getElementById('gameCanvas') as HTMLCanvasElement;

    // Create the engine. The second argument is the entity class table; this demo spawns nothing.
    const engine = await createGameEngine(canvas, {});

    // Create a scene
    const scene = engine.engines.sceneEngine.createScene();
    scene.clearColor = new Color4(0.12, 0.12, 0.14, 1);

    // Camera
    const camera = new ArcRotateCamera(
        'camera',
        Math.PI / 4,
        Math.PI / 3,
        5,
        Vector3.Zero(),
        scene
    );
    camera.attachControl(canvas, true);

    // Light
    new HemisphericLight('light', new Vector3(0, 1, 0), scene).intensity = 0.8;

    // Cube
    const cube = MeshBuilder.CreateBox('cube', { size: 1.5 }, scene);
    const material = new StandardMaterial('cubeMat', scene);
    material.diffuseColor = new Color3(0.5, 0.17, 0.17);
    cube.material = material;

    // Spin the cube every frame
    engine.managers.gameManager.registerFrameCallback((dt : number) =>
    {
        cube.rotation.x += 0.3 * dt;
        cube.rotation.y += 0.6 * dt;
        scene.render();
    });

    // Start the game loop
    engine.managers.gameManager.start();
}

main();

Run it with Vite:

bash
npx vite

You should see a dark scene with a red cube rotating. Click and drag to orbit the camera.

Troubleshooting

"Cannot find module '@skewedaspect/sage'" -- make sure the package installed correctly and the import path matches the package name exactly.

Black screen, nothing renders -- check that the canvas element is actually sized (a 0x0 canvas renders nothing) and that gameManager.start() was called.

Behaviors not responding to events -- a behavior only hears the types listed in its static events, and every type must be declared in the game's EventMap augmentation. Verify the emitter and the subscriber agree on spelling.

Vue Integration

If you are using Vue 3, the @skewedaspect/sage-vue package provides a SageCanvas component that handles engine creation, canvas management, and resize handling for you.

vue
<template>
    <SageCanvas @engine-ready="onEngineReady" :options="{ logLevel: 'info' }" />
</template>

<!--------------------------------------------------------------------------------------------------------------------->

<style scoped>
    /* SageCanvas fills its parent, so size the parent */
</style>

<!--------------------------------------------------------------------------------------------------------------------->

<script setup lang="ts">
    import type { GameEngine } from '@skewedaspect/sage';
    import { SageCanvas } from '@skewedaspect/sage-vue';

    function onEngineReady(engine : GameEngine) : void
    {
        // Set up your scene and start the game loop here.
        // The engine is fully initialized -- create scenes,
        // register frame callbacks, and call start().
    }
</script>

<!--------------------------------------------------------------------------------------------------------------------->

SageCanvas provides a scoped slot with loading, error, and engine properties, so you can overlay UI on top of the canvas:

vue
<SageCanvas @engine-ready="onEngineReady">
    <template #default="{ loading }">
        <div v-if="loading">Loading...</div>
    </template>
</SageCanvas>

The entity class table goes in through the :entity-classes prop, and engine options through :options.

TIP

Child components can access the engine instance using the useSageEngine() composable from @skewedaspect/sage-vue, without needing to pass it as a prop. The other composables have not been rebuilt for 0.10; see Vue 3 Integration.

Next Steps

This page got you from zero to spinning cube. For the full walkthrough with explanations of every piece, see the Hello Cube Guide. From there:

  • Architecture -- understand how the engine is put together
  • Entities -- learn the entity system and compiler-checked composition
  • Entity Behaviors -- build a game from behaviors and entity classes
  • Input System -- set up keyboard, mouse, and gamepad input
  • Levels -- load scenes from YAML and GLB files

Released under the MIT License.