Files
gamercomp/frontend/public/templates/TEMPLATE_GUIDE.md
T
2026-04-30 02:14:25 +00:00

13 KiB
Raw Blame History

Game Template Guide for Haiku

This guide explains how to use the game templates to generate HTML5 canvas games for GamerComp.

Template Selection

gameTemplateAssets.html - Full Asset Library Template

Use this template when the game needs:

  • Procedural background themes (120 options)
  • Procedural music (160 songs, 8 moods)
  • User's avatar with game contexts (26 contexts)
  • Accessories and effects

Best for: RPGs, adventure games, racing games, space shooters, platformers, any game where the player's avatar matters.

gameTemplateSimple.html - Minimal Template

Use this template when the game needs:

  • Simple graphics (shapes, basic sprites)
  • No avatar/user identity
  • Fast loading (no asset libraries)

Best for: Puzzle games, simple arcade games, physics toys, creative tools, games where the player controls an object (not an avatar).


Using gameTemplateAssets.html

Step 1: Fill in GAME_CONFIG

Replace the placeholder comments with actual values:

const GAME_CONFIG = {
    title: "Space Defender",  // Replace <!-- GAME_TITLE -->

    assets: {
        music: {
            mood: "Epic",      // Replace <!-- MUSIC_MOOD -->
            energy: 8,
            enabled: true
        },

        background: {
            theme: "space",     // Replace <!-- BG_THEME -->
            variant: "nebula",  // Replace <!-- BG_VARIANT -->
            animated: true,
            effects: ["stars"]
        },

        avatarContext: {
            mode: "HEAD_ONLY",           // Replace <!-- AVATAR_MODE -->
            context: "spaceship-cockpit", // Replace <!-- CONTEXT_TYPE -->
            showAccessories: true
        }
    },

    gameplay: {
        // Add your game-specific config
        enemySpeed: 200,
        spawnRate: 2000,
        bulletSpeed: 500
    }
};

Step 2: Choose Asset Combinations

Music Moods (8 options)

Mood Best For Energy Range
Epic Boss battles, action games 7-10
Chill Puzzle games, casual games 2-4
Intense Racing, shooters, action 8-10
Playful Kids games, casual games 5-7
Mysterious Horror, mystery, exploration 3-6
Heroic Adventure, platformers 6-8
Quirky Puzzle, comedy, unique games 4-7
Ambient Background, meditation, creative 1-3

Background Themes (15 themes × 8 variants each)

Theme Variants Best For
space nebula, asteroidField, deepSpace, planets, spaceStation, warpSpeed, satellites, blackHole Space games, sci-fi
nature forest, jungle, desert, mountains, ocean, underwater, waterfall, meadow Adventure, relaxing
urban citySkyline, street, rooftop, neonDistrict, subway, park, mall, alley Racing, action
fantasy castle, dungeon, enchantedForest, floatingIslands, magicalLibrary, crystalCave, temple, tower RPG, adventure
abstract geometricPatterns, gradients, particleFields, minimalist, waves, fractals, kaleidoscope, matrix Puzzle, creative
retro pixelGrid, arcadeCabinet, crtEffects, vaporwave, scanlines, glitch, eightBit, synthwave Arcade, retro
indoor laboratory, classroom, bedroom, kitchen, arcade, office, library, gym Simulation, casual
weather rain, snow, storm, sunset, sunrise, fog, lightning, aurora Atmospheric
sports stadium, raceTrack, court, field, arena, pool, gym, skatepark Sports games
seasonal springMeadow, autumnLeaves, winterWonderland, summerBeach, harvest, blossom, snowfall, tropical Seasonal themes
underwater coralReef, deepSea, kelpForest, submarine, shipwreck, abyss, iceCave, treasure Ocean games
sky clouds, flyingHigh, hotAirBalloon, airplaneView, stratosphere, birdsEye, horizon, starfield Flying games
mechanical gears, circuits, factory, robotFactory, conveyorBelts, pipes, steampunk, techLab Tech, puzzle
spooky hauntedHouse, graveyard, darkForest, abandonedBuilding, crypt, manor, fog, shadows Horror, Halloween
colorful rainbow, paintSplatter, candyWorld, disco, neon, tieDye, gradient, prism Kids, casual

Avatar Modes (4 options)

Mode Dimensions Use When
HEAD_ONLY 64×64 Cockpit view, flying games, maze games
HEAD_AND_SHOULDERS 64×96 Driving games, submarine, conversation
UPPER_BODY 64×128 Racing, shooting, hoverboard
FULL_BODY 64×160 Platformers, RPGs, sports, adventure

Avatar Contexts (26 options)

Vehicle Contexts:

  • spaceship-cockpit (HEAD_ONLY) - Space shooters
  • race-car (HEAD_AND_SHOULDERS) - Racing games
  • airplane (HEAD_AND_SHOULDERS) - Flying games
  • flappy-style (HEAD_ONLY) - Flappy bird clones
  • tank (HEAD_ONLY) - Tank games
  • pacman-style (HEAD_ONLY) - Maze games
  • hoverboard (UPPER_BODY) - Hoverboard games
  • jetpack (UPPER_BODY) - Jetpack games
  • mech-suit (HEAD_ONLY) - Mech combat
  • submarine (HEAD_AND_SHOULDERS) - Underwater
  • dragon-rider (FULL_BODY) - Dragon games
  • motorcycle (FULL_BODY) - Motorcycle racing

Costume Contexts:

  • knight-armor (FULL_BODY) - Medieval games
  • space-suit (FULL_BODY) - Space exploration
  • ninja-outfit (FULL_BODY) - Ninja games
  • wizard-robes (FULL_BODY) - Magic games
  • superhero-cape (FULL_BODY) - Hero games
  • athlete-uniform (FULL_BODY) - Sports
  • pirate-outfit (FULL_BODY) - Pirate games
  • scientist-labcoat (FULL_BODY) - Science games
  • chef-outfit (FULL_BODY) - Cooking games
  • cowboy-gear (FULL_BODY) - Western games

Pure Contexts:

  • platformer-standard (FULL_BODY) - Standard platformer
  • sports-player (FULL_BODY) - Sports games
  • adventure-hero (FULL_BODY) - Adventure games
  • runner (FULL_BODY) - Endless runners

Step 3: Implement Game Functions

The template provides these functions for you to implement:

// Called once at start and on restart
function initGame() {
    // Initialize enemies, items, level data
    state.enemies = [];
    state.items = [];
}

// Called every frame (dt = seconds since last frame)
function updateGame(dt) {
    // Update positions, check collisions, spawn objects
    state.enemies.forEach(e => {
        e.x += e.velX * dt;
        e.y += e.velY * dt;
    });

    // Check player collision with enemies
    state.enemies.forEach(e => {
        if (circleCollision(
            { x: state.playerX, y: state.playerY, r: 30 },
            { x: e.x, y: e.y, r: e.radius }
        )) {
            updateHealth(-10);
        }
    });
}

// Called every frame after updateGame
function renderGame() {
    // Draw enemies, items, effects
    state.enemies.forEach(e => {
        ctx.fillStyle = e.color;
        ctx.beginPath();
        ctx.arc(e.x, e.y, e.radius, 0, Math.PI * 2);
        ctx.fill();
    });
}

// Input handlers
function handleKeyDown(code) {
    if (code === 'Space') {
        shoot();  // Your function
    }
}

function handleTouchStart(x, y) {
    // Handle tap
}

Step 4: Use Provided Utilities

The template includes these utility functions:

// Score & Health
updateScore(10);         // Add 10 points
updateHealth(-5);        // Lose 5 health
updateHealth(10);        // Gain 10 health (capped at 100)

// Animation
setPlayerAnimation('walk');   // idle, walk, run, jump, hurt, celebrate, etc.

// Math
randomInt(1, 10);        // Random integer 1-10
randomFloat(0, 1);       // Random float 0-1
clamp(value, 0, 100);    // Clamp to range
lerp(0, 100, 0.5);       // Linear interpolation = 50

// Collision
rectCollision(r1, r2);   // {x, y, width, height} objects
circleCollision(c1, c2); // {x, y, radius} objects

// Game flow
endGame();               // Trigger game over

Using gameTemplateSimple.html

For simple games without avatars:

const GAME_CONFIG = {
    title: "Catch the Stars",

    background: {
        type: "gradient",
        colors: ["#0f0c29", "#302b63", "#24243e"]
    },

    player: {
        width: 50,
        height: 50,
        color: "#FFD700",
        speed: 400
    },

    gameplay: {
        starSpawnRate: 1000,
        starFallSpeed: 200
    }
};

Then implement:

  • initGame() - Setup
  • update(dt) - Game logic
  • render() - Draw objects
  • Input handlers

Common Patterns

Platformer Movement

const GRAVITY = 1500;
const JUMP_FORCE = 600;

function update(dt) {
    // Horizontal movement
    if (keys['ArrowLeft']) state.playerVelX = -300;
    else if (keys['ArrowRight']) state.playerVelX = 300;
    else state.playerVelX *= 0.8; // Friction

    // Apply gravity
    state.playerVelY += GRAVITY * dt;

    // Move player
    state.playerX += state.playerVelX * dt;
    state.playerY += state.playerVelY * dt;

    // Ground collision
    if (state.playerY > canvas.height - 50) {
        state.playerY = canvas.height - 50;
        state.playerVelY = 0;
        state.isGrounded = true;
    }
}

function handleKeyDown(code) {
    if (code === 'Space' && state.isGrounded) {
        state.playerVelY = -JUMP_FORCE;
        state.isGrounded = false;
        setPlayerAnimation('jump');
    }
}

Space Shooter

state.bullets = [];
state.enemies = [];

function update(dt) {
    // Update bullets
    state.bullets = state.bullets.filter(b => {
        b.y -= 500 * dt;
        return b.y > 0;
    });

    // Spawn enemies
    if (Math.random() < 0.02) {
        state.enemies.push({
            x: randomInt(50, canvas.width - 50),
            y: -30,
            radius: 20,
            color: '#ff4444'
        });
    }

    // Update enemies
    state.enemies.forEach(e => e.y += 150 * dt);
    state.enemies = state.enemies.filter(e => e.y < canvas.height + 50);

    // Collision: bullets vs enemies
    state.bullets.forEach(b => {
        state.enemies = state.enemies.filter(e => {
            if (circleCollision(b, e)) {
                updateScore(10);
                return false;
            }
            return true;
        });
    });
}

function handleKeyDown(code) {
    if (code === 'Space') {
        state.bullets.push({
            x: state.playerX,
            y: state.playerY - 30,
            radius: 5
        });
    }
}

Endless Runner

let scrollSpeed = 300;
let obstacles = [];
let lastObstacle = 0;

function update(dt) {
    scrollSpeed += dt * 2; // Speed up over time

    // Jump
    if (keys['Space'] && state.isGrounded) {
        state.playerVelY = -500;
        state.isGrounded = false;
    }

    // Gravity
    state.playerVelY += 1200 * dt;
    state.playerY += state.playerVelY * dt;

    // Ground
    const ground = canvas.height - 100;
    if (state.playerY > ground) {
        state.playerY = ground;
        state.isGrounded = true;
    }

    // Spawn obstacles
    lastObstacle += dt * 1000;
    if (lastObstacle > 1500) {
        obstacles.push({ x: canvas.width, y: ground, w: 30, h: 50 });
        lastObstacle = 0;
    }

    // Move obstacles
    obstacles = obstacles.filter(o => {
        o.x -= scrollSpeed * dt;
        return o.x > -50;
    });

    // Score
    updateScore(Math.floor(dt * 10));
}

Space Shooter

music: { mood: "Epic", energy: 8 }
background: { theme: "space", variant: "nebula" }
avatarContext: { mode: "HEAD_ONLY", context: "spaceship-cockpit" }

Platformer

music: { mood: "Playful", energy: 6 }
background: { theme: "nature", variant: "forest" }
avatarContext: { mode: "FULL_BODY", context: "platformer-standard" }

Racing

music: { mood: "Intense", energy: 9 }
background: { theme: "urban", variant: "street" }
avatarContext: { mode: "HEAD_AND_SHOULDERS", context: "race-car" }

RPG/Adventure

music: { mood: "Heroic", energy: 6 }
background: { theme: "fantasy", variant: "castle" }
avatarContext: { mode: "FULL_BODY", context: "knight-armor" }

Puzzle

music: { mood: "Chill", energy: 3 }
background: { theme: "abstract", variant: "minimalist" }
// Use gameTemplateSimple.html instead

Horror

music: { mood: "Mysterious", energy: 4 }
background: { theme: "spooky", variant: "hauntedHouse" }
avatarContext: { mode: "FULL_BODY", context: "adventure-hero" }

Important Notes

  1. Always use the provided state object - Don't create global variables for game state.

  2. Delta time is in seconds - Multiply speeds by dt for frame-independent movement.

  3. Player position is center-based - playerX and playerY are the center of the player.

  4. Earned accessories always show - User's crowns, auras, etc. render above costumes.

  5. Test on mobile - Touch handlers are provided, but test gesture-based games.

  6. Use endGame() properly - It handles score reporting and music fadeout.

  7. Don't modify the asset library scripts - Only modify the game logic section.