You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript游戏:玩家与物体的底部-顶部碰撞问题及修复

Fixed Collision Detection for All Directions in Player Movement Game

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:

  1. The player’s bottom edge has crossed the object’s top edge (playerBottom >= objTop && playerTop < objTop)
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:12:57