Friday, 25 January 2013

The easy way to make reports

The problem

Working on my project I have a tendency of generating up lots of data logs.  These things might be players score each time they play it, or how active someone has been while exercising in front of a Kinect.

Either way, its a lot of data & it generally looks like this:

image

I happen to like logging data in comma separated variable format (CSV), as it’s easy to generate, quite easy to read in. And as an added bonus, I can load it into Excel and look at it as a nice graph.

The only real issue: is it’s a bit tedious loading up Excel to have a look at all the data. I’m not sure what my users will think about doing this all the time. But since I didn’t have a better solution & I don’t want to spend weeks building up a GUI front end just to look at some logs, so I left it as is.

An Idea

A couple of days back I was looking at Devmag.org and I found:

And these caught my eye.   The articles are all about writing logs in html to make them easier to visualise. But my logs are all in text format, designed to be easily machine readable/writeable, but not suitable for human reading.

But rather than go back & redesign all my logging code to output html, I decided to write a simple program to read the logfiles & output nice looking html.

The result

Have a look, nice well laid out data.  The appearance is all due to CSS’s, so it’s easy to change the appearance.  The tables are actually filter-able and can be sorted based upon each field thanks to http://www.javascripttoolbox.com/lib/table/

image

And I can have nice effective graphs thanks to http://bluff.jcoglan.com/

image

Conclusion

It was only a day’s worth of C# coding to convert my log files into html.  And that included the time to find suitable JavaScript libraries to do the nice presentation for me.
I can see that this will be used again to make nice looking reports.

Saturday, 10 November 2012

LegoLand Malaysia

Take about 40 people, send to Lego Land Malaysia. Add lots of burning sun, and a tropical downpour at about 4pm. What do you have?

40 people who are very soggy, and several who are bright Lobster Red!
Attention to detail: Lego pigeons at the Lego fountain
You need to look at this one closely to see the 1,000,001 Lego bricks used in construction

The virgin Margaret is taking a donkey to Bethlehem?

Poly wants a brick-cracker

Spot the odd one out!

This is a Mosaic, of great detail

One day, Mark will grow up and stop feeding his kids to the monsters. But not any time soon.

Again very detailed little things.

Final Opinion?

The only time the kids played with any Lego was when they were in the queues for the rides. (They have some duplo bricks next to the queues, for kids to play with). We saw a lot of Lego art, we went on a variety of rides. But generally, I feel, its just another tourist trap and not so impressive (and way too hot!)

This picture sums up our overall feeling for the trip.

Sunday, 16 September 2012

How old do you need to make a game? About 8-10

