Three.js Game Development Skill
Comprehensive assistance with Three.js game development using WebGL, covering 3D rendering, game mechanics, physics, animations, and interactive browser-based games.
When to Use This Skill
Activate this skill when:
-
Building 3D web games with Three.js
-
Implementing game mechanics (player movement, collisions, scoring)
-
Setting up cameras, lighting, and scene management
-
Loading 3D models (GLTF, OBJ, FBX)
-
Handling user input (keyboard, mouse, touch, gamepad)
-
Creating animations and character controllers
-
Integrating physics engines (Cannon.js, Ammo.js)
-
Optimizing 3D game performance
-
Working with shaders and materials for game visuals
Quick Reference
Basic Game Setup
import * as THREE from 'three';
// Create scene, camera, renderer const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement);
// Game loop function animate(time) { requestAnimationFrame(animate);
// Update game logic here updatePlayer(time); updateEnemies(time); checkCollisions();
renderer.render(scene, camera); }
animate();
Player Controller (Third-Person)
class PlayerController { constructor(camera, target) { this.camera = camera; this.target = target; this.distance = 10; this.height = 5; this.rotationSpeed = 0.005; this.moveSpeed = 0.1; }
update(input) { // Movement const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(this.target.quaternion); const right = new THREE.Vector3(1, 0, 0).applyQuaternion(this.target.quaternion);
if (input.forward) this.target.position.add(forward.multiplyScalar(this.moveSpeed));
if (input.backward) this.target.position.add(forward.multiplyScalar(-this.moveSpeed));
if (input.left) this.target.position.add(right.multiplyScalar(-this.moveSpeed));
if (input.right) this.target.position.add(right.multiplyScalar(this.moveSpeed));
// Rotation
if (input.rotateLeft) this.target.rotation.y += this.rotationSpeed;
if (input.rotateRight) this.target.rotation.y -= this.rotationSpeed;
// Update camera position
const offset = new THREE.Vector3(0, this.height, this.distance);
offset.applyQuaternion(this.target.quaternion);
this.camera.position.copy(this.target.position).add(offset);
this.camera.lookAt(this.target.position);
} }
Input Handling
class InputManager { constructor() { this.keys = {}; this.mouse = { x: 0, y: 0, buttons: {} };
window.addEventListener('keydown', (e) => this.keys[e.code] = true);
window.addEventListener('keyup', (e) => this.keys[e.code] = false);
window.addEventListener('mousemove', (e) => {
this.mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
this.mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
});
}
getInput() { return { forward: this.keys['KeyW'] || this.keys['ArrowUp'], backward: this.keys['KeyS'] || this.keys['ArrowDown'], left: this.keys['KeyA'] || this.keys['ArrowLeft'], right: this.keys['KeyD'] || this.keys['ArrowRight'], jump: this.keys['Space'], action: this.keys['KeyE'], rotateLeft: this.keys['KeyQ'], rotateRight: this.keys['KeyE'] }; } }
Collision Detection (Raycasting)
function checkCollisions(player, obstacles) { const raycaster = new THREE.Raycaster(); const directions = [ new THREE.Vector3(1, 0, 0), // right new THREE.Vector3(-1, 0, 0), // left new THREE.Vector3(0, 0, 1), // forward new THREE.Vector3(0, 0, -1), // backward ];
for (const direction of directions) { raycaster.set(player.position, direction); const intersects = raycaster.intersectObjects(obstacles);
if (intersects.length > 0 && intersects[0].distance < 1.0) {
return {
collision: true,
object: intersects[0].object,
distance: intersects[0].distance,
point: intersects[0].point
};
}
}
return { collision: false }; }
Loading 3D Models (GLTF)
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
const loader = new GLTFLoader();
function loadCharacter(path) { return new Promise((resolve, reject) => { loader.load( path, (gltf) => { const model = gltf.scene; model.scale.set(1, 1, 1); scene.add(model);
// Setup animations if available
const mixer = new THREE.AnimationMixer(model);
const animations = {};
gltf.animations.forEach(clip => {
animations[clip.name] = mixer.clipAction(clip);
});
resolve({ model, mixer, animations });
},
(progress) => {
console.log(`Loading: ${(progress.loaded / progress.total * 100).toFixed(2)}%`);
},
(error) => reject(error)
);
}); }
// Usage const character = await loadCharacter('/models/character.glb'); character.animations.idle.play();
Basic Physics (Gravity & Jumping)
class PhysicsBody { constructor(mesh) { this.mesh = mesh; this.velocity = new THREE.Vector3(); this.onGround = false; this.gravity = -9.8; this.jumpPower = 5; }
update(deltaTime) { // Apply gravity if (!this.onGround) { this.velocity.y += this.gravity * deltaTime; }
// Apply velocity
this.mesh.position.add(this.velocity.clone().multiplyScalar(deltaTime));
// Ground check
if (this.mesh.position.y <= 0) {
this.mesh.position.y = 0;
this.velocity.y = 0;
this.onGround = true;
}
}
jump() { if (this.onGround) { this.velocity.y = this.jumpPower; this.onGround = false; } } }
Interactive Objects (Picking)
const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2();
function onMouseClick(event) { mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(interactableObjects);
if (intersects.length > 0) { const object = intersects[0].object; object.userData.onInteract?.(); } }
window.addEventListener('click', onMouseClick);
Health & Damage System
class Entity { constructor(mesh, maxHealth) { this.mesh = mesh; this.maxHealth = maxHealth; this.health = maxHealth; this.isDead = false; }
takeDamage(amount) { if (this.isDead) return;
this.health = Math.max(0, this.health - amount);
if (this.health === 0) {
this.die();
}
return this.health;
}
heal(amount) { this.health = Math.min(this.maxHealth, this.health + amount); return this.health; }
die() { this.isDead = true; this.mesh.visible = false; // Trigger death animation, effects, etc. } }
Key Concepts
Scene Graph
-
Organize game objects hierarchically
-
Use groups for complex objects
-
Parent-child transformations
Game Loop
-
Use requestAnimationFrame for 60fps
-
Calculate delta time for frame-independent movement
-
Separate update logic from rendering
Camera Systems
-
PerspectiveCamera: First/third-person games
-
OrthographicCamera: 2D/isometric games
-
Implement camera follow and smooth transitions
Lighting
-
AmbientLight: Base illumination
-
DirectionalLight: Sun/moonlight with shadows
-
PointLight: Torches, explosions
-
SpotLight: Flashlights, stage lights
Performance Optimization
-
Use instancing for repeated objects
-
Implement frustum culling
-
Use LOD (Level of Detail) for distant objects
-
Minimize draw calls
-
Use texture atlases
-
Enable shadow map optimization
Asset Loading
-
Preload all assets before game start
-
Show loading progress bar
-
Use LoadingManager for coordination
-
Cache loaded assets
Common Game Patterns
State Machine (Game States)
class GameStateMachine { constructor() { this.states = { menu: new MenuState(), playing: new PlayingState(), paused: new PausedState(), gameOver: new GameOverState() }; this.currentState = this.states.menu; }
changeState(stateName) { this.currentState.exit(); this.currentState = this.states[stateName]; this.currentState.enter(); }
update(deltaTime) { this.currentState.update(deltaTime); } }
Object Pooling
class ObjectPool { constructor(factory, initialSize = 10) { this.factory = factory; this.available = []; this.inUse = [];
for (let i = 0; i < initialSize; i++) {
this.available.push(factory());
}
}
acquire() { let obj = this.available.pop(); if (!obj) obj = this.factory(); this.inUse.push(obj); return obj; }
release(obj) { const index = this.inUse.indexOf(obj); if (index > -1) { this.inUse.splice(index, 1); this.available.push(obj); } } }
// Usage const bulletPool = new ObjectPool(() => createBullet(), 20); const bullet = bulletPool.acquire(); // ... use bullet bulletPool.release(bullet);
Reference Files
Detailed documentation organized by topic:
-
getting_started.md - Three.js fundamentals, setup, and basic concepts
-
game_development.md - Game loop, player controllers, game mechanics
-
scene_graph.md - Scene organization, hierarchy, transformations
-
materials.md - Material types, shaders, visual effects
-
textures.md - Texture loading, UV mapping, atlases
-
lighting.md - Light types, shadows, HDR
-
cameras.md - Camera types, controls, viewport management
-
geometry.md - Built-in geometries, custom geometry, buffers
-
loading.md - Asset loading (models, textures, audio)
-
animation.md - Animation system, skeletal animation, tweens
-
interactivity.md - Raycasting, picking, UI integration
-
effects.md - Post-processing, particles, fog
Resources
Official Documentation
-
Three.js Manual: https://threejs.org/manual/
-
Three.js API: https://threejs.org/docs/
-
Three.js Examples: https://threejs.org/examples/
Physics Integration
-
Cannon.js: Lightweight 3D physics
-
Ammo.js: Full Bullet physics engine port
-
Rapier: High-performance physics
Useful Libraries
-
three-mesh-bvh: Fast raycasting
-
three-pathfinding: Navigation meshes
-
postprocessing: Advanced effects
Working with This Skill
For Beginners
-
Start with basic scene setup
-
Learn the coordinate system
-
Understand the game loop
-
Practice with simple shapes before models
For Game Development
-
Plan your game architecture
-
Implement input handling first
-
Build a simple player controller
-
Add gameplay mechanics incrementally
-
Optimize performance throughout
For Advanced Features
-
Integrate physics engines
-
Implement advanced shaders
-
Add post-processing effects
-
Build multiplayer networking
Notes
-
Three.js uses a right-handed coordinate system (X right, Y up, Z out)
-
Optimize early: profile regularly, minimize draw calls
-
Use development builds for debugging, production builds for release
-
Consider WebGL 2 features for modern browsers
-
Mobile performance requires careful optimization