Javascript JS:碰撞检测不会';当球移动得更快时,它不工作

Javascript JS:碰撞检测不会';当球移动得更快时,它不工作,javascript,performance,collision-detection,frame-rate,game-loop,Javascript,Performance,Collision Detection,Frame Rate,Game Loop,我目前正在尝试学习JavaScript,并学习了一个关于编写突破游戏的教程。我在教程之后添加了一些东西。我补充的一点是,随着比赛的进行,球会变得更快。现在我有以下问题 我的球拍是10px厚的,但在某个点上,每帧/更新球的移动速度超过10px。正因为如此,它经常直接穿过桨叶,而不是从桨叶上弹起。我已经将FPS/UPS从60增加到了120,并将球的速度除以2 当然,我可以增加更多的fps,但我希望有一个更有效/优雅的版本来解决这个问题 以下是我用来让球从球拍上弹起的功能: function ball

我目前正在尝试学习JavaScript,并学习了一个关于编写突破游戏的教程。我在教程之后添加了一些东西。我补充的一点是,随着比赛的进行,球会变得更快。现在我有以下问题

我的球拍是10px厚的,但在某个点上,每帧/更新球的移动速度超过10px。正因为如此,它经常直接穿过桨叶,而不是从桨叶上弹起。我已经将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
函数处理(){
var palletopedgey=canvas.height-palle\u DIST\u与边缘的距离;
var桨叶底部边缘=桨叶顶部边缘+桨叶厚度;
var PapperLeftedgex=Papperx;
var PapperRightedgex=PapperLeftedgex+桨叶宽度;
如果(球>桨叶顶部)在桨叶顶部下方&&//
巴利<桨叶底部边沿&//桨叶底部上方
ballX>桨叶左边缘&&//桨叶左侧的右侧
ballX<桨叶右边缘){//桨叶左侧的左侧
ball*=-1;
var centerOfPaddleX=桨叶X+桨叶U宽度/2;
var BalldistFromPackerCenterX=ballX-Padlex的中心;
ballSpeedX=球拍中心的球差x*0.35;
if(bricksleet==0){
gameWon=true;
//brickReset();
}//用砖头
}//球心内侧球拍
}//球拍处理结束

如果你想查看我的所有代码,你可以在这里这样做:

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

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

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

< P>你可以使用射线命中测试。 为了简化它,您只需对桨叶的上表面进行测试

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))
}
函数处理(){
var palletopedgey=canvas.height-palle\u DIST\u与边缘的距离;
//计算前一位置的球数
var px=ballX-ballSpeedX
var py=ballY-ballY
//计算弹道角
变量角度=获取角度(px,py,ballX,ballY)
//计算要测试的光线长度
变量长度=getDist(px,py,ballX,ballY)
//将要测试的线定义为桨叶的上表面
变量行={x:pallex,y:palletopedgey,w:palle_WIDTH}
//获取命中位置,如果未命中,则为false
var hit_x=光线HitTestHorizontalline(px,py,角度,长度,直线)
如果(命中x!==false){
ball*=-1;
var centerOfPaddleX=桨叶X+桨叶U宽度/2;
var BalldistFromPackerCenterX=点击次数x-点击次数中心;
ballSpeedX=球拍中心的球差x*0.35;
}
}
函数rayHitTestHorizontalLine(px、py、角度、长度、线){
var dist=(line.y-py)/(-Math.cos(角度))
如果(距离>长度)
返回错误
var hit_x=px+数学正弦(角度)*距离

如果(hit\u x>=line.x&&hit\u通常我们要做的是计算对象(桨)是否在主对象(球)的路径上而不是物体是否与主物体重叠。这就简化了两条线是否重叠的问题。在你的情况下,桨上有4条线是你必须考虑的。<代码> Bal++= BalthyDy;< /代码>这一部分可以将球移到桨叶上。你应该检查在你改变BALY之前是否会发生碰撞。@杰姆斯如果球每滴答移动超过一个球拍高度,它可能永远不会“碰撞”(修改Y之前球拍上方,修改Y之后球拍下方)@IrkenInvader对,这是我的观点。但在实际移动之前,很容易检查球是否会穿过球拍。我认为他们的意思是为球的开始/停止位置和每个球拍角的开始/停止位置构造线。(开始=在帧之前的位置,停止=在绘制帧之后结束的位置)超级有帮助的坏油漆图纸: