🌾 FarmHeart
Three.jsTutorialBeginner

Three.js Game Tutorial: Build Your First 3D Game in a Weekend

2026-09-14 · 12 min read

Why Three.js for Games?

Three.js is the most popular 3D library for the web, and for good reason. It abstracts away the complexity of raw WebGL while giving you full control over scenes, lighting, materials, and animation. If you've never built a 3D game before, Three.js is the friendliest on-ramp.

Unlike game engines like Unity or Unreal, Three.js games run directly in the browser. No app store, no installer, no 2GB download — just a URL. That means anyone can play your game on any device with a modern browser.

What You'll Build

By the end of this tutorial, you'll have a simple 3D game running in the browser: a player character that moves through a procedurally generated environment, collects items, and avoids obstacles. We'll cover:

Step 1: Project Setup

Start with a clean HTML file. You don't need npm, webpack, or any build tools — Three.js works perfectly with a simple script tag or ES module import from a CDN.

Create three files: index.html, style.css, and game.js. The HTML sets up a full-screen canvas. The CSS makes the body margin-zero and overflow-hidden. The JavaScript is where the game lives.

Tip: Use import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.170/build/three.module.js' to skip npm entirely. Pin a specific version to avoid breaking changes.

Step 2: Scene, Camera, Renderer

Every Three.js application starts with three objects: a Scene (the container for everything), a Camera (what the player sees), and a Renderer (what draws the scene to the screen).

Use a PerspectiveCamera with a field of view around 60-75 degrees. For games, you typically want the camera to follow the player, so store a reference you'll update each frame.

The renderer should be created with antialias: true for smoother edges. Set its size to window.innerWidth and window.innerHeight, and add a resize listener to handle window changes.

Step 3: Lighting and Materials

Good lighting makes the difference between a tech demo and a game that feels alive. Start with two lights:

For materials, MeshStandardMaterial responds to light realistically. Use MeshBasicMaterial for UI elements that should always be visible regardless of lighting.

Step 4: Player Movement

Track which keys are pressed using a Set that adds keys on keydown and removes them on keyup. In your animation loop, check the set and update the player position accordingly.

A common pattern for smooth movement:

Tip: Always use requestAnimationFrame for your game loop, never setInterval. It syncs to the display refresh rate and pauses when the tab is hidden (saving battery and CPU).

Step 5: Collision Detection

For simple games, you don't need a physics engine. Axis-Aligned Bounding Box (AABB) collision detection works for most cases: check if two boxes overlap on all three axes.

Create a helper function that takes two objects with position and size, then returns true if they overlap. Call it each frame to check the player against collectibles and obstacles.

Step 6: Procedural Generation

Instead of hand-placing every tree and rock, write a function that scatters objects randomly within bounds. Use seeded randomness if you want reproducible worlds.

Key technique: create objects in a pool and reuse them. When an object moves off-screen behind the player, teleport it ahead of them. This gives the illusion of an infinite world with a fixed number of mesh objects — critical for performance.

Step 7: Game State and UI

Track score, health, and game state in a plain JavaScript object. Render the UI with HTML/CSS overlaid on the canvas — this is much easier than rendering text in 3D and gives you full CSS styling control.

Game states to handle: menu, playing, paused, gameover. A simple state machine keeps your code organized as the game grows.

Step 8: Sound Effects

The Web Audio API lets you generate sounds procedurally — no audio files needed. Create short synthesized effects for collecting items (ascending tone), hitting obstacles (low buzz), and game over (descending sweep).

Always gate audio behind a user interaction (click or keypress) because browsers block autoplay. Start your AudioContext on the first user input.

Step 9: Mobile Support

Browser games that don't work on mobile miss half their audience. Add touch controls: a virtual joystick (two nested divs with touch event handlers) and tap-to-interact buttons.

Detect touch capability with 'ontouchstart' in window and show/hide the appropriate controls. Test on a real phone — emulators miss performance issues that real devices expose.

Step 10: Deployment

Your game is just static files — HTML, CSS, and JavaScript. Deploy to any static hosting service for free:

ServiceFree TierDeploy Method
Cloudflare PagesUnlimited bandwidthGit push or drag-and-drop
GitHub Pages1GB storage, 100GB/mo bandwidthGit push
Netlify100GB/mo bandwidthGit push or drag-and-drop
Vercel100GB/mo bandwidthGit push

Cloudflare Pages is the best choice for games because of unlimited bandwidth — a popular game can burn through other services' free tiers quickly.

Common Beginner Mistakes

What's Next?

Once your basic game works, try adding: particle effects (sparks, dust, rain), a day/night cycle, save/load with localStorage, and a leaderboard with a simple serverless function.

FarmHeart started as a simple Three.js prototype and grew into a full farming simulation. The same techniques in this tutorial — scene management, procedural generation, state machines — scale up to surprisingly complex games.

Play FarmHeart

A cozy 3D farming game that runs right in your browser. No download, no signup.

Play Now