Sunday 5 February 2012

Static variables in Classes and Games

Morning Everyone,

I has a couple of questions over the weekend on statics, so I aught to give some ideas on this topic.

Concepts
If you want to know the theory on statics, you can go look it up elsewhere, I'm not going to give you all the gory details:
So here is a quick summary:
Most attributes and functions in a class are attached to an instance: (E.g. each 'Person' has its own 'Name', 'Age', 'Occupation')
However, static attributes and functions are not attached to a given instance, but are shared across all instances.  (E.g. the total number of 'Person's is not an attribute of any given object, but its shared across all persons)
Code
The next thing to consider is the code required.  Today I'm going to cover C++ and C# which are my main programming languages, Java certainly has this concept too, and most other OO languages have.
So here's some code
// C++
// the class declaration (in header file)
class ClassA
{
public:
  int x,y; // all ClassA's have their own x & y attribute
  static int z; // the z attribute is SHARED between all ClassA's
};

// the class definition (in the CPP file)
// Do NOT put in header file, you will get a 'multiple declaration' error
// and if you forget it, you get an 'undefined external' error
int ClassA::z=0; // the actual shared variable
/////////////////////////////////////////////////////////////////////////////
// C#
public class ClassA
{
  public int x,y; // all ClassA's have their own x & y attribute
  public static int z; // the z attribute is SHARED between all ClassA's
}
There are also static functions, but I'm not going to bother covering the syntax for those.

Application
Ok, theory lesson over, how do we use them? In fact do we even need them? (Obviously yes).

Lets take a simple example: space invaders.
Each invader has its own position & its own appearance.  But they all go in the same direction at the same rate.  This makes a good candidate for a static direction attribute.  When one of the enemies reaches the edge of the screen, it can set the direction attribute to down and then all the invaders will move downwards together.

Lets take another common example the options screen:
In the options screen the player will choose various options: difficulty, volume, keyboard/joystick, and so on.  But once the player leaves the options screen, the screen will probably be destroyed and those options would them be lost (oops).  The solution to this problem is to store these options as static variables. Like this:
// pseudo C# code, do not expect to compile unedited
class OptionsScreen
{
  public static int difficulty=10;
  public static float volume=1.0f;
  public static bool joystick=false;
...
}
So within the OptionScreen code it will set these variables, but because the are public and static they can be accessed anywhere within the game

// pseudo C++ code, do not expect to compile unedited
if (OptionsScreen::joystick==true) // in C++ its ::
{
  // do the joystick stuff
}
else
{
  // do the keyboard stuff
}

////////////////////////////////////////////////////
// C# equivilent
if (OptionsScreen.joystick==true) // in C# its just a .
{
  // do the joystick stuff
}
else
{
  // do the keyboard stuff
}

I think you get the idea.
The other good thing about this is when you leave the options screen and then come back later, the options will still be the same.
You could also use a static for holding the high scores too (you will need some kind of static array or static list/vector).  This would not automatically save the scores for you, so if you exited the game and played it again the scores would be reset.  If you wanted that you will need to write the load/save code yourself.

Another good idea is for storing player details (score, lives, XP, and so on) across multiple levels.  You could make these values static attributes of the Player class, or of the Game class (its up to you to decide which is more reasonable), but they would work the same way.  That way as the player moves from level to level, their information stays the same.

Note: this would not work for a two player game, as both players would end up sharing the same score variable.  You might end up having to have a static player_1_score and a static player_2_score, or even having static players!

Final idea is to have all the enemies sharing a few variables, such as enemy_speed and aggression.  This would allow you to change a single variable to control the speed/aggression for ALL enemies.  Obviously this is not so useful if you want to have different enemies having different speeds/aggressions.  But if you wanted all enemies with the same abilities, this works well.

Just one thing: Don't try putting graphics as a static.  Yes quite often all the enemies have the same graphics, but its better not to force it to be so.  If its static, then it MUST be the same.  If its a normal member, then it CAN be the same.

Hope this gives you some good ideas:
Happy Coding
Mark