• Advertisement
Sign in to follow this  
  • entries
  • comments
  • views

From Puppies to Bullets: real-time pixels and CES

Sign in to follow this  


Moving right into making a new game to revive my C# and XNA skills, I decided to go with a top-down view shooter. I already have a code base to start with, which includes some basic AI. The AI is a big one for me, since as long as I could remember I have avoided this subject and haven't really done anything with it. It's one of the areas of game development that was still tricky to me and didn't fully know how to start. But an article here on GameDev has helped clear up my mind a lot about it- this article about State Machines in games.

I'm familiar with the State Machine concept and have used patterns common with them to move a user through screens and game modes. However, the significant part of the article comes at the section "A More Complex Set of Machines". This takes State Machine patterns to create game actors that feel almost like living entities in the game. Here is where I wanted to pursue this idea further.

Fortunately for me, the sample code for this part is in C# and I got to examining it right away. The tutorial used puppies and toys for things to interact with. I could easily picture what you can do when you start replacing graphics and adding your own behaviors. The article even hints at turning it into a shooter as well. The first thing I decided to change is the API- it uses WinForms and that is definitely not going to be used in my game. Replacing the draw functions was trivial, and then it came down to moving all the state machine related code into my XNA game.

Now I have the puppies moving around chasing balls and sleeping on mats again, but this time it's hardware accelerated (aww yeah). With WinForms elements removed I no longer got any text feedback on the puppies' stats so I added some Sprite Font text to show the debug info. I put four puppies in my simulation and each one has their stats displayed clearly on the top of the screen like a basic HUD. If you squint your eyes hard enough you can almost see some sort of 2D competitive game with 4 AI players. Almost.


A Component Entity System architecture

After getting the code ported to XNA, it's time for the next big change- add a Component-Entity System. I did one a long time ago for practice and picking up from there. So far I have a SpriteRenderer System working with Sprite components and Transform components. But the dogs don't move anymore because the behavior code has been made ineffective now. This is where I have to do some thinking- how do I integrate the AI in the Component-Entity System? Should AI be distinct component, or part of a PlayerActor component?

As a distinct component I attempted to have a system act on the PlayerAction component (what I call the AI choices), but there is a setback in having PlayerActions as an abstract class to which other PlayerActions can be derived from. The idea was to have the system loop through the Entities with PlayerActions and perform their updates, and each Update function returns either a new type of PlayerAction or null. The system removes the old PlayerAction component from the Entity if a new one is returned, or does nothing otherwise.

I thought this would work but the class detection was not working. I am using reflection to find the class, but code behavior was unexpected with abstract classes. For instance, suppose I have a AI with an Idle object that derives from abstract PlayerAction. Idle should be detected as a PlayerAction but instead is it detected as Idle. So when an update tells it to replace the PlayerAction, the system won't be able to do it because it is not reading the right class.

That's when I realized that this method of Component detection is inefficient, not to mention wordy. Reflection has its costs, especially if you have hundreds of Entities to loop through. Then I also end up with code like this:

[font='courier new']Components.Transform transform = gameEntity.Component();[/font]

[font='courier new'][font=arial]Although it's lengthy mostly because I have my Components in a Components namespace to avoid some name clashes with XNA specific classes. What I should be doing instead is using bit masks and using an Enum as a Component ID as an argument to the Component function. (The bit mask can be better understood in a key-lock analogy as explained in this article). Then finding appropriate Entities and Components becomes easier.[/font][/font]

[font='courier new'][font=arial]AI interacting with the world[/font][/font]

[font=arial]Now I need to choose whether to move the AI actions into a bigger component instead. The AI needs to interact with items of interest in the world. With the puppy example, it would be toys and sleeping mats. In the original code, the puppies are given information on how many playthings are there and where they are. Changing the code to a ECS pattern means that all these things will have their positions stored in their own components. The PlayerAction component no longer has direct access to the positions, health, speed etc. of other things- in fact, not even about the player itself! As it is now, the component just cares about what it does and not what it's controlling. But for certain actions, it needs to know.[/font]

Maybe I should bring the focus of AI on the player's own information. The puppies in the simulation do not care about other puppies- only about themselves. It goes to a sleeping mat when it's low on energy and then finds a ball to chase after its energy is full. [font=arial]This is okay, because it is an easy start for changing the code to what I want it to do. I could possibly make an exception for the PlayerAction component by giving it a reference to the Entity it's a part of. Then it will have direct access to its statistics and location. I am fine with this, because if it's supposed to be like the brains of the player, it should know almost all about itself. As far as updating the action goes, the AI System makes a limited list of Entities that would be of possible interest to the player and sends that in the Update function.[/font]

I am settled on this design for now. First thing I have to do is make Components accessible by ID and use bit masks to select them in the Systems. Implementing the different behaviors should then be cake.
Sign in to follow this  


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement