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:当球移动得更快时,碰撞检测不起作用的主要内容,如果未能解决你的问题,请参考以下文章