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

JS碰撞检测器问题:区分角色撞墙与落地的碰撞差异

解决玩家碰撞方块顶部与侧面的区分问题

嘿,我完全懂你现在的困扰——当前的碰撞逻辑不管玩家是从上方稳稳落到方块上,还是不小心从侧面撞过去,都会直接把玩家“拎”到方块顶部,这肯定不是你想要的效果。咱们来一步步搞定这个问题。

问题根源

你的hitTest函数只做了“是否碰撞”的判断,没有区分碰撞的方向。所以每次检测到碰撞,代码都会执行myPlayer.y = blocks[i].y - myPlayer.h,把玩家强行放到方块顶部,完全忽略了侧面碰撞的情况。

解决方案:判断碰撞方向

核心思路是:当检测到碰撞时,通过计算玩家与方块的重叠区域,结合玩家的移动速度,判断出碰撞的主要方向(顶部/左侧/右侧/底部),再针对不同方向执行对应的逻辑。

修改后的碰撞检测代码

function collisionDetector(){
    // 画布边界碰撞逻辑保持不变
    if(myPlayer.y + myPlayer.h > c.height){ 
        myPlayer.vy = 0;
        myPlayer.ay = 0;
        myPlayer.y = c.height - myPlayer.h;
        myPlayer.onGround = true;
    }
    if(myPlayer.x + myPlayer.w >= c.width){ 
        myPlayer.x = c.width - myPlayer.w;
        myPlayer.vx = 0;
    }
    if(myPlayer.x <= 0){ 
        myPlayer.x = 0;
        myPlayer.vx = 0;
    }

    // 碰撞检测核心函数
    function hitTest(a,b){
        return a.y + a.h > b.y && a.y < b.y + b.h && a.x + a.w > b.x && a.x < b.x + b.w;
    }

    for(var i = 0; i < blocks.length; i++){
        var block = blocks[i];
        if(hitTest(myPlayer, block)){
            // 计算各个方向的重叠量(重叠越小,说明碰撞越先发生在这个方向)
            var overlapTop = (myPlayer.y + myPlayer.h) - block.y; // 玩家底部撞方块顶部的重叠
            var overlapBottom = (block.y + block.h) - myPlayer.y; // 玩家顶部撞方块底部的重叠
            var overlapLeft = (myPlayer.x + myPlayer.w) - block.x; // 玩家右侧撞方块左侧的重叠
            var overlapRight = (block.x + block.w) - myPlayer.x; // 玩家左侧撞方块右侧的重叠

            // 确定碰撞的主要方向
            var minOverlap = Math.min(overlapTop, overlapBottom, overlapLeft, overlapRight);

            // 根据不同方向处理碰撞
            if(minOverlap === overlapTop && myPlayer.vy > 0){
                // 顶部碰撞:玩家从上方落到方块上
                myPlayer.y = block.y - myPlayer.h;
                myPlayer.vy = 0; // 停止垂直运动
                myPlayer.onGround = true;
            } else if(minOverlap === overlapLeft){
                // 左侧碰撞:玩家撞向方块右侧
                myPlayer.x = block.x - myPlayer.w;
                myPlayer.vx = 0; // 停止水平运动
            } else if(minOverlap === overlapRight){
                // 右侧碰撞:玩家撞向方块左侧
                myPlayer.x = block.x + block.w;
                myPlayer.vx = 0; // 停止水平运动
            } else if(minOverlap === overlapBottom){
                // 底部碰撞:玩家从下方顶到方块(比如跳起来撞方块底部)
                myPlayer.y = block.y + block.h;
                myPlayer.vy = 0;
            }
        }
    }
}

代码解释

  1. 重叠量计算:通过计算玩家和方块在四个方向上的重叠长度,判断哪个方向是碰撞的“主要来源”——重叠量最小的方向,就是玩家最先接触到方块的方向。
  2. 速度判断:在顶部碰撞时额外检查myPlayer.vy > 0(玩家正在向下运动),避免玩家从方块下方穿过时被误判为落地。
  3. 针对性处理:不同方向的碰撞对应不同的位置修正和速度重置,比如侧面碰撞只修正水平位置和速度,不会触发onGround状态。

额外建议

  • 记得在玩家跳跃或者离开方块时,把myPlayer.onGround设为false,否则玩家会一直处于“可跳跃”状态。
  • 如果你觉得重叠量的方式不够精准,也可以记录玩家碰撞前的位置(比如在更新玩家位置前保存prevX和prevY),通过比较碰撞前后的位置来判断移动方向,这也是一种常用的碰撞方向判断方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:38:44