Java 使球在画布上反弹
我已经写了一些代码,这些代码应该是一个简单的乒乓球游戏的基础。这很有效,但我不明白为什么。它不应该起作用。我希望有人能给我一些我所缺少的关于它为什么起作用的见解 我的画布中有以下概念(左上角有(0,0)): 球总是以0到180度的角度反弹。我以画布的底部为基础。左边是0度,右边是180度。如果球在墙上反弹,球的角度(Java 使球在画布上反弹,java,swing,collision-detection,java-2d,Java,Swing,Collision Detection,Java 2d,我已经写了一些代码,这些代码应该是一个简单的乒乓球游戏的基础。这很有效,但我不明白为什么。它不应该起作用。我希望有人能给我一些我所缺少的关于它为什么起作用的见解 我的画布中有以下概念(左上角有(0,0)): 球总是以0到180度的角度反弹。我以画布的底部为基础。左边是0度,右边是180度。如果球在墙上反弹,球的角度(ball\u angle)将变为180-ball\u angle度。球的轨迹由另外两个变量(x_-traj和y_-traj)定义,指示每个轴上的方向 我没有得到的部分是ballHit
ball\u angle
)将变为180-ball\u angle
度。球的轨迹由另外两个变量(x_-traj
和y_-traj
)定义,指示每个轴上的方向
我没有得到的部分是ballHits()
方法。如果球从右侧以度数(例如100度)撞击赛琳,则应以度数80反弹。球是从右边来的,所以x轨迹是负数。我们在球拍上弹跳,因此球会下降而不是上升,因此我们将y_traj
从负(上升)改为正(下降)。球仍然会向右移动,所以我们要巧妙地保持这个方向
第二种情况是当球击中左墙时。球又从右边来了,所以我们知道traj_x
是负数。我们弹起使球回到右边,因此traj_x
应乘以-1
,使其再次为正(向右移动)。无论我们是从上面还是从下面撞到墙,在墙反弹后,我们仍然沿着同一方向前进。我们不更改traj_y
变量
但是,下面是工作代码。当我碰到左边或右边的墙时,我不需要改变任何变量。谁能给我解释一下原因吗
如果需要,可以在上找到完整的编译项目
将球移动到新坐标的代码:
private void updateBall()
{
// http://gamedev.stackexchange.com/questions/73593/calculating-ball-trajectory-in-pong
// If the ball is not hitting anything, we simply move it.
// http://en.wikipedia.org/wiki/Polar_coordinate_system
if (ballHits())
{
// Bounce the ball off the wall.
ball_angle = 180 - ball_angle;
}
// http://en.wikipedia.org/wiki/Polar_coordinate_system
// Convert the angle to radians.
double angle = (ball_angle * Math.PI) / 180;
// Calculate the next point using polar coordinates.
ball_x = ball_x + (int) (x_traj * BALL_STEPSIZE * Math.cos(angle));
ball_y = ball_y + (int) (y_traj * BALL_STEPSIZE * Math.sin(angle));
System.out.printf("Ball: (%d,%d) @ %d\n", ball_x, ball_y, ball_angle);
}
确定我们是否撞到墙的代码:
private boolean ballHits()
{
// If we came out of bounds just reset it.
ball_y = Math.max(0, ball_y);
ball_x = Math.max(0, ball_x);
// Check to see if it hits any walls.
// Top
if(ball_y <= 0)
{
System.out.println("Collision on top");
y_traj *= -1;
x_traj *= -1;
return true;
}
// Left
if(ball_x <= 0)
{
System.out.println("Collision on left");
//y_traj *= -1;
//x_traj *= -1;
return true;
}
// Right
if(ball_x >= B_WIDTH)
{
System.out.println("Collision on right");
//y_traj *= -1;
//x_traj *= -1;
return true;
}
// Bottom
if(ball_y >= B_HEIGHT)
{
System.out.println("Collision on bottom");
y_traj *= -1;
x_traj *= -1;
return true;
}
return false;
}
private boolean ballHits()
{
//如果我们出界,就重新设置它。
ball_y=Math.max(0,ball_y);
ball_x=Math.max(0,ball_x);
//检查它是否碰到任何墙壁。
//顶
如果(球y=B高度)
{
System.out.println(“底部碰撞”);
y_traj*=-1;
x_traj*=-1;
返回true;
}
返回false;
}
它的工作方式很复杂,因为当角度>90°时,余弦为负。
如果球先击中底部或顶部,那么让他从不同的初始轨迹和角度出发是行不通的
编辑:我原以为这样做可以,但在纸上做证明我错了,这是一种奇怪的方式,但它按预期工作。我会调查一下,看看有没有办法
编辑2:在[88-92]范围内的起始角度是否可行?若要更快获得更好的帮助,请发布一个(最小的、完整的、可验证的示例)。另请参见。嗯,我已尝试使其在角度>内反弹,并在顶部和底部分别反弹<90°,但似乎效果不错。但我知道它来自余弦。不过,我会在纸上复制一些场景。我编辑了我的答案,你能告诉我这是否有效吗?是的,这非常有效。有点奇怪。但是,我想知道,那么惯用的方法是什么呢?你可以只使用角度,然后用它们的符号得到轨迹的变化,但这意味着你必须重新考虑你的角度范围[0-180]是不够的,你需要[0-360]的范围,你也可以保持你的轨迹,在余弦上加一个abs()。对于你必须放置一个由球刚刚击中的一侧确定的偏移角度,它可能是,右侧90°,顶部180°,左侧270°,底部0,你不必再为x_traj和y_traj费心了。