Components of a shmup game: Manage and recycle objects
I thought about writing some series about developing a shmup game. It will be from my perspective (with the shmup engine I'm creating) and focus on some of the components in a shmup game. If I provide examples and code there will be with C# and XNA. I will probably not explain in detail what the sourcecode looks like, I will more explain the concept and design. Ok, lets go!
This is the first part of the series "Components of a shmup game" where I will write about how my shmup engine manages and recycles objects.
Introduction to objects in a shmup game
In a shmup game lots of objects are created and destroyed very often. Bullets that the player is firing, enemies that are spawned and then milliseconds later are destroyed, explosion particles and so on... The average lifetime of an object in a shmup game is very short.
Every time the player fires a bullet I don't want to create a new bullet (new Bullet()) because this will be pretty inefficient for the garbage collector, instead I want to recycle an already destroyed bullet. This makes all of the objects in the game need to know when they should be destroyed and recycled.
With this in mind I decided to create a few classes that helps me achieve this.
What the classes looks like when managing objects
What we know: Every game object in the shmup engine can be updated and drawn. It also need to know when it should be destroyed, recycled and how to be created from the "recycle bin".
Product - Base for every game object. Provides functionality to be updated/drawn. Can also be added to a manager through the method Activate(IManager manager) and removed from an manager with the Deactivate() method.
IManager - Interface for every object manager. Provides functionality to add an object with Add(IProduct product).
Manager - An implementation for a manager. Provides functionality to update and draw all the objects in the manager. When an object is destroyed and wants to be recycled it uses the associated Factory to add it to the "recycle bin".
IManufacturer - Interface for a manufacturer. Provides functionality to create an object with the method Create().
Factory - Handles creation of objects. Provides functionality to add and create objects to/from the "recycle bin". Manufacturers can be registered (with a name) to the factory for creation of objects that has not been recycled.
What is a factory and manufacturer, and how does it work?
It's pretty simple, a manufacturer is used to create objects. It has a single method, Create() that returns a created object. Every manufacturer knows how to create exactly one object.
A factory contains a dictionary of manufacturers. Manufacturers are registered (added) to the factory with the method Register(string name, IManufacturer manufacturer). The factory is also used with the Manager to handle destroyed objects. The factory got a Create(string name) method (the name is specified for the method so it knows which manufacturer to use to create the object). The factory also got a dictionary of destroyed objects (with the name of the object as the key).
When the Create(string name) method on the factory is called it first looks in the recycled objects dictionary to see if there are any objects available. If there are objects available it will be removed from the list and immediately returned. If there are no objects available the Manufacturer (with the specified name) is used to create the object and return it.
Example when the player fires bullets
Let me explain the object management of a bullet that is fired by the player and then hits a enemy (some stuff are excluded to we can focus on object management).
First we need to do some setup (this is before the game has been started):
I have the intention to write more about developing shmup components (for example):
This is the first part of the series "Components of a shmup game" where I will write about how my shmup engine manages and recycles objects.
Introduction to objects in a shmup game
In a shmup game lots of objects are created and destroyed very often. Bullets that the player is firing, enemies that are spawned and then milliseconds later are destroyed, explosion particles and so on... The average lifetime of an object in a shmup game is very short.
Every time the player fires a bullet I don't want to create a new bullet (new Bullet()) because this will be pretty inefficient for the garbage collector, instead I want to recycle an already destroyed bullet. This makes all of the objects in the game need to know when they should be destroyed and recycled.
With this in mind I decided to create a few classes that helps me achieve this.
What the classes looks like when managing objects
What we know: Every game object in the shmup engine can be updated and drawn. It also need to know when it should be destroyed, recycled and how to be created from the "recycle bin".
Product - Base for every game object. Provides functionality to be updated/drawn. Can also be added to a manager through the method Activate(IManager manager) and removed from an manager with the Deactivate() method.
IManager - Interface for every object manager. Provides functionality to add an object with Add(IProduct product).
Manager - An implementation for a manager. Provides functionality to update and draw all the objects in the manager. When an object is destroyed and wants to be recycled it uses the associated Factory to add it to the "recycle bin".
IManufacturer - Interface for a manufacturer. Provides functionality to create an object with the method Create().
Factory - Handles creation of objects. Provides functionality to add and create objects to/from the "recycle bin". Manufacturers can be registered (with a name) to the factory for creation of objects that has not been recycled.
What is a factory and manufacturer, and how does it work?
It's pretty simple, a manufacturer is used to create objects. It has a single method, Create() that returns a created object. Every manufacturer knows how to create exactly one object.
A factory contains a dictionary of manufacturers. Manufacturers are registered (added) to the factory with the method Register(string name, IManufacturer manufacturer). The factory is also used with the Manager to handle destroyed objects. The factory got a Create(string name) method (the name is specified for the method so it knows which manufacturer to use to create the object). The factory also got a dictionary of destroyed objects (with the name of the object as the key).
When the Create(string name) method on the factory is called it first looks in the recycled objects dictionary to see if there are any objects available. If there are objects available it will be removed from the list and immediately returned. If there are no objects available the Manufacturer (with the specified name) is used to create the object and return it.
Example when the player fires bullets
Let me explain the object management of a bullet that is fired by the player and then hits a enemy (some stuff are excluded to we can focus on object management).
First we need to do some setup (this is before the game has been started):
- We created a BulletManufacturer class that creates a bullet.
- Register the BulletManufacturer in the Factory (with the name "MyBullet").
- Player presses space to fire a bullet. The Create("MyBullet") method on the Factory is called.
- Factory checks if there are any recycled objects available. There are not (because the bullet has never been fired before).
- Factory gets the BulletManufacturer (with "MyBullet" name) and calls the Create() method which returns a bullet. We now got our bullet that we add to our Manager (that handles bullets).
- Manager updates and draws the bullet as it moves across the screen for a few frames.
- The bullet collides with an enemy. Now we want our bullet to be removed from the Manager so we call Deactivate() on it.
- When the bullet is deactivated the Manager will add it to the Factory recycled objects.
- A few frames passes by and the player wants to fire another bullet. The Create("MyBullet") method on the Factory is called.
- Factory checks if there are any recycled objects available. There are, so we just return the recycled bullet. We now got our bullet that we add to our Manager again.
I have the intention to write more about developing shmup components (for example):
- Rendering system
- How the stage and timeline works
- Behaviors for entities
- Developing a datadriven shmup