Shmup Development (using XNA and C#)

Wednesday, January 16, 2008

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):

  • We created a BulletManufacturer class that creates a bullet.
  • Register the BulletManufacturer in the Factory (with the name "MyBullet").
This is what happens when the game is running and player wants to fire a bullet:

  • 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.
That's how it works. I have provided more concept than code, but I hope this can help some of you to understand how you could implement this kind of object management.

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
Would anyone be interested in that? Please write some comments...

6 Comments:

  • I would be very interested in seeing more of this type of content.

    By Anonymous Anonymous, at 1:47 AM  

  • Nicely put in a SHMUP where most objects besides bosses and the player live less than a minute garbage collection is quite the problem so I agree re-usability of already existing objects should be used more often and should not be limited to just bullets, you could reuse enemies as well saving memory and time.

    I have also been hovering over the idea of a Making Of series of articles about the making of a Shmup engine so Yes it would be quite interesting to see what somebody else comes up with.

    P.S. Nice blog you have here, how'd I miss this I wonder, oh well keep up the good job.

    By Blogger Oprean Dan Stefan, at 4:50 PM  

  • I'd be interested in this :)

    By Blogger Matthew Findlater, at 7:37 AM  

  • I would be very interested in what you have to say on this topic. I am a C# developer myself, never done any game programming but XNA has be very intrigued.

    By Anonymous Anonymous, at 7:17 PM  

  • Is it easy to use Windows Power Shell alongside any of the .NET developer apps? When I say easy I just mean how well it integrates; it should intergrate since it is designed for the .NET environment!

    It seems to have a lot of features that would be very useful to efficient games coding.

    What about the BulletML (on the ABA games website)? Can that be used with C# or other .NET developer apps?

    There is also Mono (freeware, opensource) that lets you use .NET development on other OSs (Mac, Unix, Linux, more)....it'd be interesting too to find out what's been done so far with that.
    (it's not Mono the Linux firewall, it just has the same name)

    By Anonymous Anonymous, at 5:55 PM  

  • I must admit that I am extremely interested in this Manufacturer and Factory process. I am looking to make a shump myself and I would love to fully understand how this process works by seeing the actual code. Of course I'm going to have to try this myself whilst I wait though. I think the biggest problem that I have with game development is that I can never seem to create lots of objects without lots of lag. Of course I use lists and arrays but using this method seems like it would be much more effective. Thanks for delivering the concept to me! :D
    -DiasRaven

    By Anonymous Anonymous, at 11:51 PM  

Post a Comment

<< Home