Collision detection between 3D objects is made very simple by Irrlicht. Unfortunately there is no such built in facility for 2D collision detection. In this tutorial we will create a system to detect and respond to collisions between 2D objects.
In previous tutorials the EngineManager class maintained a collection of BaseObjects. This collection was used to trigger events that were common to all game objects, 2D or 3D. With the 2D collision detection we only want to work with the TwoDGameObjects (obviously it doesn’t make sense to apply the 2D collision detection logic to 3D objects). To facilitate this we will create a new collection that holds only TwoDGameObjects.
There is one catch with these collections though: the objects in the collections are expected to remove themselves from the collection while the EngineManager is iterating over the collection. As an example the EngineManager will iterate over the collection of TwoDGameObjects looking for collisions. A collision is then found between two objects (say between the player and an enemy). Both the player and the enemy are notified of the collision, and in response they get blown up and remove themselves from the game, which implies that they also remove themselves from the collection of TwoDGameObjects. But modifying the collection while iterating over it will at best cause an exception, and at worst will cause some very hard to track down bugs.
The EngineManagerCollection class is used to overcome this.
EngineManagerCollection.java Source Code
Three separate collections are maintained in the EngineManagerCollection class: the main collection, a collection for new objects, and a collection for removed objects. Any new objects to be placed in the main collection are stored temporarily in the newCollection, and similarly any removed objects are placed in the removedCollection. These two collections are then merged into the mainCollection with a call to the sync function. This ensures that the mainCollection is not modified inside a loop.
EngineManager.java Source Code
TwoDGameObject.java Source Code
The EngineManager uses two EngineManagerCollections to maintain a list of all BaseObjects, and all TwoDGameObjects.
The EngineManager collisionMap property is used to define which TwoDGameObjects collide based on the TwoDGameObject collisionName property. The key of the HashTable is the collisionName, while the value of the HashTable is a list of all the collisionNames that the key collisionName will collide with. The addCollidingPair function is used to add those collisionNames that will collide to the collisionMap HashTable.
ApplicationManager.java Source Code
The ApplicationManager is used to make the call to the EngineManager addCollidingPair function from the startupApplicationManager function, in this case to define a collision between the players weapons and the enemies.
Now that we have a way to define which TwoDGameObjects will collide along with a separate list of all the active TwoDGameObjects we need a way to actually check for collisions. For this we create the checkCollisions function. This function loops through the collection of TwoDGameObjects twice checking each TwoDGameObject against every other TwoDGameObject looking for two that overlap. When two colliding TwoDGameObjects are found they are both notified through their collision function.
Player.java Source Code
Finally the classes extending the TwoDGameObject class need to specify their collisionName with the call to startTwoDGameObject. If you look at the startPlayerFunction of the Player class you will see that it specifies itself as a CollisionIdentifiers.PLAYER, with CollisionIdentifiers simply containing a list of collision type names.
With these changes we now have a simply way to detect collisions between 2D objects. Check out the online demo here, browse the source code here, and download the source code in a TAR file here.