Semi-random thoughts and tales of tinkering
Our world so far fits on one screen. But Minecraft worlds are huge! In this lesson, we'll create a world much bigger than the screen and add a camera that follows the player. 🎥
Our screen is maybe 600 pixels wide, but we want a world that's thousands of pixels wide. We can't see the whole world at once — we need to show just the part around the player, like looking through a window that moves.
The camera has a position: cameraX and cameraY.
When we draw things, we subtract the camera position from everything.
This makes the world appear to slide under the camera!
let cameraX = 0;
let cameraY = 0;
function updateCamera() {
// Center the camera on the player
cameraX = playerX - canvas.width / 2;
cameraY = playerY - canvas.height / 2;
}
// When drawing blocks, subtract the camera position:
function drawWorld() {
for (let row = 0; row < ROWS; row++) {
for (let col = 0; col < COLS; col++) {
const block = world[row][col];
if (block === 0) continue;
// Convert world position to screen position
const screenX = col * BLOCK_SIZE - cameraX;
const screenY = row * BLOCK_SIZE - cameraY;
ctx.fillStyle = COLORS[block];
ctx.fillRect(screenX, screenY, BLOCK_SIZE, BLOCK_SIZE);
}
}
}
screenX = worldX - cameraXIf the camera is at x=1000 and a block is at x=1050, the block appears at screen position 50 (near the left edge).
Snapping the camera directly to the player feels jerky. Instead, we make it smoothly glide toward the player:
function updateCamera() {
// Where the camera WANTS to be
const targetX = playerX - canvas.width / 2;
const targetY = playerY - canvas.height / 2;
// Move 10% of the way there each frame (smooth!)
cameraX += (targetX - cameraX) * 0.1;
cameraY += (targetY - cameraY) * 0.1;
}
Our world might have thousands of blocks, but the screen only shows a few dozen. Drawing blocks that aren't visible wastes time! We calculate which blocks are on screen and only draw those:
// Which blocks are visible?
const startCol = Math.max(0, Math.floor(cameraX / BLOCK_SIZE));
const startRow = Math.max(0, Math.floor(cameraY / BLOCK_SIZE));
const endCol = Math.min(COLS, Math.ceil((cameraX + canvas.width) / BLOCK_SIZE) + 1);
const endRow = Math.min(ROWS, Math.ceil((cameraY + canvas.height) / BLOCK_SIZE) + 1);
// Only loop through visible blocks!
for (let row = startRow; row < endRow; row++) {
for (let col = startCol; col < endCol; col++) {
// draw this block...
}
}
⬆️ Click here first! A D to move, Space to jump. Explore the world — it's bigger than the screen!
0.1 smooth factor to 0.5 or 1.0 — how does it feel?screen position = world position - camera position