sg.js API Reference
Complete reference for the SiliconGhetto engine JavaScript API (sg.js).
import sg from 'https://cdn.siliconghetto.com/engine/v0.1/sg.js';
Lifecycle
sg.init(canvasId, width, height) — async
Initialize the engine. Loads the WASM module, detects GPU (WebGPU or WebGL2 fallback), and sets up the rendering context.
await sg.init('game-canvas', 800, 600);
sg.run({ update, draw })
Start the game loop. update() runs at 60fps for game logic. draw() runs after for rendering.
sg.run({
update() { /* game logic */ },
draw() { /* rendering */ },
});
sg.stop()
Stop the game loop.
sg.clear(r, g, b)
Set the background clear color. Call at the start of draw().
sg.clear(0.1, 0.1, 0.2); // dark blue
Time
| Property | Type | Description |
|---|
sg.dt | number | Delta time in seconds since last frame |
sg.elapsed | number | Total elapsed time in seconds |
sg.frame | number | Total frame count |
Keyboard
| Method | Returns | Description |
|---|
sg.keyDown(key) | boolean | Key is currently held |
sg.keyPressed(key) | boolean | Key was pressed this frame |
Key names use KeyboardEvent.code values: 'KeyW', 'ArrowUp', 'Space', 'ShiftLeft', etc.
if (sg.keyDown('KeyW')) { /* moving forward */ }
if (sg.keyPressed('Space')) { /* just jumped */ }
Mouse
| Property/Method | Type | Description |
|---|
sg.mouseX | number | Mouse X position on canvas |
sg.mouseY | number | Mouse Y position on canvas |
sg.mouseDX | number | Mouse X movement delta (works under pointer lock) |
sg.mouseDY | number | Mouse Y movement delta |
sg.scrollDelta | number | Scroll wheel delta (positive = down) |
sg.mouseButton(btn) | boolean | Mouse button held (0=left, 1=middle, 2=right) |
sg.lockPointer() | void | Request pointer lock for FPS-style mouse look |
sg.pointerLocked | boolean | Whether pointer is currently locked |
Entities (2D)
sg.spawn(opts) → number
Create an entity. Returns a numeric handle used to reference the entity in all other calls.
const player = sg.spawn({
x: 400, y: 300,
sprite: { w: 32, h: 32, r: 1, g: 0.3, b: 0.3 },
collision: { w: 32, h: 32 },
tag: 'player',
});
| Option | Type | Description |
|---|
x, y | number | Initial position |
sprite | { w, h, r?, g?, b?, a? } | Size and color |
collision | { w, h } | Collision box dimensions |
tag | string | Tag for finding entities later |
texture | string | Texture ID (loaded with loadTexture) |
sg.despawn(entity)
Remove an entity and clean up all subsystem state (health, physics, AI, animation).
Position & Velocity
| Method | Description |
|---|
sg.setPos(e, x, y) | Set 2D position |
sg.setPos3D(e, x, y, z) | Set 3D position |
sg.getX(e) | Get X position |
sg.getY(e) | Get Y position |
sg.setVelocity(e, vx, vy) | Set velocity |
sg.getVelocity(e) | Get velocity → { vx, vy } |
Appearance
| Method | Description |
|---|
sg.setSprite(e, w, h, r, g, b, a) | Set size and color |
sg.setTexture(e, textureId) | Set texture |
| Method | Description |
|---|
sg.tag(e, tag) | Set a tag |
sg.hasTag(e, tag) | Check for tag |
sg.findByTag(tag) | Find first entity with tag |
Camera
| Method | Description |
|---|
sg.setCamera(x, y, zoom) | Set 2D camera position and zoom |
sg.setCamera3D(px, py, pz, tx, ty, tz) | Set 3D camera (position → target) |
sg.cameraFollow(entity, lerpSpeed) | Camera smoothly follows an entity |
Drawing
Call these inside draw(). All coordinates are screen-space pixels.
| Method | Description |
|---|
sg.drawAll() | Draw all entities |
sg.drawRect(x, y, w, h, { r, g, b, a }) | Draw a filled rectangle |
sg.drawCircle(x, y, radius, { r, g, b, a }) | Draw a filled circle |
sg.drawLine(x1, y1, x2, y2, { thickness, r, g, b, a }) | Draw a line |
sg.drawText(text, x, y, size, { r, g, b }) | Draw text |
sg.drawSprite(textureId, x, y, w, h) | Draw a textured sprite |
sg.drawRect(10, 10, 200, 30, { r: 0, g: 0, b: 0, a: 0.5 });
sg.drawText('Score: 100', 15, 15, 14, { r: 1, g: 1, b: 1 });
Screen
| Property | Type | Description |
|---|
sg.screenWidth | number | Canvas width in pixels |
sg.screenHeight | number | Canvas height in pixels |
| Method | Description |
|---|
sg.resize(width, height) | Resize canvas and GPU surfaces |
Physics (2D)
Collision Detection
| Method | Returns | Description |
|---|
sg.checkCollision(a, b) | boolean | AABB overlap test between two entities |
sg.overlapping(e) | number[] | All entities overlapping with e |
sg.moveAndCollide(e, dx, dy) | boolean | Move entity, stop at collisions |
Full platformer controller with gravity, jumping (coyote time + jump buffer), and variable jump height.
const player = sg.spawn({ x: 100, y: 100, collision: { w: 16, h: 24 } });
sg.setPlatformerPhysics(player, {
gravity: 980, jumpForce: 400, maxFall: 600, speed: 200,
});
// In update():
const input = sg.keyDown('ArrowRight') ? 1 : sg.keyDown('ArrowLeft') ? -1 : 0;
if (sg.keyPressed('Space')) sg.platformerJump(player);
sg.platformerJumpHeld(player, sg.keyDown('Space'));
const { dx, dy } = sg.updatePlatformer(player, input);
const { hitX, hitY } = sg.tilemapCollide(sg.getX(player), sg.getY(player), 8, 12, dx, dy);
sg.platformerResolve(player, hitX, hitY, dy > 0);
| Method | Description |
|---|
sg.setPlatformerPhysics(e, opts) | Enable platformer physics (gravity, jumpForce, maxFall, speed) |
sg.updatePlatformer(e, inputX) | Compute movement delta → { dx, dy } |
sg.platformerJump(e) | Request jump (buffered) |
sg.platformerJumpHeld(e, held) | Set jump button hold state |
sg.platformerResolve(e, hitX, hitY, wasMovingDown) | Resolve collision |
sg.onGround(e) | boolean — is entity on ground? |
sg.facing(e) | -1 or 1 — facing direction |
sg.onWallLeft(e) | boolean — touching wall on left |
sg.onWallRight(e) | boolean — touching wall on right |
Top-Down Physics
sg.setTopDownPhysics(entity, { speed: 150, friction: 600 });
Tile Maps
Grid-based level system with collision.
sg.createTileMap(20, 15, 32); // 20x15 grid, 32px tiles
sg.setTile(5, 14, 1); // solid ground
sg.setTileFlags(3, 10, 2, 2); // platform (one-way)
// In draw():
sg.drawTileMap();
| Method | Description |
|---|
sg.createTileMap(w, h, tileSize) | Create grid |
sg.setTile(x, y, type) | Set tile (0=empty) |
sg.setTileFlags(x, y, type, flags) | Set tile with collision flags (1=solid, 2=platform, 4=ladder, 8=hazard) |
sg.getTile(x, y) | Get tile type |
sg.getTileFlags(x, y) | Get collision flags |
sg.drawTileMap() | Render the map |
sg.tilemapCollide(cx, cy, halfW, halfH, dx, dy) | AABB collision → { x, y, hitX, hitY } |
sg.tileAtWorld(wx, wy) | Get tile at world position |
sg.isTileHazard(x, y) | Check hazard flag |
sg.isTileLadder(x, y) | Check ladder flag |
sg.clearTileMap() | Destroy tile map |
Animation
Frame-based sprite animation system.
sg.addAnimation(player, 'run', { frames: [0, 1, 2, 3], fps: 10, loop: true });
sg.addAnimation(player, 'idle', { frames: [0], fps: 1 });
sg.playAnim(player, 'run');
// In draw():
const frame = sg.getAnimFrame(player); // current frame index
| Method | Description |
|---|
sg.addAnimation(e, name, { frames, fps, loop }) | Define animation clip |
sg.playAnim(e, name) | Play animation |
sg.getAnimFrame(e) | Current frame index (-1 if none) |
sg.animationName(e) | Currently playing animation name |
sg.animationFinished(e) | Has non-looping animation finished? |
Health & Damage
sg.setHealth(enemy, 50); // 50 HP
sg.damage(enemy, 20); // -20 HP, triggers invincibility
sg.heal(enemy, 10); // +10 HP (capped at max)
if (sg.isDead(enemy)) sg.despawn(enemy);
| Method | Returns | Description |
|---|
sg.setHealth(e, max) | | Set max HP (also sets current to max) |
sg.damage(e, amount) | boolean | Deal damage (false if invincible) |
sg.heal(e, amount) | | Restore HP |
sg.getHealth(e) | number | Current HP (-1 if no health component) |
sg.getMaxHealth(e) | number | Max HP |
sg.isDead(e) | boolean | HP <= 0 |
sg.healthFraction(e) | number | HP / maxHP (0.0 to 1.0) |
sg.healthVisible(e) | boolean | Visible during hit flicker |
sg.updateHealth() | | Update invincibility timers (call in update()) |
sg.revive(e) | | Reset HP to max |
sg.setInvincibilityDuration(e, secs) | | Set i-frame duration |
Projectiles
const bullet = sg.spawnProjectile(x, y, 1, 0, 300, {
damage: 25, lifetime: 2, owner: player,
w: 8, h: 4, r: 1, g: 0.8, b: 0,
});
// In update():
sg.updateProjectiles();
for (const { handle, damage } of sg.checkProjectileHits()) {
sg.damage(handle, damage);
}
// In draw():
sg.drawProjectiles();
| Method | Description |
|---|
sg.spawnProjectile(x, y, dirX, dirY, speed, opts) | Spawn projectile → ID |
sg.updateProjectiles() | Move all projectiles (call in update()) |
sg.drawProjectiles() | Render all projectiles (call in draw()) |
sg.checkProjectileHits() | Check hits → [{ handle, damage }] |
sg.projectileCount | Active projectile count |
sg.clearProjectiles() | Remove all projectiles |
AI Behaviors
sg.setAI(enemy, 'chase', { target: player, speed: 80 });
sg.setAI(guard, 'patrol', { points: [[100,200], [300,200]], speed: 60 });
sg.setAI(rabbit, 'flee', { target: player, speed: 120, maxDistance: 200 });
// In update():
for (const { handle, dx, dy, facing } of sg.updateAI()) {
const { hitX, hitY } = sg.tilemapCollide(sg.getX(handle), sg.getY(handle), 8, 12, dx, dy);
sg.setPos(handle, sg.getX(handle) + (hitX ? 0 : dx), sg.getY(handle) + (hitY ? 0 : dy));
}
| Behavior | Options | Description |
|---|
'chase' | { target, speed } | Move toward target entity |
'patrol' | { points, speed } | Walk between waypoints |
'flee' | { target, speed, maxDistance } | Run away from target |
Voxel World
Quick Start
const { seed } = await sg.createVoxelGame({
canvas: 'game-canvas',
worldSize: [256, 64, 256],
seed: 42,
});
sg.run({
update() { sg.fpsUpdate(); },
draw() { sg.clear(0.5, 0.7, 1.0); },
});
sg.createVoxelGame(opts) — async
One-call setup: initializes engine, creates voxel world, generates terrain with 20 biomes, enables FPS controller, sets up pointer lock.
| Option | Default | Description |
|---|
canvas | 'game-canvas' | Canvas element ID |
width | 960 | Canvas width |
height | 600 | Canvas height |
worldSize | [256, 64, 256] | World dimensions [x, y, z] |
worldHeight | 64 | Y height (overridden by worldSize[1]) |
seed | random | Terrain generation seed |
player | {} | FPS controller settings (see below) |
biomes | 20 defaults | Custom biome array (replaces defaults) |
spawn | center | [x, y, z] spawn position |
Returns { seed, canvas, width, height }.
Block Operations
| Method | Description |
|---|
sg.createVoxelWorld(sx, sy, sz) | Create empty voxel world |
sg.setBlock(x, y, z, type) | Set a block (auto-remeshes chunk) |
sg.getBlock(x, y, z) | Get block type at position |
sg.fillBlocks(x1, y1, z1, x2, y2, z2, type) | Fill region with block type |
sg.voxelSizeX/Y/Z | World dimensions |
Block Types
Access via sg.BLOCKS or sg.blockTypes:
sg.setBlock(x, y, z, sg.BLOCKS.STONE);
sg.setBlock(x, y, z, sg.BLOCKS.DIAMOND_ORE);
| ID | Constant | ID | Constant |
|---|
| 0 | AIR | 22 | CALCITE |
| 1 | DIRT | 23 | FLOWER_YELLOW |
| 2 | GRASS | 24 | FLOWER_RED |
| 3 | STONE | 25 | TALL_GRASS |
| 4 | SAND | 26 | DEAD_BUSH |
| 5 | WOOD | 27 | CACTUS |
| 6 | LEAVES | 28 | MUSHROOM_RED |
| 7 | WATER | 29 | MUSHROOM_BROWN |
| 8 | BRICK | 30 | CHERRY_LEAVES |
| 9 | COBBLESTONE | 31 | BIRCH_WOOD |
| 10 | PLANKS | 32 | SPRUCE_WOOD |
| 11 | SNOW | 33 | JUNGLE_WOOD |
| 12 | GRAVEL | 34 | ACACIA_WOOD |
| 13 | PACKED_ICE | 35 | GLOW_LICHEN |
| 14 | SANDSTONE | 36 | IRON_ORE |
| 15 | RED_SAND | 37 | GOLD_ORE |
| 16 | TERRACOTTA | 38 | DIAMOND_ORE |
| 17 | PODZOL | 39 | COAL_ORE |
| 18 | MYCELIUM | 40 | LAVA |
| 19 | MUD | 41 | DRY_GRASS |
| 20 | CLAY | 42 | SPRUCE_LEAVES |
| 21 | MOSSY_STONE | | |
Block names are available via sg.BLOCK_NAMES[id].
FPS Controller
Enabled automatically by createVoxelGame(), or manually:
sg.enableFPSController({
speed: 7, // walk speed
jumpForce: 8.5, // jump velocity
gravity: 22, // gravity strength
sensitivity: 0.003, // mouse look sensitivity
flySpeed: 14, // fly mode speed
sprintMultiplier: 1.6,// shift sprint
playerRadius: 0.28, // collision cylinder radius
playerHeight: 1.65, // collision cylinder height
});
Built-in controls: WASD (move), Mouse (look), Space (jump), Shift (sprint), F (fly toggle), Ctrl (fly down).
| Method | Returns | Description |
|---|
sg.fpsUpdate() | { x, y, z, eyeY, targetX/Y/Z, onGround, flyMode, sprinting } | Update controller (call in update()) |
sg.fpsSetPosition(x, y, z) | | Teleport player |
sg.fpsGetPosition() | { x, y, z } | Player feet position |
sg.fpsGetLook() | { yaw, pitch } | Camera angles (radians) |
sg.fpsSetFly(bool) | | Set fly mode |
Raycasting
DDA (Digital Differential Analyzer) — exact, never misses a block.
// From FPS eye position:
const hit = sg.voxelRaycast(7);
if (hit.hit) {
// hit.x, hit.y, hit.z — the block that was hit
// hit.prevX, hit.prevY, hit.prevZ — the air block before it (for placing)
// hit.blockType — block type ID
}
// From arbitrary position + direction:
const hit2 = sg.voxelRaycastFrom(ox, oy, oz, dx, dy, dz, 20);
Collision
| Method | Returns | Description |
|---|
sg.voxelCollide(px, py, pz, dx, dy, dz, radius, height) | { x, y, z, hitY } | AABB collision (standalone) |
sg.voxelFindSpawnY(x, z) | number | Highest solid block + 2 at column |
sg.voxelIsWater(x, y, z) | boolean | Is block water? |
Terrain Generation
sg.generateTerrain({ seed: 42 });
Generates terrain using simplex noise with 20 biomes, 3 cave types (cheese, spaghetti, noodle), Y-level ore distribution, biome-specific trees, and surface decoration (flowers, grass).
Biome System
20 default biomes are registered automatically. To customize:
// Replace all biomes with custom set:
sg.resetBiomes();
sg.addBiome({
name: 'Alien Desert',
tempRange: [0.5, 1.0],
moistRange: [-1, 0],
surface: sg.BLOCKS.RED_SAND,
subSurface: sg.BLOCKS.TERRACOTTA,
treeDensity: 0.02,
treeTrunk: sg.BLOCKS.CACTUS,
treeLeaves: sg.BLOCKS.AIR,
});
sg.generateTerrain({ seed: 42 });
| Method | Description |
|---|
sg.addBiome(opts) | Add a biome (first match wins) |
sg.resetBiomes() | Clear all biomes (for custom set) |
sg.clearBiomes() | Reset to 20 defaults |
sg.biomeCount | Number of registered biomes |
Assets
await sg.loadTexture('hero', 'hero.png');
await sg.loadSound('jump', 'jump.wav');
sg.drawSprite('hero', 100, 200, 32, 32);
sg.playSound('jump');
| Method | Description |
|---|
sg.loadTexture(id, url) | Load texture (async) |
sg.loadSound(id, url) | Load audio (async) |
sg.playSound(id) | Play sound effect |
sg.playMusic(id) | Play looping music |
sg.stopMusic() | Stop music |
sg.setVolume(v) | Set master volume (0.0–1.0) |
CDN Library
await sg.loadTexture('hero', sg.lib.texture('hero-spritesheet'));
await sg.loadSound('jump', sg.lib.sound('jump'));
Particles
const emitter = sg.createEmitter(400, 300);
sg.emitBurst(emitter, 50); // spawn 50 particles
3D Meshes
const cube = sg.createCube();
const sphere = sg.createSphere();
const plane = sg.createPlane();