E. Darwin Hartshorn: //Boilerplate

Code

Secret Coding: Making Object Oriented Programmers Tear Out Their Hair

First programming tutorial!  Ha!

Okay, before we get too excited:  I’m not going to teach you to program.  I’m going to teach people who can program how to program games.  So, the first thing you’re going to need to do is learn a little C# if you don’t already know some.  Google C# tutorials.  Or go here.  It’s where I learned.

That website will walk you through installing C#, as well as how to code in it.  To write programs in XNA Game Studio, which is a set of game programming libraries for C#, go here.

To those of you who are watching the game industry closely, and are now wondering “Why XNA?  Isn’t XNA dead?”  I can only reply 1: XNA is not dead so long as MonoGame exists, and 2: I’ve spent the last couple of years coming to terms with XNA.  It’s where I’m able to help you.

Unity might be simpler to learn.  It may even be better.  It’s certainly the direction things are going, and I won’t tell you not to check it out.  But XNA is what I know, and what I teach, and there’s still some life left in it.

Cool beans.

This first part is theory (explaining what we’re going to be doing).  Next week, we’ll actually do something with all that theory.  Of course, if you’ve just run across my site, and it’s already been more than a week since I wrote this, you can just skip right ahead.

It’s time to dive in to the strange, alien terrain of coding that isn’t exactly as Object Oriented as you may like.  I’m going to tell you to do some relatively complicated things today, and if you’re already a pretty good programmer, you are going to want to punch me right in the face before I’m done.  The reason is I’m using (or trying to use) a methodology called Entity Systems (ES), which is a different way of doing things than Object Oriented Programming (OOP), and thus Good ES Programming Is Often Bad OOP (GEPIOBO).  (Okay, that last acronym is ridiculous.  Ignore it.  I’ll probably never use it again.)

I think it’s better to show you how things work rather than starting by explaining the theory, which will come in more next week.  What you need to understand starting out is this:

If I were showing you how to use OOP to make games, I could teach you to do step one, get a rectangle on the screen, in six lines of code.  Seriously.  You can make your first XNA game project displaying rectangles and even pictures on command in the time it’s taken me to type this sentence.

But it will take us a bit longer to get our basic ES framework in place.  Like, maybe a half-hour to an hour.

The trade-off is that once we’ve gotten that framework into place, actually making the game will go much faster.  As in months or years faster.

Starfighter X took me about two months to build.  I could rebuild it using ES in a couple of days.  And it would be awesomer.

The other part of the trade-off is that making a game with OOP is like Real Chemistry.  You carefully map out a chemical chart, mix together a few things that look exactly like water, and if you get the mixture wrong, it just sits there and looks like water.  Or burns you.

ES is like Mad Scientist Chemistry.  You throw random colorful ingredients together, and it always results in a dramatic explosion, and when the colored smoke clears there’s a really strange animal sitting on your desk that you’ve never seen before, and you can’t stop cackling like a maniac.

I’m not even kidding.  It really is exactly like that.

But remember:  GEPIOBO.  If you are already a decent programmer, suck it up, hold off judgement, and wait ’till you see how things work.  Then, pooh-pooh it if you like.

Step one:  fire up Visual C# Express, and start a new Solution.  Select “Windows Game”, name it, then as soon as it’s finished loading, hit F5 to run your game.

Tada!

It burns!  It freezes! Take it off us, my Precious!

It burns! It freezes! Take it off us, my Precious!

Man, I hate Cornflower Blue.  The evilest, most hateful color on God’s Green Earth.  That has to go.

Terminate your program, and scroll on down through the code that Microsoft has so conveniently provided you.  You should find a bit that looks like this:


/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

// TODO: Add your drawing code here

base.Draw(gameTime);
}

Schweet.  Check out line 7: “GraphicsDevice.Clear(Color.CornflowerBlue);”.  That line does exactly what you think it does.  Why not highlight the word “CornflowerBlue” and replace it with another color?  Black is always popular.

Even Greater Accomplishments

This color represents how I’m a nonconformist, rebelling in perfect lockstep with all the other nonconformists!

 

How’s that taste of Real Ultimate Power?  Feels pretty good, right?  Well, it had better tide you over, ’cause we are going to leave behind powersville for a little while so that in the future, we won’t have to leave it ever again.

Right-click on your solution in the solution explorer.  Select “Add -> New Project”

Yes it is.

That’s not mildly insulting…

Add a Windows Game Library.  Give it a rockin’ awesome name like “AtomSmasher”.  Make sure you right-click on your game project and Add Reference, then add AtomSmasher, as otherwise your game will not know that it exists.

Right-o.  AtomSmasher is going to contain our Entity System.  Let’s start by renaming Class1.cs to ES.cs.  Visual C# will kindly offer to rename all references for you, and I suggest you accept its offer.

Here’s the code we’re going to write for starters in ES.cs:

Entity System 01

 

I’ve underlined the word ‘static’ in the class declaration because it’s important.  Static means that you don’t create ES objects.  Instead, you access the class directly.

