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

时间:2018-03-23 19:41:44

标签: javascript performance collision-detection frame-rate game-loop

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

我的球拍厚度为10px,但在某些时候球的移动速度超过每帧10px /更新。因此,它经常直接通过从其反弹的桨叶。我已经将FPS / UPS从60加倍到120,并将球速除以2.

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

这是我用来让球从球拍上反弹的功能:

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

2 个答案:

答案 0 :(得分:1)

也许你的问题是:当你把球放在新位置时,新的坐标位于球拍下方,从一帧到另一帧,所以球从未通过球拍,它只是在帧之间传送到桨之后。

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

答案 1 :(得分:1)

您可以使用光线命中测试。 为了简化它,您只需测试桨的上表面。

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))
}

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