Monkey Fighter Monkey Fighter
Games Help Help Search Search Shop Shop
Asteroids

Lesson 5: Collisions

3D Game Programming - Java Programming Language

OpenGL Game Programming For the Web!

Home Page

3D Asteroids Home

Files

Lesson5.zip

Lessons

1. Models
2. Actors
3. Keyboard
4. Fonts
5. Collisions
6. Timing
7. Particles

Play Now!

3D Asteroids Normal
3D Asteroids Tiny
3D Asteroids 800x600
3D Asteroids 1024x768

Find Books

- Java Game Coding
- Game Programming
- Java Programming
- OpenGL


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

Asteroids

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.


Asteroids

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.

Copyright ©2005, Robert Walsh, All Rights reserved.