Now, anywhere in your game code, you type in something like int Vorgon = ES.Next; and your variable (Vorgon) will be assigned a unique number.

Why is it unique, you ask?

Well, let’s take a look at the rest of that code.  First we have ‘cur’ which is shorthand for “Current Number Which is Definitely The Biggest One We’ve Assigned.”  We start it off at negative one.  Every time we ask ES for the Next number, barring other circumstances, it increase cur by one, and then sends us back the result.

Next on the list after cur is Available, the only thing so far that has a sensible name (but we don’t care about cur because we’re never going to do anything else with it ever again1).

Available is a Stack.  That is, it is a collection that can hold an ever-expanding list of stuff.  The catch is the stuff is stacked up like a bunch of plates.  We can Push a new plate on the Stack, or we can Pop the top plate off the Stack, but if we try to yank a plate out of the middle or (Yog-Sothoth forbid) off the bottom, Bad Stuff Happens.

Stack has angle brackets around the word ‘int’.  That means it’s a stack of ints.  It could be a stack of anything, but we are using ints.

The next thing is, handily enough, Next.  A property.  First, it checks if there are any numbers on the Available Stack.  If there are any, it Pops the top one off and sends it back.  If not, it increases cur, and sends that back.

So, when we are done with Vorgon and no longer need it, we can send it back to ES.  ES will Push it onto the Available Stack, and the next time our program needs a unique number, it will get a gently used number instead.

That’s what the Kill(e) method is for.  When we call Kill, we are telling the Entity System that we no longer have any use for the unique number we are killing.

So, so far, we have a way to fetch a unique number, and a way to give back the number when we are done with it.

Why?

These numbers are the Entities in “Entity System”.

These numbers are all there is to the Entities in “Entity System”.  An Entity is a number.  No two Entities are allowed to be the same number, lest weird stuff happen.

As the name Entity Systems suggests, the second thing we need to implement after Entities is…

Components.

Psyche.

Add a Folder to the AtomSmasher project called “Components”.  Then, add a class called Art.cs.  Here’s the code for Art:

Art Component 01

 

Let’s esplain all this:

Art is a class to hold all of our Art components.  We don’t technically need a class just for the Art components — we can (and I once did) just shove all the components into ES.cs — but it’s easier to find the component you want if you sort them by category.

The component, or rather, component dictionary, is “public static Dictionary<int, Rectangle> VisibleRectangle;”.

Like Stack, a Dictionary is a special sort of list2.  Unlike Stack, which works like a stack of plates, a Dictionary works like… well, a Dictionary.  You store things in the Dictionary under a Key.  When you want the thing you stored, you just use the Key, and the Dictionary looks it up for you.

Inside the angle brackets, we have two data types:  int, and Rectangle.  The first is the data type we are using for the Key, in this case a number.  The second is the data type we are filing in the Dictionary, in this case a Rectangle.

We are calling it “VisibleRectangle” because this dictionary represents rectangles that are drawn on the screen.  So, the goal is, each VisibleRectangle in the Dictionary will eventually be drawn on the screen.

That happens in the Systems in Entity Systems, but we are getting way ahead of ourselves here.

In the class’s constructor (static Art()), we initialize VisibleRectangle with a size of 128.  This is a rough guess of how many rectangles we will need on the screen at a time.  We can fine-tune this up or down later, but making guesses like this is handy because if we ever need more rectangles than we have pages in the Dictionary, the Dictionary will be forced to make a new, bigger Dictionary, and copy everything from the old one into it.

It’s not hugely important, and you shouldn’t spend time worrying about it unless and until you are running a game and it starts to slow down, but there you go.

The way we are going to use this in code is this:  when we have an Entity, we can add any Component to it by simply filing that Component in the appropriate dictionary under the Entity we want it to belong to.

The way to do it is this:

int Vogon = ES.Next;
Art.VisibleRectangle[Vogon] = new Rectangle(x, y, height, width);

So, now you know why Entities are just unique numbers.  Any Entity can ‘own’ one of any component simply by having that component filed under its ‘name’ (that is, the number it consists of).

That leads us to Art.Kill(int e).  Inside the kill method, we remove the entry for whatever number we’re sent from the dictionary (and no worries — if there isn’t an entry, the program will just move on as if nothing happened.

That means that in ES.cs, we are going to have to add a couple of things.

First, up at the top in the using statements:

using AtomSmasher.Components;

And then, in ES.Kill(e):

Art.Kill(e);

Right.  We have a way of getting new Entities (ES.Next), and a way of filing visible rectangles under our Entities (Art.VisibleRectangle[Entity] = Whatever).  Now we need code to actually draw the rectangles, right?

Well, yes, but first, we need access to our art supplies.  And as I, sadly, have run out of time to run this article, I am going to leave that off for part two.

 

1. Yes we are.  It will show up again when we write ES.Nuke().  But that’s a little bit down the road.

2. For those who are wondering, it’s a Hash Table.

 

Leave a Reply