JS:当球移动得更快时,碰撞检测不起作用

Posted

技术标签:

【中文标题】JS:当球移动得更快时,碰撞检测不起作用【英文标题】:JS: Collision Detection doesn't work when Ball is moving faster 【发布时间】:2018-03-23 19:41:43 【问题描述】:

我目前正在尝试学习 javascript,并遵循了有关编程 Breakout 游戏的教程。我在教程之后添加了一些东西。我添加的一件事是随着比赛的进行,球会变得更快。现在我有以下问题。

我的球拍厚度为 10 像素,但在某些时候球的移动速度超过了每帧/更新 10 像素。正因为如此,它经常直接穿过桨板,因为它会反弹。我已经将 FPS/UPS 从 60 翻倍到 120,并将球速除以 2。

当然我可以进一步提高 fps,但我希望有一个更高效/优雅的版本来处理这个问题。

这是我用来让球从桨上反弹的函数:

function ballPaddleHandling() 
    var paddleTopEdgeY = canvas.height-PADDLE_DIST_FROM_EDGE;
    var paddleBottomEdgeY = paddleTopEdgeY + PADDLE_THICKNESS;
    var paddleLeftEdgeX = paddleX;
    var paddleRightEdgeX = paddleLeftEdgeX + PADDLE_WIDTH;
    if( ballY > paddleTopEdgeY && // below the top of paddle
        ballY < paddleBottomEdgeY && // above bottom of paddle
        ballX > paddleLeftEdgeX && // right of the left side of paddle
        ballX < paddleRightEdgeX)  // left of the left side of paddle

        ballSpeedY *= -1;

        var centerOfPaddleX = paddleX+PADDLE_WIDTH/2;
        var ballDistFromPaddleCenterX = ballX - centerOfPaddleX;
        ballSpeedX = ballDistFromPaddleCenterX * 0.35;

        if(bricksLeft == 0) 
            gameWon = true;
            //brickReset();
         // out of bricks
     // ball center inside paddle
 // end of ballPaddleHandling

如果您想查看我的所有代码,可以在此处进行:https://jpst.it/1cHKn

【问题讨论】:

通常我们做的是计算物体(桨)是否在主物体(球)的路径中而不是物体是否与主物体重叠对象。这将问题简化为两条线是否重叠。在您的情况下,您必须考虑桨叶上的 4 条线。 ballY += ballSpeedY; 那部分可以让球通过桨。在更换ballY之前,您应该检查是否会发生碰撞。 @James 如果球每次移动超过一个桨高度,它可能永远不会“碰撞”(在修改 Y 之前高于桨,之后低于它) @IrkenInvader 对,这就是我的观点。但是在实际移动球之前,很容易检查球是否会穿过球拍。 我认为他们的意思是为球的开始/停止位置和每个桨角开始/停止构建线。 (开始 = 帧前的位置,停止 = 绘制帧后的结束位置)超级有用的糟糕绘图:i.imgur.com/yCzPrww.png 【参考方案1】:

也许你的问题是:当你把球放在新位置时,新坐标在桨下,从一帧到另一帧,所以球永远不会通过桨,它只是帧之间的瞬移到桨之后。

也许你需要:计算球的轨迹,当检测到球将在桨Y位置之后,从一帧到另一帧,检查桨是否在中间的轨迹并将球放在桨的上限的新位置

【讨论】:

【参考方案2】:

您可以为此使用射线命中测试。 为简化起见,您只需对桨的上表面进行测试。

function ballPaddleHandling() 
    var paddleTopEdgeY = canvas.height-PADDLE_DIST_FROM_EDGE;

    // calculate balls previous position
    var px = ballX - ballSpeedX
    var py = ballY - ballSpeedY

    // calculate trajectory angle
    var angle = getAngle(px,py,ballX,ballY) 

    // calulcate the length of the ray to test
    var length = getDist(px,py,ballX,ballY)

    // define the line to test as the upper face of the paddle
    var line = x:paddleX, y:paddleTopEdgeY, w:PADDLE_WIDTH

    // get position of hit, or false if no hit occured
    var hit_x = rayHitTestHorizontalLine(px,py,angle,length,line)

    if(hit_x!==false)
        ballSpeedY *= -1;

        var centerOfPaddleX = paddleX+PADDLE_WIDTH/2;
        var ballDistFromPaddleCenterX = hit_x - centerOfPaddleX;
        ballSpeedX = ballDistFromPaddleCenterX * 0.35;
    


function rayHitTestHorizontalLine(px,py,angle,length,line)
    var dist = (line.y - py)/(-Math.cos(angle))
    if(dist>length)
        return false
    var hit_x = px+Math.sin(angle)*dist
    if(hit_x>=line.x && hit_x<=line.x+line.w)
        return hit_x
    else
        return false


function getAngle(x1,y1,x2,y2)
    return Math.atan2(y2-y1,x2-x1) + Math.PI/2


function getDist(x1,y1,x2,y2)
    return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))

让我知道它是否有效,我自己无法真正测试它。

【讨论】:

以上是关于JS:当球移动得更快时,碰撞检测不起作用的主要内容,如果未能解决你的问题,请参考以下文章

SKPhysicsJoint:接触和碰撞不起作用

精灵面具碰撞不起作用(直接碰撞工作)

添加炸弹数量,当玩家碰撞时不起作用

为啥在我的 JavaScript 浏览器游戏中弹跳 Actor 不起作用?

Sprite比右侧pygame移动得更快

url中的哈希#时jquery移动表单提交不起作用