Destroying Entities

Introduction

The Destroy method is a method that should be written in to your Entity to completely destroy the Entity. This method should remove all FlatRedBall objects from their managers, and the it should also remove the Entity itself from the engine. If your Entity belongs to any PositionedObjectLists, the Destroy methods will remove the Entity from those lists automatically if the Entity removes itself from the SpriteManager.

For Glue users: Glue automatically generates a Destroy method for your Entity. Any objects which are added to your Entity through Glue will automatically be properly destroyed for you. Of course, Glue does not look at your non-Generated code, so if you create any objects by hand in your non-Generated code, you will need to manually remove those objects in your “CustomDestroy” method which is automatically called when your Entity is destroyed.

What does Destroy do?

In general, there are two things that an Entity should do in its Destroy method:

  1. Remove any FlatRedBall objects that it contains, such as Sprites used for VisibleRepresentation and Circles used for Collision.
  2. Remove “this” from the SpriteManager using FlatRedBall.SpriteManager.RemovePositionedObject.

The Entity should not unload content. The content manager used to load content for the Entity should be provided by the Screen that contains the Entity. Screens automatically unload their content managers, and this will clean up content loaded by the Entity.

When is Destroy called?

Destroy should be called in two situations:

  1. If an Entity is being manually removed due to game logic. For example, if a Bullet Entity collides with the wall, and it is proper in the game’s context to remove that Bullet, then its Destroy method should be manually called.
  2. If a Screen is being Destroyed. Screens should Destroy any of their contained Entities when they are Destroyed.

For Glue users: Any Entity that is created as an object in a Screen in Glue will automatically have its Destroy method called in the containing Screen’s Destroy method. Also, any PositionedObjectLists that contain Entities which are added to a Screen through Glue will also be destroyed in a loop in the Screen’s Destroy method.

Similar to Entities, any Screen that manually creates Entities in its non-Generated code should destroy those Entities in the Screen’s “CustomDestroy” method.

Code Example

For an example, consider an Entity which defines the following:

In this case, it is likely that the Entity will have a Constructor or Initialize method which does the following:

The Destroy method should mirror the code that was used to initialize your Entity. Therefore, your Destroy method might look like:

For Glue users: An Entity’s generated code will automatically add and remove the Entity from the SpriteManager, so your non-Generated code should never call

Entities and presence in your game

If you create a game with Entities, then you will be instantiating and storing these Entities somewhere in your game. For example, you may have a Character and Enemy entity defined as follows:

In which case you might instantiate them as follows:

The fist thing to note is that the code above uses the PositionedObjectList class. This is very important. Let’s investigate why.

The idea behind using Entities is that you should be able able to destroy your Entity completely with one call – a call to Destroy. This means that the Entity should remove itself from the FlatRedBall Engine as well as from your game. Well, the only way that the Entity can remove itself from your game is if it knows which objects to remove itself from in your game. This means that you must use a class that supports two-way membership. The PositionedObjectList (or any class inheriting from it) supports two-way relationships.

If you use the PositionedObjectList class, then any time you call Destroy on an Enemy, it will be automatically removed from your list – assuming of course that your Enemy’s Destroy method calls

For Glue users: As mentioned above, an Entity’s generated code will automatically remove the Entity from the SpriteManager. All you have to do is create a PositionedObjectList in your game to store the Entities. Glue also supports creating PositionedObjectLists so use that type in Glue if you plan on creating lists of Entities.

Destroy and membership in your game

The two-way relationship between Entities (and all other PositionedObjects) and the PositionedObjectList class is what enables the Destroy method to remove an Entity from the engine. In fact, the PositionedObjectList (and any class which inherits from PositionedObjectList) is the only reference that Entities know about. If you store a reference to an individual Entity, the reference will still be valid after you call Destroy unless your code handles this case. Let’s look at some simple examples.

In our first example we’ll create some code where the user is keeping track of an individual player and enemy:

At class scope:

This piece of code checks for the player attacking the enemy:

This piece of code checks for the player touching and being hurt by the enemy:

The code above has a logic bug which will cause the game to behave improperly. When the Enemy is destroyed (through mEnemy.Destroy();) then all of its components will be removed from the engine. Its visible representation and collision will be removed from the appropriate managers. It will also be removed from the SpriteManager so that it is no longer managed by the Engine.

However the collision check between mPlayer and mEnemy is still being done! If you think about it a bit, this makes sense. This is because your code doesn’t check if mEnemy is dead. It does the check no matter what. However, since mEnemy is destroyed, it is no longer part of the engine. The result is that mEnemy will seem to completely disappear, but its Collision object will still be sitting there, invisible, in the level. Even though it is not part of the engine, it can still be used to test collisions.

There are two solutions to this problem:

  1. (Preferred solution) Create a PositionedObjectList<Enemy> and add your Enemy to that list. Then replace all code which checks against mEnemy to instead loop through your PositionedObjectList<Enemy> and test collision. This should be done for all logic including player attacking enemy and enemy attacking player. When your Enemy is destroyed, it will be removed from the PositionedObjectList<Enemy> and your game will function properly.
  2. (Necessary if you need to keep track of specific Entities) Check your mEnemy’s Health before performing collisions. If its health is less than or equal to 0, then it is dead and you shouldn’t perform collisions. For example, your collision check should look like: