33. 实现桌球的反弹

来源:互联网 发布:xampp mac 修改根目录 编辑:程序博客网 时间:2024/04/30 11:40

33.Making Your Balls Bounce

In this post, we will finally complete our pool game. We’ve already seenhow to detect collisions between balls: we just need to check if two circles are overlapping. We’ve also seenhow to resolve a collision when bouncing a ball off a wall(i.e. one moving object and one stationary). The final piece of the puzzle is just to put it all together in the case of two moving balls.

在这篇文章中,我们将最终完成我们的桌球游戏。我们已经看到如何检测球之间的碰撞:我们只需要检查两个圆是重叠的。我们也看到了如何解决当球与墙壁反弹时的碰撞(即一个移动对象和一个固定对象)。最后的难题是只是将其结合在一起在两个移动球的情形下。

Bouncy Balls

球之间的反弹

The principle behind collision resolution for pool balls is as follows. You have a situation where two balls are colliding, and you know their velocities (step 1 in the diagram below). You separate out each ball’s velocity (the solid blue and green arrows in step 1, below) into two perpendicular components: the component heading towards the other ball (the dotted blue and green arrows in step 2) and the component that is perpendicular to the other ball (the dashed blue and green arrows in step 2).

桌球间的碰撞解决方案背后的原理如下。你有一个情境,两球的碰撞,你知道他们的速度(步骤1在下图)。你分离出每一球的速度(在步骤1中的蓝色和绿色的实线箭头,下图)分成两个垂直分量:朝着其他球(在步骤2中的蓝色和绿色的虚线箭头)的分量以及垂直于其他球(在步骤2中的蓝色和绿色的折线箭头)的分量。

This is the same principle as we used when colliding with a wall. The difference here is that while you still leave alone the components that are parallel, instead of reversing each ball’s component that heads towards the other ball, youswap the components between the two balls (as we move from step 2 to step 3), then finally recombine the velocities for each ball to leave the result (step 4):

我们使用壁碰撞同样的原理不同之处在于仍然保持各自的平行分量的同时,交换两个球的相对分量(正如我们从步骤2转到步骤3所示的那样),而不是反转每个球朝着另一个球的分量,接下来为每个球重新合成速度来得到结果(步骤4):

This means that the code we need is actually only a small modification on the previous code for wall collision:

这意味着我们需要的代码实际上只要在前面的墙壁碰撞代码之上做一点小小的修改:

                double towardsThem = distAlong(b.getMoveX(), b.getMoveY(), distX, distY);                double towardsMe = distAlong(c.getMoveX(), c.getMoveY(), distX, distY);                                double myOrtho = distAlong(b.getMoveX(), b.getMoveY(), distY, -distX);                double theirOrtho = distAlong(c.getMoveX(), c.getMoveY(), distY, -distX);                b.setMove(towardsMe * distX + myOrtho * distY,                          towardsMe * distY + myOrtho * -distX);                c.setMove(towardsThem * distX + theirOrtho * distY,                          towardsThem * distY + theirOrtho * -distX);
You can have a play with the relevant scenario over on the Greenfoot site.

你可以在Greenfoot网站上玩一下相应的游戏剧本。

Programming Challenge Task

编写挑战任务

The scenario needs a bit more work to make a finished game: interface polish, a second player (with two types of balls, and a black 8-ball) and scoring. Feel free to take the code and finish off the game.

这个游戏剧本需要更多的一点工作去成为一个完整的游戏:平滑的界面,第二个玩家(使用两种类型的球,以及一个黑8球)以及计分。任意使用代码同时完成游戏。

Mathematical Challenge Task

The collision resolution is not as precise as it could be. Because it uses the destination position at the end of the frame for resolving the collision, two balls which move towards each quickly can potentially bounce off at a strange angle. This could be fixed by modelling a ball’s position as:

\begin{pmatrix} x \\ y \end{pmatrix} = \begin{pmatrix} \text{startX} \\ \text{startY} \end{pmatrix} + t \times \begin{pmatrix} \text{moveX} \\ \text{moveY} \end{pmatrix}

Where t varies from 0 (at the start of the frame) to 1 (at the end). You can then find at which value of t the two balls collide (building on thecircle collision work), and use these positions of the exact collision when resolving the collision. If you feel like a challenge, have a go at using that idea to improve the collision mechanism.

原创粉丝点击