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

自制Pac-Man游戏碰撞检测失效问题求助

解决Pac-Man与容器Shell的碰撞检测异常问题

看起来你遇到的核心问题是边界计算逻辑错误——你用了固定像素值(比如85、130)和错误的尺寸偏移来判断碰撞,而没有考虑容器shell的实际视口位置和动态尺寸(毕竟它用的是百分比宽高)。咱们一步步来修复:

问题根源拆解

  1. 顶部/左侧看似正常的假象:你直接用了shell的top:85px和left:130px作为边界阈值,但这只在当前屏幕尺寸下巧合生效,一旦窗口缩放就会失效。
  2. 右侧/底部的提前碰撞:你计算的width = shell宽度 - pac宽度,然后用leftRight >= width +35判断右边界,这里的+35完全是硬编码,没有考虑shell自身的left偏移(130px),所以实际右边界应该是shell的left + shell的宽度 - pac的宽度,而不是你现在的计算方式。同理底部边界也犯了同样的错误。
  3. 固定定位的坐标逻辑:pac和shell都是position:fixed,它们的top/left都是相对于浏览器视口的,所以碰撞判断必须基于两者的视口坐标,不能孤立计算尺寸差。

修复方案:用getBoundingClientRect()简化边界计算

getBoundingClientRect()可以直接获取元素在视口的精确位置(top、left、right、bottom),避免手动计算的误差。咱们重写碰撞检测逻辑:

修改后的JavaScript代码

function move() {
  // 获取元素的DOM对象(比反复用id更高效)
  const pac = document.getElementById('pac');
  const shell = document.getElementById('shell');

  // 获取两者的视口位置和尺寸
  const pacRect = pac.getBoundingClientRect();
  const shellRect = shell.getBoundingClientRect();

  // 初始化新位置(基于当前位置)
  let newTop = pacRect.top;
  let newLeft = pacRect.left;

  // 根据方向键更新位置
  if (arrowKey === 40) { // 下
    newTop += 2;
  } else if (arrowKey === 38) { // 上
    newTop -= 2;
  } else if (arrowKey === 37) { // 左
    newLeft -= 2;
  } else if (arrowKey === 39) { // 右
    newLeft += 2;
  }

  // 碰撞检测:确保Pac-Man完全在Shell内部
  // 顶部边界:Pac的top不能小于Shell的top
  if (newTop < shellRect.top) {
    newTop = shellRect.top;
  }
  // 底部边界:Pac的bottom(newTop + pac高度)不能大于Shell的bottom
  if (newTop + pacRect.height > shellRect.bottom) {
    newTop = shellRect.bottom - pacRect.height;
  }
  // 左侧边界:Pac的left不能小于Shell的left
  if (newLeft < shellRect.left) {
    newLeft = shellRect.left;
  }
  // 右侧边界:Pac的right(newLeft + pac宽度)不能大于Shell的right
  if (newLeft + pacRect.width > shellRect.right) {
    newLeft = shellRect.right - pacRect.width;
  }

  // 更新Pac-Man的位置(注意要转换为相对于视口的top/left,因为是fixed定位)
  pac.style.top = `${newTop}px`;
  pac.style.left = `${newLeft}px`;
}

关键改进点

  • 用DOM对象替代重复的getStyle调用:直接获取元素对象,减少不必要的DOM查询,性能更好。
  • getBoundingClientRect()的精准性:不管窗口怎么缩放,都能拿到元素的实时视口坐标,彻底解决百分比尺寸带来的适配问题。
  • 边界逻辑更直观:直接比较Pac-Man的边界与容器的边界,比如底部边界判断newTop + pac高度 > shell底部,这样Pac-Man的底部不会超出容器底部,完全符合视觉预期。
  • 移除硬编码的像素值:再也不用依赖85、130这种固定值,代码更健壮。

额外建议

  1. 如果你之前的getStyle函数是自己实现的,确保它能正确获取计算后的样式(比如用window.getComputedStyle),不过用getBoundingClientRect()会更省心。
  2. 测试时可以给shell加个背景色或者边框,直观观察Pac-Man的边界是否真的贴合容器。

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:57:09