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

CSS关键帧动画执行时调用JS函数检测游戏角色碰撞问题

解决敌人碰撞检测的时机与逻辑问题

首先,咱们先说说你当前代码里的两个核心问题:碰撞检测逻辑太严格和检测时机太稀疏,这俩加起来就是你碰不到碰撞触发的主要原因。


1. 先修复碰撞检测逻辑

你现在用==来判断位置,这在连续动画里几乎不可能触发——敌人是平滑移动的,刚好让$("#enemy").position().top + $("#enemy").height()等于玩家top的瞬间太罕见了。而且你只检测了垂直方向,完全没考虑水平方向的重叠,就算垂直位置对上了,敌人在别的车道也不算碰撞啊!

咱们把碰撞检测改成范围判断,同时覆盖水平和垂直两个方向:

function checkCollision() {
  const enemy = $("#enemy");
  const player = $("#player");
  
  const enemyPos = enemy.position();
  const enemyWidth = enemy.width();
  const enemyHeight = enemy.height();
  const enemyBottom = enemyPos.top + enemyHeight;
  const enemyRight = enemyPos.left + enemyWidth;
  
  const playerPos = player.position();
  const playerWidth = player.width();
  const playerHeight = player.height();
  const playerBottom = playerPos.top + playerHeight;
  const playerRight = playerPos.left + playerWidth;
  
  // 碰撞条件:两个元素在水平和垂直方向都有重叠区域
  const verticalOverlap = enemyBottom > playerPos.top && enemyPos.top < playerBottom;
  const horizontalOverlap = enemyRight > playerPos.left && enemyPos.left < playerRight;
  
  if (verticalOverlap && horizontalOverlap) {
    console.log("碰撞发生了!");
    // 这里可以加碰撞后的逻辑,比如游戏结束、扣分、播放音效等
  }
}

2. 选择正确的检测时机

你之前只在每2秒切换动画的时候检测一次,这中间敌人一直在移动,大部分碰撞瞬间都会被漏掉。咱们有两个更合适的选择:

选项A:用requestAnimationFrame(推荐)

这是浏览器专门为动画/实时交互设计的API,会在浏览器每次重绘前执行,性能更好,能保证每帧都检测一次:

// 定义循环检测函数
function collisionDetectionLoop() {
  checkCollision();
  // 递归调用自己,保持持续检测
  requestAnimationFrame(collisionDetectionLoop);
}

// 在页面加载完成后启动循环
$(document).ready(function() {
  // ... 你原来的其他代码 ...
  
  // 启动碰撞检测循环
  collisionDetectionLoop();
});

选项B:用短间隔的setInterval

如果觉得requestAnimationFrame不好理解,也可以用16ms左右的间隔(接近60帧的刷新率):

$(document).ready(function() {
  // ... 你原来的其他代码 ...
  
  // 每16ms检测一次,接近屏幕刷新率
  setInterval(checkCollision, 16);
});

3. 整合到你的现有代码里

把上面的checkCollision函数放到你的myScript.js里,然后启动检测循环就行。另外,你原来myTimer里的碰撞判断可以删掉了,因为我们已经在持续检测了。

修改后的完整JS代码大概是这样:

$(document).ready(function() {
  //posiziona macchina in fondo al container
  $('#player').css("top", ($("#container").height() - $("#player").height() + "px"));
  var verticalSteps = "159.475";
  var horizontalSteps = "300";
  $('#music').prop("muted", false);
  $('#music').prop("loop", true);
  
  $(document).keydown(function() {
    $("#music")[0].play();
  })
  
  $(document).keydown(function(e) {
    // ... 你原来的键盘控制代码保持不变 ...
  })
  
  // 碰撞检测函数
  function checkCollision() {
    const enemy = $("#enemy");
    const player = $("#player");
    
    const enemyPos = enemy.position();
    const enemyWidth = enemy.width();
    const enemyHeight = enemy.height();
    const enemyBottom = enemyPos.top + enemyHeight;
    const enemyRight = enemyPos.left + enemyWidth;
    
    const playerPos = player.position();
    const playerWidth = player.width();
    const playerHeight = player.height();
    const playerBottom = playerPos.top + playerHeight;
    const playerRight = playerPos.left + playerWidth;
    
    const verticalOverlap = enemyBottom > playerPos.top && enemyPos.top < playerBottom;
    const horizontalOverlap = enemyRight > playerPos.left && enemyPos.left < playerRight;
    
    if (verticalOverlap && horizontalOverlap) {
      console.log("碰撞发生了!");
      // 这里添加碰撞后的处理逻辑
    }
  }
  
  // 启动碰撞检测循环
  function collisionDetectionLoop() {
    checkCollision();
    requestAnimationFrame(collisionDetectionLoop);
  }
  collisionDetectionLoop();
  
  var imagesArray = ["images/240z.png", "images/civicSi.png", "images/porsche.png", "images/r32.png", "images/s2000.png"];
  
  function myTimer() {
    toggleAnimation();
    $("#enemy").attr("src", imagesArray[(Math.floor(Math.random() * imagesArray.length))]);
  }
  
  var myVar = setInterval(myTimer, 2000);
  
  function toggleAnimation() {
    // ... 你原来的切换动画代码保持不变 ...
  }
})

额外小提示

  • 如果你担心requestAnimationFrame在页面隐藏时还在运行,可以加个判断,或者用cancelAnimationFrame在需要的时候停止检测。
  • 可以给碰撞检测加个小“缓冲”,比如稍微缩小一点检测范围,避免边缘的误触,或者根据你的游戏手感调整参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:43:11