Semi-random thoughts and tales of tinkering
You've learned every building block (pun intended! 😄). Now let's see how they all come together in the final game, plus a few bonus features: a day/night cycle, crafting, and a health system! 🎮🏆
The sky changes color over time, creating a day/night cycle! We use a simple timer that cycles through sunrise → day → sunset → night:
let gameTime = 30000; // Start at noon
function getTimeOfDay() {
const cycle = 120000; // Full cycle = 2 minutes
return (gameTime % cycle) / cycle; // Returns 0.0 to 1.0
}
function getSkyColor(time) {
if (time < 0.2) return lerpColor('#0a0a2e', '#87ceeb', time / 0.2); // Dawn
if (time < 0.5) return '#87ceeb'; // Day
if (time < 0.7) return lerpColor('#87ceeb', '#0a0a2e', (time-0.5)/0.2);// Dusk
return '#0a0a2e'; // Night
}
// Darken the screen at night
function getDarkness(time) {
if (time < 0.2) return 1 - time / 0.2; // Getting lighter (dawn)
if (time < 0.5) return 0; // Full daylight
if (time < 0.7) return (time - 0.5) / 0.2; // Getting darker (dusk)
return 1; // Full darkness
}
lerpColor smoothly blends between two colors. "Lerp" stands for
Linear Interpolation — a fancy way of saying "gradually transition
from A to B." At 0% you get color A, at 100% you get color B, and at 50% you get
a perfect mix in between!
Crafting turns raw materials into new items. Each recipe lists inputs and outputs:
const RECIPES = [
// 1 wood → 4 planks
{ input: { WOOD: 1 }, output: { block: PLANKS, count: 4 } },
// 4 planks → 1 crafting table
{ input: { PLANKS: 4 }, output: { block: CRAFTING_TABLE, count: 1 } },
// 1 cobblestone + 1 coal → 4 torches
{ input: { COBBLESTONE: 1, COAL: 1 }, output: { block: TORCH, count: 4 } },
];
function canCraft(recipe) {
// Check if player has all required inputs
return Object.entries(recipe.input).every(([blockType, needed]) => {
const total = inventory.reduce((sum, slot) =>
sum + (slot && slot.block === blockType ? slot.count : 0), 0);
return total >= needed;
});
}
const player = {
health: 20, // 10 hearts (each heart = 2 HP)
maxHealth: 20,
// ...other properties
};
// Fall damage — if falling speed is too high when landing
if (player.vy > 10) {
player.health -= Math.floor((player.vy - 10) * 2);
}
// Passive healing (small random chance each frame)
if (player.health < player.maxHealth && Math.random() < 0.003) {
player.health++;
}
// Respawn when health reaches 0
if (player.health <= 0) {
player.health = player.maxHealth;
// Teleport back to spawn point
}
Here's the complete architecture of our game — every system you built!
| Lesson | Concept | What It Does in the Game |
|---|---|---|
| 1 | Canvas & Drawing | The screen we draw everything on |
| 2 | Variables & Functions | Player position, drawBlock(), drawPlayer() |
| 3 | Animation Loop | The gameLoop() that runs 60× per second |
| 4 | Keyboard Controls | WASD movement, slot selection |
| 5 | Gravity & Jumping | Falling, jumping, velocity physics |
| 6 | 2D Arrays | The world grid storing every block |
| 7 | Collision Detection | Walking on blocks, hitting walls |
| 8 | Scrolling Camera | Showing a huge world through a small window |
| 9 | Mouse Input | Breaking and placing blocks |
| 10 | Inventory | Collecting and managing items |
| 11 | World Generation | Procedural terrain, trees, ores, caves |
| 12 | Polish | Day/night, crafting, health, final game |
You've learned how to build a complete 2D game from scratch! You now understand variables, functions, arrays, loops, physics, collision detection, procedural generation, and so much more.
These are real programming skills that professional game developers use every day. You should be really proud! 🌟
⛏️ Play the Complete Game!The game is complete, but there's always more you can add! Here are some ideas:
Add zombies or creepers that spawn at night and chase the player!
Use the Web Audio API to add mining, placing, and walking sounds.
Use localStorage to save the world and load it later.
Make water flow and fill in gaps, like real Minecraft water!
Add doors, windows, stairs, ladders — each with unique behavior.
Plant seeds, water them, and harvest crops!
Different regions: desert, snow, jungle — each with unique terrain.
Use WebSockets to let friends join your world!
localStorage.setItem('world', JSON.stringify(world))<audio> tag