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

原生vanillaJS网页游戏两个img元素碰撞检测失效问题求助

问题原因

  • 你的碰撞检测代码仅在页面首次加载时执行一次,后续通过方向键移动角色后不会重新运行检测逻辑,所以一直输出首次检测的结果
  • 直接读取DOM元素的.x/.y属性获取坐标不可靠,该属性不是元素实时渲染后的实际位置,不同定位方式下会出现取值偏差

修复方案

1. 核心逻辑调整

使用getBoundingClientRect()获取元素实时的视口坐标和尺寸,把碰撞检测封装为函数,每次角色移动后/逐帧调用检测:

// 获取两个元素
const perso = document.querySelector('.perso')
const obstacle = document.querySelector('.obstacle')

// 封装碰撞检测函数
function checkCollision() {
  // 拿到实时位置和尺寸
  const rect1 = perso.getBoundingClientRect()
  const rect2 = obstacle.getBoundingClientRect()

  const isCollision = rect1.left < rect2.left + rect2.width
    && rect1.left + rect1.width > rect2.left
    && rect1.top < rect2.top + rect2.height
    && rect1.top + rect1.height > rect2.top

  if (isCollision) {
    console.log("collision")
    // 取消注释即可跳转页面
    // window.location.href = 'htmlpage1.html'
  } else {
    console.log("no collision")
  }
}

// 逐帧检测碰撞,也可以选择在每次键盘移动角色后直接调用checkCollision()
function loop() {
  checkCollision()
  requestAnimationFrame(loop)
}
loop()

// 方向键移动示例,如果你已有完整移动逻辑可以忽略这部分,只需在移动后调用checkCollision()即可
let posX = 0, posY = 0
document.addEventListener('keydown', e => {
  const step = 10 // 每次移动的步长
  switch(e.key) {
    case 'ArrowUp': posY -= step; break
    case 'ArrowDown': posY += step; break
    case 'ArrowLeft': posX -= step; break
    case 'ArrowRight': posX += step; break
  }
  perso.style.transform = `translate(${posX}px, ${posY}px)`
})

2. 可选优化

你的角色当前是relative定位,使用transform做移动性能更好,不会触发页面重排,比修改top/left属性的运行效率更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 13:06:02