本文详解为何原始碰撞检测无法准确计分,并提供基于空间状态机的跳跃判定方案,通过分离X轴重叠与Y轴位置关系,精准识别“成功越过障碍物”事件,避免误判与重复计分。
本文详解为何原始碰撞检测无法准确计分,并提供基于空间状态机的跳跃判定方案,通过分离X轴重叠与Y轴位置关系,精准识别“成功越过障碍物”事件,避免误判与重复计分。
在2D无限跑酷类游戏中(如Chrome小恐龙),得分逻辑不应依赖“碰撞发生”,而应基于“障碍物被成功避开”这一状态变化。原始代码中 detectCollision() 仅判断矩形相交,导致两种关键误判:
updateScore(),造成分数暴增。根本问题在于:“跳跃成功”不是瞬时碰撞事件,而是跨越障碍物的完整过程——需跟踪障碍物从右侧入场、水平掠过玩家、直至重置的整个生命周期。
我们引入三个布尔标志位,构建轻量级状态机,精确刻画障碍物与玩家的交互阶段:
| 状态变量 | 含义 | 触发条件 |
|---|---|---|
jumpStarted |
障碍物X方向已进入玩家活动区(即左右边界重叠) | playerRect.left < obstacleRect.right && playerRect.right > obstacleRect.left |
jumpFull |
障碍物已完全通过玩家(X方向不再重叠),且全程未发生Y方向碰撞 |
jumpStarted === true 且当前X无重叠 |
collision |
X重叠期间,Y方向也发生重叠(即真实碰撞) | X重叠 + playerRect.top < obstacleRect.bottom && playerRect.bottom > obstacleRect.top
|
关键设计原则:
? 状态仅在障碍物重置时清空(即 obstacle.style.right = '0' 时),确保每个障碍物周期独立判定;
? jumpFull 和 collision 互斥且不可逆:一旦任一成立,该障碍物周期内不再响应后续检测。
let jumpStarted = false, jumpFull = false, collision = false;function moveObstacle() {const speed = 5;let obstaclePosition = parseInt(getComputedStyle(obstacle).getPropertyValue('right'));if (obstaclePosition < window.innerWidth) {obstacle.style.right = `${obstaclePosition + speed}px`;} else {// 障碍物重置:触发最终判定并清空状态if (jumpStarted && !collision && !jumpFull) {updateScore(); // 成功越过:X重叠过 + 无Y碰撞 + 未标记jumpFull → 补充计分}jumpStarted = jumpFull = collision = false; // 重置周期obstacle.style.right = '0';}detectCollision();}function detectCollision() {if (collision || jumpFull) return; // 状态锁定,避免重复处理const playerRect = player.getBoundingClientRect();const obstacleRect = obstacle.getBoundingClientRect();const xOverlap = playerRect.left < obstacleRect.right && playerRect.right > obstacleRect.left;if (xOverlap) {// X重叠中:检查Y方向是否碰撞const yOverlap = playerRect.top < obstacleRect.bottom && playerRect.bottom > obstacleRect.top;if (yOverlap) {collision = true;updateCollisions();} else {jumpStarted = true; // 进入“可能成功”阶段}} else if (jumpStarted) {// X重叠已结束,且此前已标记jumpStarted → 确认成功越过jumpFull = true;updateScore();}}
getBoundingClientRect() 在每帧调用开销可控,但若后续扩展复杂物理,建议缓存矩形数据或使用 requestAnimationFrame 替代 setInterval;setTimeout 控制跳跃动画时长(500ms)需与CSS transition 或 animation 严格同步,否则Y坐标检测可能失准;#player 和 #obstacle 添加 outline: 2px solid red,直观观察重叠区域。通过将“得分”语义从“无碰撞”修正为“X重叠期间全程无Y碰撞”,本方案彻底解决了原始逻辑中计分滞后、重复、遗漏三大缺陷,为可扩展的游戏机制奠定坚实基础。
tlwdr7650路由器没有wps按钮(tlwdr7650路由器没有wps按钮怎么办)
tlwdr7632扩展器电脑怎么设置(tlwdr7632扩展器电脑设置方法)
tlwda6332re安装教程(tlwda6332re如何安装)
tlwdr7632扩展器手机怎么设置(tlwdr7632扩展器手机设置方法)
tlxdr3010怎么设置网速快(tlxdr3010网速快设置方法)
tlwdr5620易展版怎么克隆(tlwdr5620易展版克隆方法)