Initial commit
This commit is contained in:
@@ -0,0 +1,451 @@
|
||||
# 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:
|
||||
|
||||
```javascript
|
||||
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:
|
||||
|
||||
```javascript
|
||||
// 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:
|
||||
|
||||
```javascript
|
||||
// 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:
|
||||
|
||||
```javascript
|
||||
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
|
||||
```javascript
|
||||
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
|
||||
```javascript
|
||||
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
|
||||
```javascript
|
||||
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));
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recommended Combinations by Game Type
|
||||
|
||||
### Space Shooter
|
||||
```javascript
|
||||
music: { mood: "Epic", energy: 8 }
|
||||
background: { theme: "space", variant: "nebula" }
|
||||
avatarContext: { mode: "HEAD_ONLY", context: "spaceship-cockpit" }
|
||||
```
|
||||
|
||||
### Platformer
|
||||
```javascript
|
||||
music: { mood: "Playful", energy: 6 }
|
||||
background: { theme: "nature", variant: "forest" }
|
||||
avatarContext: { mode: "FULL_BODY", context: "platformer-standard" }
|
||||
```
|
||||
|
||||
### Racing
|
||||
```javascript
|
||||
music: { mood: "Intense", energy: 9 }
|
||||
background: { theme: "urban", variant: "street" }
|
||||
avatarContext: { mode: "HEAD_AND_SHOULDERS", context: "race-car" }
|
||||
```
|
||||
|
||||
### RPG/Adventure
|
||||
```javascript
|
||||
music: { mood: "Heroic", energy: 6 }
|
||||
background: { theme: "fantasy", variant: "castle" }
|
||||
avatarContext: { mode: "FULL_BODY", context: "knight-armor" }
|
||||
```
|
||||
|
||||
### Puzzle
|
||||
```javascript
|
||||
music: { mood: "Chill", energy: 3 }
|
||||
background: { theme: "abstract", variant: "minimalist" }
|
||||
// Use gameTemplateSimple.html instead
|
||||
```
|
||||
|
||||
### Horror
|
||||
```javascript
|
||||
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.
|
||||
Reference in New Issue
Block a user