|
There are many means to detect collisions in a 3D environment ranging from the simple to the profound. When creating 3D
Asteroids, I realized could achieve effective collision detection with on of the simplest collision detection algorithms,
ball to ball.
Ball to Ball Collision Detection
Ball to Ball Collision Detection defines a spherical area (radius) around an object in 3 space. Collisions occur when
the distance between the centers of two objects is less the sum of their radius. So, let's say (X1, Y1, Z1) is the coordinates
for the center the first object with radius R1, and (X2, Y2, Z2) is the coordinates for the center of the second object with
radius of R2. Then, the distance between them is d = sqrt((X1-X2)² + (Y1-Y2)² + (Z1-Z2)²). So, if D<(R1+R2), a collision occurred.
The Code
For this lesson, code is implemented to detect collisions between bullets and rocks. If the is a collision, both the bullet and
the rock are removed. Code is added to add eight new rocks whenever all the rocks are rocks are removed.
private void collisionBulletRock()
{ Actor aBullet, aRock;
for(int b=0; b<aBullets.size(); b++)
{ aBullet = (Actor)aBullets.get(b);
for(int r=0; r<aRocks.size(); r++)
{ aRock = (Actor)aRocks.get(r);
if(gEngine.collisionBallBall(aBullet, aBullet.model.minRadius,
aRock, aRock.model.minRadius))
{ gEngine.killActor(aBullet);
gEngine.killActor(aRock);
aBullets.remove(aBullets.indexOf(aBullet));
aRocks.remove(aRocks.indexOf(aRock));
addScore(100);
b=aBullets.size();
r=aRocks.size();
} } } }
Add this method to your class. It will remove rocks and bullets, if they collide. It may not be obvious how. So, let's look
at the code. First aBullet and aRock are declared as Actors. They are needed to store temporary references to an object while we iterrate
through lists of objects. So, the next four lines implement what was just mentioned. The list of bullets and rocks are traversed in a
nested for loop while temporary references to objects in these lists are stored in aBullet and aRock. Then, gEngine.CollisionBallBall()
is called to determine if aBullet collided with aRock. Notice, that I used the minRadius field of the model class. This is automatically
computed when you load the model. There is also maxRadius. These fields store the points nearest and furthest from the origin. Obviously,
if the origin of the model is not centered, collisionBallBall will not be very applicable. Also, for objects like the player's space craft
that have points very near the origin, maxRadius is preferred. Anyhow, if a collision is detected, we remove the actors from with the
killActor() method. This removes the actor from the game engine. However, our local actor lists, aBullets and aRocks, still contain a
reference to them. So, we need to remove those references from those lists. Next, 100 points are added to the score. And finally, we force
the for loops to terminate. This must be done because we changed the aRocks and aBullets lists. Of course, this also prevents further collision
detection between bullets and rocks. Any additional collision between bullets and rocks will have to be caught the next time this method
is called. Incidentally, this does not detract from game play and it actually aids performance.
while(!stop)
{ doKeyboard();
gEngine.updateActors();
collisionBulletRock(); // *** New Line ***
if(aRocks.size()==0) addRocks(8); // *** New Line ***
gEngine.sDisplay();
sleep(10);
} } }
There are only two lines left to add to the class and they should be added as shown to the run() method. The first one calls the
method that was just added and the second adds eight new rocks whenever all the rocks are gone.
Your applet should now displays four rocks moving across the display. The player's space craft is visible, centered in the display. Pressing
shift will fire bullets from the space craft. The left and right arrows will rotate the craft. The up and down arrows will provide movement and
stopping and SCORE: 000000 is displayed at the top of the screen. Rocks are removed when they encounter collisions with the bullets. Rocks are
renewed when they are all removed. And, 100 points are added to the score every time a rock is removed.
|