JavaScript游戏:玩家与物体的底部-顶部碰撞问题及修复
Hey folks,
I’ve been building a game where players move around using arrow keys and need to collide with in-game objects. I had already nailed the collision logic for the player’s right side hitting an object’s left edge, and the player’s left side hitting an object’s right edge—but I was stuck bad on getting the player’s bottom colliding with an object’s top to work. I searched everywhere for solutions and came up empty-handed.
After some trial and error (and a lot of console logs), I finally cracked it! Below is the full, fixed code that handles collision detection for all four directions:
// Player object with position, size, and movement speed const player = { x: 50, y: 50, width: 32, height: 32, speed: 5 }; // Array of in-game objects to collide with const objects = [ { x: 200, y: 200, width: 64, height: 64 }, { x: 400, y: 300, width: 64, height: 64 } ]; // Tracks pressed keys for movement const keys = {}; window.addEventListener('keydown', e => keys[e.key] = true); window.addEventListener('keyup', e => keys[e.key] = false); // Core collision detection function function checkCollision(player, obj) { // Calculate edge positions for both player and object const playerRight = player.x + player.width; const playerLeft = player.x; const playerBottom = player.y + player.height; const playerTop = player.y; const objRight = obj.x + obj.width; const objLeft = obj.x; const objBottom = obj.y + obj.height; const objTop = obj.y; // Player right colliding with object left if (playerRight >= objLeft && playerLeft < objLeft && playerBottom > objTop && playerTop < objBottom) { player.x = objLeft - player.width; return true; } // Player left colliding with object right if (playerLeft <= objRight && playerRight > objRight && playerBottom > objTop && playerTop < objBottom) { player.x = objRight; return true; } // Player bottom colliding with object top (the tricky one!) if (playerBottom >= objTop && playerTop < objTop && playerRight > objLeft && playerLeft < objRight) { player.y = objTop - player.height; return true; } // Player top colliding with object bottom if (playerTop <= objBottom && playerBottom > objBottom && playerRight > objLeft && playerLeft < objRight) { player.y = objBottom; return true; } return false; } // Handle player movement and collision checks function updateGame() { // Save previous position to fall back on if needed const prevX = player.x; const prevY = player.y; // Update player position based on pressed keys if (keys.ArrowRight) player.x += player.speed; if (keys.ArrowLeft) player.x -= player.speed; if (keys.ArrowDown) player.y += player.speed; if (keys.ArrowUp) player.y -= player.speed; // Check collision with every object in the scene for (const obj of objects) { checkCollision(player, obj); } requestAnimationFrame(updateGame); } // Start the game loop updateGame();
The Fix for Bottom-Top Collision
The main mistake I made earlier was skipping the horizontal overlap check for vertical collisions. For the player’s bottom to properly collide with an object’s top, two things need to be true:
- The player’s bottom edge has crossed the object’s top edge (
playerBottom >= objTop && playerTop < objTop) - There’s actual horizontal overlap between the player and the object (
playerRight > objLeft && playerLeft < objRight)
Without that second condition, the collision would trigger even when the player was completely to the left or right of the object—causing all sorts of janky movement. Adding that horizontal check fixed the issue instantly!
Hope this saves someone else the headache I went through—happy coding!
内容的提问来源于stack exchange,提问作者Josh Berger

