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:
npm install @skewedaspect/sage @skewedaspect/sage-core @babylonjs/core @babylonjs/havok @babylonjs/loadersIf you are building a Vue application, also install the Vue integration package:
npm install @skewedaspect/sage-vueTypeScript Configuration
Make sure your tsconfig.json includes these settings:
{
"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:
<!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:
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:
npx viteYou 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.
<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:
<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