Last week was school holiday. But for the week I was teaching, I had a group of 15-16 year old school kids to teach game making to.
I taught them how to use Game Maker (http://yoyogames.com/make/), and they managed to make two games in five days. Although several of them were much more interested in playing minecraft, as can be seen.


However, in a class full of game players, there are always one of two contentious students. This is probably the hardest working student in the class:

Yup, Its Daniel!

Since it was school break, all three kids had the week off. Carmen (aged 8) came in and joined the class for two days, Daniel (aged 10) joined for three days.  They were not as fast workers as the secondary school kids, but they were consistent in their work, and rarely (if ever) played games.

Was their work as good as the secondary schools? Almost. Does this mean I could teach game maker to primary school kids? NO NO NO! My kids were well behaved (they didn't dare annoy daddy), but I doubt that a class of primary school kids could be that disciplined, in fact I doubt my kids are that well behaved at school normally.

But just in case there are any parents out there reading this. A 8-10 year old could build a game with some support.

Have a look an decide what you think on the games. They should run on most Windows PC, and were completed by the kids with minimal supervision.

Tuesday, 17 July 2012

Sockets and Serialisation

Introduction

If you have looked at some of the previous posts, you will see that I use XML-serialisation.  The reason is simple: its easy to do, automatically done by the compiler and the least error prone solution I know.  There are of course a few issues: You are tied to the .Net framework and XML is not the most efficient storage format.
When you start sending the data down a socket I never seem to get it working so well and I end up hitting issues with various things.  So I decided to have another go and write down some of my experiences.

XML-Serialisation and TCP

The basic XML-serialisation to a string is easy.  If you want to know about it, see my past post (http://codethegame.blogspot.com/2011/11/xml-serialisation-of-hierarchy-in-c.html).  Once the XML is generated, its fairly simple to send, or is it?
When I work with TCP, I normally send data one line at a time. So you see a lot of ReadLine/WriteLine in my code.  To format the XML onto a single line takes a bit of work (you need to use and XmlWriter and XmlWriterSettings, you can look it up easily).  So your code ends up a bit like this:
// Pseudo C# to send
Message m=....  // whatever
string msg=DoSerialise(m); // convert it to a string
socketWriter.WriteLine(msg); // send it
// Pseudo C# to receive
string msg=socketReader.ReadLine(); // get a line from the socket
Message m=DoDeserialise(msg);  // convert back to an object
// do your message handling here
This is all fine and simple.  But what happens if I want to switch to binary instead?

Binary-Serialisation and UDP

Binary serialisation obviously turns the object into an array of bytes.  This works very easily with UDP, as its also designed to work with arrays of bytes.  The code ends up looking like this:
// Pseudo C# to send
Message m=....  // whatever
IFormatter formatter = new BinaryFormatter();
MemoryStream mem=new MemoryStream();
formatter.Serialize(mem,m); // serialise
byte[] data=mem.ToArray(); // get the bytes
SendUdp(data); // send it
// Pseudo C# to receive
byte[] data=RecvUdp(); // get the data from the socket
IFormatter formatter = new BinaryFormatter();
MemoryStream mem=new MemoryStream(data);
Message m=(Message)formatter.Deserialize(mem); // deserialise
// do your message handling here
Overall its quite simple: Message=>Binary Array=>UDP=>Binary Array=>Message.
However, if you try this simple approach in TCP, it fails very quickly.
// BROKEN Pseudo C# to send
Message m=....  // whatever
byte[] data=Serialise(m); // get the bytes
SendTcp(data); // send it
// BROKEN Pseudo C# to receive
byte[] data=RecvTcp(); // get the data from the socket
Message m=Deserialise(data); // deserialise
// do your message handling here
‘Why?’ you ask, well its because of the way the TCP and UDP handle data.

TCP vs UDP

Without boring you all senseless with theory which you hopefully already know: UDP is packet based and TCP is stream based.  Or to put it another way:

UDP
This is UDP.
As you can see.
Each ‘box’ is a separate packet of data.
You can clearly see each item separately.

TCP 1
This is TCP. As you can see. Its all together in one continual stream.  Its still quite easy to follow what is going on, because this is English. All you have to do is look for the full stops and you can separate the sentences from each other.

TCP 2
Butnowlookatthismessthisissomemoretextwithoutspacesorpunctuationanditsquiteanightmaretofigureoutwhatsgoingonunlessyoureadverycarefullytomakemattersworseifyougetconfusedyouprobablyendupbacktrackinguntilyoucanpickupthemessageproperly

The above example (TCP 2) is why stuffing binary down TCP becomes quite hard. Unless you can cleanly extract the messages (words/sentences) its hard to process.
With UDP, you can be sure that each packet of data contains a single message.  With TCP, you cannot be sure.  A single TCP read call might give you a message, half a message, 1.5 messages, 2 or even more messages.  You are then stuck trying to break the binary array down, before you feed it into the deserialiser.
Or if you are like me: you just stuff the data into the deserialiser and then it fails because it has no idea what to do with it!
This problem of sending chunks of binary data down the TCP socket annoyed me for quite a while.  The proper way to do it is to use message framing (http://nitoprograms.blogspot.com/2009/04/message-framing.html).  If you want to know what framing is: think of it as adding the spaces and the full stops between the letters you know where one word begins and the next ends.

Binary-Serialisation and TCP

I considered writing a framing algorithm to send/receive the data of the right packet size and so on.  But the trouble is, that all this complexity means, I might as well just go for a simpler solution, like switch back to UDP or use XML instead. 

That it until I suddenly realized I was going about this the wrong way.

I asked myself: ‘why are you using a memory-stream to serialize the object, then take the memory and push it down a network-second stream? Why not serialize directly to the network-stream?’
Do I hacked up the following code:
// Pseudo C# to send
Message m=....  // whatever
IFormatter formatter = new BinaryFormatter();
NetworkStream stream=socket.GetStream();
formatter.Serialize(stream,m); // serialise directly to the network
// Pseudo C# to receive
IFormatter formatter = new BinaryFormatter();
NetworkStream stream=socket.GetStream();
Message m=(Message)formatter.Deserialize(stream); // deserialise
// do your message handling here
I looked at the code & though, “its to simple, it won’t work, the serialiser will not be able to frame the message properly”. But I tried it anyway.
And It worked!

Conclusion

Is this a perfect solution?  Well, almost. I wrote some test routines which had many clients sending messages to and from the server. I managed 10 clients, each sending 200* 2KB message per second.  That’s 4MB/second going into the server and 4MB/seconds going out of the server.
The only time I hit an issue was then I sent so much data in a single message burst that the entire serialiser hung.  I’m not able to explain why yet.  It occurs in the ‘serialise’ function when I send lots of data down the network.
My best guess is that because both sides were writing, the send buffer filled up and blocked, deadlocking the whole system.  If this is the case: having a separate thread just to read the network might fix this.
Overall this is looking quite good. I will be testing more in the future and will let you know.

Anyway, Hope this is useful,
Mark

Code

Here is the code, feel free to mess about with it.

    [Serializable]
    public class Message
    {
        public string s;
        public byte[] megaArray = new byte[1 * 1024];
    }
    class SimpleClient
    {
        static void Main(string[] args)
        {
            new SimpleClient().Go();
        }
        TcpClient sock;
        IFormatter formatter;
        NetworkStream stream;
        public int messageIn, messageOut;

        double Now() { return DateTime.Now.Ticks / 1e7; } // time in seconds
        private void Go()
        {
            sock = new TcpClient("127.0.0.1", 3000);
            stream = sock.GetStream();
            formatter= new BinaryFormatter();
            const int SEND_PER_SECOND=200;
            const double TIME_TO_NEXT_SEND=1.0 / SEND_PER_SECOND;
            double nextSend = Now() + TIME_TO_NEXT_SEND;
            double nextDisplay = Now() + 1;
            while (true)
            {
                if (Now() >= nextSend)
                {
                    SendData();
                    nextSend += TIME_TO_NEXT_SEND;
                }
                RecvData();
                if (Now() >= nextDisplay)
                {
                    Console.WriteLine(string.Format("Messages out {0} Messages In {1}", messageOut, messageIn));
                    messageIn = messageOut = 0;
                    nextDisplay++;
                }
                Thread.Sleep(1);
            }            
        }
        private void SendData()
        {
            Message m = new Message();
            formatter.Serialize(stream, m);
            stream.Flush();
            messageOut++;
        }
        private void RecvData()
        {
            while (stream.DataAvailable)
            {
                Message m = (Message)formatter.Deserialize(stream);
                messageIn++;
            }
        }
    }
    class SimpleServer
    {
        static void Main(string[] args)
        {
            new SimpleServer().Go();
        }
        class Connection
        {
            public TcpClient sock;
            public IFormatter formatter = new BinaryFormatter();
            public NetworkStream stream;
        }
        List<Connection> connections = new List<Connection>();
        TcpListener server;
        public int messageIn, messageOut;

        double Now() { return DateTime.Now.Ticks / 1e7; } // time in seconds
        private void Go()
        {
            server = new TcpListener(IPAddress.Parse("127.0.0.1"), 3000);
            server.Start();
            const int SEND_PER_SECOND = 200;
            const double TIME_TO_NEXT_SEND = 1.0 / SEND_PER_SECOND;
            double nextSend = Now() + TIME_TO_NEXT_SEND;
            double nextDisplay = Now() + 1;
            while (true)
            {
                AcceptConnections();
                if (Now() >= nextSend)
                {
                    SendData();
                    nextSend += TIME_TO_NEXT_SEND;
                }
                RecvData();
                if (Now() >= nextDisplay)
                {
                    Console.WriteLine(string.Format("Messages out {0} Messages In {1}", messageOut, messageIn));
                    messageIn = messageOut = 0;
                    nextDisplay++;
                }
                Thread.Sleep(1);
            }
        }
        private void AcceptConnections()
        {
            if (server.Pending())
            {
                Connection conn = new Connection();
                conn.sock = server.AcceptTcpClient();
                conn.stream = conn.sock.GetStream();
                conn.formatter = new BinaryFormatter();
                connections.Add(conn);
            }
        }
        private void SendData()
        {
            Message m = new Message();
            // send to all
            foreach (Connection c in connections)
            {
                c.formatter.Serialize(c.stream, m);
                c.stream.Flush();
                messageOut++;
            }
        }
        private void RecvData()
        {
            foreach (Connection c in connections)
            {
                while (c.stream.DataAvailable)
                {
                    Message m = (Message)c.formatter.Deserialize(c.stream);
                    messageIn++;
                }
            }
        }
    }

Tuesday, 19 June 2012

Game Design Thoughts

The problem:

In my teaching of game programming, I watch students come up with game ideas, try to build them and then fail.  I see some fail because they are lazy and just don’t work at the project, I see others fail because though they have good ideas; they cannot translate those ideas into code.  My concern is those who have the capability, but cannot express the kind of game they want to build, or who express the ideas poorly and miss out important bits of the concept.
I have just finished reading ‘Unity 3D Game Development by Example’ by Ryan Henson Creighton.  The book is fair (but I’m sure some of it is out of date by now), but it has a great concept on the design and keeping the game simple.  So I will borrow some concepts from there and try to string it together into a coherent whole.
I’m writing this to my students and developers who are in a team of 5 or less people and are trying to get something out in a few weeks-months

How not to do it:


(or just go to the original http://www.youtube.com/watch?v=3hMYF2CRFRo and skip to 6:03)


“My game will be like quake <or some other game>, just better!”
  • Brain Dead!
  • Define ‘better’?
  • And if ‘better’ means ‘more weapons, more monsters, more levels, more ...’, then you must be even more brain dead!
“My game will be like Diablo, but with only 2 classes each with 5 special abilities, 5 monsters, 1 level, 3 quests...”
  • This may look better, but it’s still impossible.
  • Ask yourself the following questions:
    • How much effort does it take to design(think up) 5 types of monster?
    • How much effort does it take to design(think up) 50 types of monster?
    • How much effort does it take to draw/animate 5 types of monster?
    • How much effort does it take to draw/animate 50 types of monster?
    • How much effort does it take to program 5 types of monster?
    • How much effort does it take to program 50 types of monster?
  • For the designing and drawing, it will take about 10 times as long to do 50 types of monsters as it will for 5, but for programming, the difference is minimal because of code reuse.
  • However the amount of effort to implement the monster system is a lot. Once it’s in, adding new monsters is easy.
  • Now look at the idea again: you realise that from the programmer’s perspective, it’s got almost as much code as the full game.  Reducing the amount of monsters/quests/classes has not made it any easier.
“My game will be based upon this barbarian. In the beginning his parents and entire village will be killed by raiders and he will escape, vowing revenge and then he will journey across the wilderness and meet up with...”
  • This is not a game, this is a story.
  • Back stories add colour and mood to your game, but they cannot replace the main game mechanic.
  • The early games like space invaders, pong & pacman did not need a story.
  • But they did have gameplay, and your game must have that too.

So what do we need?

Ok, for a while I will park all the content (story, levels, graphics, etc...) off to one side and ask yourself the following questions.  Each answer should be a few sentences, a paragraph at most:
  • What is the game mechanic? How does the game physically function? How to you play the game?
  • What are the main features of the game? What are the technical items which will need to be implemented?
  • Which is the most important feature to making your game interesting/fun/special? (If your answer is ‘Storyline’, then this means that your gameplay must be totally generic and boring)
  • What is the goal of the game? Does the game have an end, or does it just go on forever?  (When answering this question, keep it short and sweet, don’t use the 50 page background story.)
Once you have this, you can talk about the appearance of the game (its skin) and all the rest of the content.

A couple of examples:

Let’s have a couple of simple examples so we are clear on this:

Pong

The one true game.  It’s ancient, yes, but it’s easy to describe.
  • Main Game Mechanic: 2 players, each controlling a bat and bouncing a ball between each other
  • Features:
    • 2 Paddles/Bats
    • Ball, which bounces off the wall & bats
    • Score when ball goes off the screen
    • Win/lose condition
  • Most important feature: The bats & the ball, without it the game is just nothing
  • Goal: First player to X points wins (it is 15 or 21 points, I cannot remember)

PacMan

Another old game.
  • Main Game Mechanic: Player runs around the maze, eating objects and avoiding the ghosts
  • Features:
    • Player which moves about
    • Maze with wrap around
    • Items to eat
    • Bonus items (fruit) to eat for extra score
    • Ghosts which patrol and then start chasing you
    • Player killed when ghost catches it
    • Power pills which turn the ghosts blue, and allows the player to eat them
    • New level when all the items are eaten
    • Three lives
  • Most important feature: It’s the running around the maze with the ghosts chasing you all the way. That what makes the game fun.
  • Goal: After each level the next level is a little harder, no final goal. Losing when you run out of lives

Serious Sam

For those who don’t know, go and look it up on YouTube (http://www.youtube.com/watch?v=uOgnIKjtKyE). It’s an FPS game which doesn’t take itself seriously and requires a 3-4 digit body count every level.
  • Main Game Mechanic: It’s an FPS! Player runs around a level, sometimes having to avoid traps or jump over gaps & stuff, but mainly just shooting bucket loads of monsters
  • Features:
    • FPS Player movement
    • Large 3D maps
    • Moving platforms, doors, triggers, traps & such like
    • Weapons (pistols, shotguns, mini-guns, sniper rifles, rocket launchers, lasers, flame throwers, cannons, etc...)
    • Smart bomb (yes, that’s right, an FPS with a smart bomb!)
    • Items to pickup (health, armour, weapons, ammo)
    • Bad guys which chase after the player
    • Bad guys which shoot at the player
    • Bad guys which kamikaze into the player
    • Boss bad guy’s the size of tower blocks!
    • Scoring
    • Load/save game
    • Plus quite a few other bits I missed...
  • Most important feature: The thing that makes this game most fun is the ludicrous amount of bad guys which you end up mowing down each level
  • Goal: There is a tiny back story, but basically its reaching the end of each level, killing everything in your path

Conclusion

Coming up with a game idea is one thing.  Being able to describe it for others and then break it down into features to be implemented is another.  I hope that this has helped a bit in getting you to think a bit about describing the technical aspects of your game.

Happy Designing, before the coding,
Mark :-)

Wednesday, 11 April 2012

Kinect for Windows 101

Introduction

I have been messing about with the Kinect SDK for over a year now. I tried OpenNI (its was horrible to work with), and I moved over to the official Kinect SDK (beta).
Yesterday, I decided to sit down and upgrade my code to the official Kinect for Windows SDK.
After having a quick look though the new code I found the following things:
  1. They changed the API's (this is annoying, but not unexpected)
  2. There are a lot more examples available (that's OK)
  3. The Kinect for Windows team cannot write a simple example!
Oh dear!

Let me ask you, if you wanted a program to access the Kinect get the data, and display it. How much code would you like to read?
One page, two pages?

Well the simplest example (in C#) requires:
  • 6 files of code
  • 370 lines of code
Dear Microsoft,
If you want people to use your programs, you must provide a neat, well organised API (which you have done), AND simple examples (which you have not done)

I will not do Microsoft's job for them, but I will show you how you can get most of the work done in two functions and less than 100 lines of code.
Oh, and these 100 lines of code has more comments than the 370 lines of Microsoft code too.
Here is is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Kinect;
using System.Threading;

namespace ConsoleKinect
{
    class Program
    {
        static void Main(string[] args)
        {
            new Program().Go();
        }

        // main data:
        KinectSensor kinect;
        byte[] pixelData = new byte[640 * 480 * 4]; // 4 bytes/pixel
        short[] depthData=new short[320 * 240];   // 1 short/depth pixel
        Skeleton[] skeletons;

        void Go()
        {
            //////////////////////
            // Setup Code
            //////////////////////

            // simple code: just grabs the first sensor (not recomended)
            //kinect = KinectSensor.KinectSensors[0];
            // more complex code:
            // uses the generics to get the first active sensor
            kinect = (from sensorToCheck in KinectSensor.KinectSensors
                        where sensorToCheck.Status == KinectStatus.Connected
                        select sensorToCheck).FirstOrDefault();
            // TODO: check to make sure there really is a sensor

            // you probably should add in a callback function to check for 
            // sensors being added/removed
            //KinectSensor.KinectSensors.StatusChanged+=KinectSensorStatusChange;

            // Initalise the kinect
            // lets have video:640x480, depth:320x240 and skeleton
            kinect.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
            kinect.DepthStream.Enable(DepthImageFormat.Resolution320x240Fps30);
            kinect.SkeletonStream.Enable(); // just enable without worrying on smoothing params
            kinect.Start();
            // we could use polling to access the data, but I'm using event as its simple
            kinect.AllFramesReady += KinectAllFramesReady;  // calls this fn when data is ready

            skeletons = new Skeleton[kinect.SkeletonStream.FrameSkeletonArrayLength];   // max array len

            while(true)
            {
                // should do some stuff here:
                Thread.Sleep(1000);
            }
        }
        // callback for data: call everytime data is ready
        private void KinectAllFramesReady(object sender, AllFramesReadyEventArgs e)
        {
            using (SkeletonFrame sf = e.OpenSkeletonFrame())
            {
                if (sf!=null)   // if we have a skeleton
                {
                    sf.CopySkeletonDataTo(skeletons);   // make a copy
                    // TODO: use it
                }
            }
            using (DepthImageFrame dif = e.OpenDepthImageFrame())
            {
                if (dif!=null)  // if we have a depth frame
                {
                    dif.CopyPixelDataTo(depthData); // make a copy
                    // TODO: use it
                }
            }
            using (ColorImageFrame cif = e.OpenColorImageFrame())
            {
                if (cif!=null)  // if we have a colour image
                {
                    cif.CopyPixelDataTo(pixelData); // make a copy
                    // TODO: use it
                }
            }
        }
    }
}

Thats it!
This code compiles & runs without issue, but it doesn't actually display anything.
The code just starts up and captures the data and does nothing with it.
You can easily add in your own display code.

XNA display

Ok, I think I will add a little bit more. Since my tool of choice is XNA. Here is a quick summary of how to add the Kinect into XNA.

Rather than give a full explanation, I will just drop in some commented snippets of code, you should be able to figure it out from there.

// Snippets for XNA 4.0:
// you need a texture for display, and an array for the raw data:
Texture2D texture;  // texture
Color[] colorData = new Color[640 * 480]; // raw 640x480 colours

// in your LoadContent you can set it up
// at the same time as you setup the Kinect
texture = new Texture2D(GraphicsDevice, 640, 480);

// when you are processing, you can copy the bytes into colours:
// (assuming pixelData is the raw RGB's from Kinect
for (int i = 0; i < 640 * 480; i++)
{
  int idx = i * 4;
  // Either the XNA format is reversed or the Kinect format is
  // its an RGB/BGR issue
  // hence the reversed order for the pixels
  colorData[i] = new Color(pixelData[idx+2], pixelData[idx + 1], pixelData[idx], 255);
}

// when you display, you will need to put the colours into the textures:
// XNA cannot let you write to a texture if its in use:
// so remove all textures from use:
GraphicsDevice.Textures[0] = GraphicsDevice.Textures[1] = null;
texture.SetData<Color>(colorData);
// draw it
spriteBatch.Begin();
spriteBatch.Draw(texture, new Rectangle(0, 0, 640, 480), Color.White);
spriteBatch.End();

Thats All Folk's
Happy Coding:
Mark


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