Semi-random thoughts and tales of tinkering
In Lesson 5, the player fell to a fixed "ground level." But in Minecraft, the ground is made of blocks at different heights! We need to check if the player is bumping into blocks — this is called collision detection. 🧱🚫
Every frame, before we move the player, we ask: "If I move to this new position, will I be overlapping with any solid block?" If yes, we don't allow the move. If no, we move freely.
The player's position is in pixels, but our world is a grid of blocks. To convert from pixels to block coordinates, we divide by the block size:
const BLOCK_SIZE = 32;
// Convert pixel position to block position
let blockCol = Math.floor(playerX / BLOCK_SIZE);
let blockRow = Math.floor(playerY / BLOCK_SIZE);
// Now we can check what block is at that position!
let blockType = world[blockRow][blockCol];
Math.floor() rounds a number down to the nearest
whole number. If the player is at pixel 75, Math.floor(75 / 32)
gives us 2 — meaning the player is in block column 2. This is how we translate
between the smooth pixel world and the blocky grid world!
The player isn't just a single point — they have width and height! We need to check ALL the blocks that the player's body overlaps with:
function isSolid(col, row) {
const block = getBlock(col, row);
return block !== 0; // Anything that isn't air is solid
}
function collidesWithWorld(px, py, pw, ph) {
// Find which blocks the player overlaps
const leftCol = Math.floor(px / BLOCK_SIZE);
const rightCol = Math.floor((px + pw - 1) / BLOCK_SIZE);
const topRow = Math.floor(py / BLOCK_SIZE);
const bottomRow = Math.floor((py + ph - 1) / BLOCK_SIZE);
// Check each overlapped block
for (let col = leftCol; col <= rightCol; col++) {
for (let row = topRow; row <= bottomRow; row++) {
if (isSolid(col, row)) return true; // Hit something!
}
}
return false; // Nothing in the way
}
The trick is to check collision before actually moving the player. We try the new position — if it would overlap with a block, we don't move there. We handle X and Y separately so the player can slide along walls:
// --- Horizontal Movement ---
let newX = playerX;
if (keys['KeyA']) newX -= SPEED;
if (keys['KeyD']) newX += SPEED;
// Only move if the new position doesn't collide
if (!collidesWithWorld(newX, playerY, playerW, playerH)) {
playerX = newX; // Safe to move!
}
// --- Vertical Movement (gravity) ---
vy += GRAVITY;
let newY = playerY + vy;
if (!collidesWithWorld(playerX, newY, playerW, playerH)) {
playerY = newY; // Safe to fall/rise
onGround = false;
} else {
// We hit something!
if (vy > 0) {
// We were falling — snap to top of the block we hit
playerY = Math.floor((playerY + playerH + vy) / BLOCK_SIZE) * BLOCK_SIZE - playerH;
onGround = true;
}
vy = 0; // Stop vertical movement
}
⬆️ Click here first! A D to move, Space to jump. The player now collides with blocks!
isSolid return false for that typeMath.floor(px / BLOCK_SIZE)