31. Rack ‘Em Up

来源:互联网 发布:怎么安装java 编辑:程序博客网 时间:2024/06/05 16:41

In recent posts, we’ve been building a pool game. One aspect of pool that we need to implement is positioning the balls for the start. There are fifteen balls to line up in a tightly packed triangle. But to actually put down this triangle in a program, we need to know the exact coordinates of the balls! And it turns out, this needs some maths too.

Rows

You can think of the triangle of balls as being a series of rows, each with one ball more than the last:

Original photo by Sam, CC BY 2.0

Each ball in a left-hand row has two balls behind it in the right-hand row. The gap between the balls on the right must align with the centre of the ball on the left (the dotted line below), and the balls nestle so close that the distance between each pair must be the same (the solid line below):

We can now start labelling the distances on this diagram. If the balls exactly touched then the distance between the two centres would be two times the ball radius. But due to the way our collision detection will work, it’s best if the balls don’t completely touch, but instead have a small gap. So we’ll define\text{radiusPlus} to be slightly bigger than the ball radius, which will give us this gap. Then:

So we know the vertical distances between the centres. All we need now is the horizontal distance (i.e. the length of the dashed line above). This is actually just a case for Pythagoras:

\text{horizDist}^2 + \text{radiusPlus}^2 = (2 \times \text{radiusPlus})^2
\text{horizDist}^2 + \text{radiusPlus}^2 = 4 \times \text{radiusPlus}^2
\text{horizDist}^2  = 3 \times \text{radiusPlus}^2
\text{horizDist}  = \sqrt{3} \times \text{radiusPlus}

Here’s the code:

 final int radiusPlus = 25 + 2; //radius + 2 for (int row = 0; row < 5; row++) {     int startY = 300 - row * radiusPlus; // Each row starts radiusPlus further up     int x = 500 + (int)(row * (Math.sqrt(3) * (double)radiusPlus));     for (int ball = 0; ball < row + 1; ball++)     {        addObject(new PoolBall(Color.RED), x, startY + ball * (2 * radiusPlus));        // Each ball in a row is 2*radiusPlus further down ^^     } }

This gives the finished layout:

I haven’t uploaded the scenario because it’s only the small bit of code above that has been added. Next time we’ll look at adding collision detection and collision resolution.