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

Tuesday 31 January 2012

Version Control for Dummies - part 3


This will be a three part series. Part 1 is aimed at the project leader. It explains why you need version control and how to set it up. Part 2 is aimed at the developer who will need to work with the version control, so covers how to use it. Part 3 is about conflicts and other important topics.

Introduction
The version control is working, its being used ok. This is looking at some of the other features and a very common issue: conflicts.

What is a Conflict?
Take a case when you have two developers 'Fred' and 'Jim' both working on the same set of code.  We will assume they both get copies of the code & work on their machines adding different features.
When it comes times to commit back to the version control, this is when problems occur.

Fred commits first and there is no issue, after all he is working with the most recent copy of the code.
But when Jim want to commit what will happen?

If you are using a shared directory approach, Jim's code will just overwrite Fred's (not good).  Instead, the version control detects that Jim's code was based upon an older copy of the code and will not allow it to happen:
This is known as a conflict.

You can find out a bit more about this using the 'show log' command, and then do a compare your current code against the code stored in the version control.
This will provide a graphics difference comparing the two copies of the code. (Looks complex, doesn't it?)

Resolving the conflict
There are basically 3 ways to solve the conflict:

  1. Jim can delete out your own code, then do a update from the version control and replace all his code with Fred's newer copy
  2. Jim could move his code out of the way, get an updated copy of the code and try to copy/merge his changes in (good luck)
  3. Jim can let the version control system merge the code together (which is hopefully not too painful)

If none of these sound good, thats because they are.  But remember, the alternative was just to blindly overwrite someones else code.

First you need to update the code to get it up to the most recent version (done before, not covered)
You will get a warning message like this:
It warns you that there is a conflict which needs to be resolved.
If you look at your hard disk, you will see a set of files:
The .mine is your original code, the .r4 & .r5 are the other copies of the code (in this case version 4 & 5, you will have other numbers).  The original file will have been replaced by the merged code which looks a bit like this:
If you know how, you can edit this directly and fix the code, but its easier to instead right click and use 'Edit Conflicts' which gets the merge program up.
The code in the top left is the 'most up-to-date' code from the repository.  The code on the top right is 'your code', and the code at the bottom is where you put the merged code.
There are a number of helpful features to make it a little easier:
This allows you to just copy the block of code from one side or the other or have them both.

VITAL: Once you have finished making a merge, load the code back into your compiler and recompile to make sure there are no errors in the code.  Just because it merges, doesn't mean the code is good.

Once the code has been checked, its time to commit the new code to the repository and move on.

Backups
One of the great things about version control systems is it keeps a complete copy of all the code.  But what happens if the server goes down?
If usually possible to backup the repository, here's how to backup an SVN http://stackoverflow.com/questions/2302592/how-do-i-back-up-a-remote-svn-repository

Getting a certain copy of the code
Again another task you might want to do: Get last weeks code.  To do this, just use Checkout, but instead of getting the 'HEAD', you can specify a given revision in the dialog box.

Branches & Merges
Its possible (though I just about never do it). To branch the code off, then you can work on two versions of the code (the main trunk and the branch).
Possible, not required, probably not advisable.

Conclusion
Thats about all I have ever needed to do with the version control systems, and overall it has served me well.
Hope this gives you a good idea of what its all about.

Happy coding,
Mark


Monday 30 January 2012

Simple Shadows

Nice shadows? What do you think?


Will its actually a quick hack and simple to do. So lets look at it.

The basics
How did I do it?  Well take a suitable transparent looking texture.  Then you just stick on onto the ground like this:
Suddenly it becomes obvious what I did, doesn't it?

What do we need:

  1. A suitable transparent texture (you can do this yourself)
  2. A textured quad to draw on the ground
  3. A way to make sure it appears on the ground but not in the ground

So, lets get to it...

The Textured Quad
This is using DirectX 9, but the idea is the same for DirectX 10, or even XNA.  We just need to an array of positions and UV coordinates.  The code will probably be something like this:
// the structure for feeding into DX9
struct ShadowVertex
{
  D3DXVECTOR3 pos;
  D3DXVECTOR2 uv;
};
// the FVF
const DWORD ShadowVertex_FVF=D3DFVF_XYZ | D3DFVF_TEX1;

// sets up the UV coordinates, which only needs to be done once
void InitShadowQuad(ShadowVertex quad[4])
{
  quad[0].uv=D3DXVECTOR2(1,1);
  quad[1].uv=D3DXVECTOR2(0,1);
  quad[2].uv=D3DXVECTOR2(1,0);
  quad[3].uv=D3DXVECTOR2(0,0);
}

// sets up the XZ coordinates for the quad
// you will need to adjust the Y coordinates to make sure they are
// neatly on the ground
void UpdateShadowQuad(ShadowVertex quad[4],D3DXVECTOR3 pos,float size)
{
  quad[0].pos=pos+D3DXVECTOR3(size,0,size);
  quad[1].pos=pos+D3DXVECTOR3(size,0,-size);
  quad[2].pos=pos+D3DXVECTOR3(-size,0,size);
  quad[3].pos=pos+D3DXVECTOR3(-size,0,-size);
}

I really should have a vertex buffer to hold these in, but I'm going for the simplest possible solution and just sticking with an array of data.

The other task you will need to do is to make sure that the Y coordinates of the quad are neatly on the ground.  For flat terrain that's just a matter of quad[0].pos.y=0, but it you are doing it on 3D terrain, it will be a little more complex.


The Rendering
For those who know their render states, this should be simple.  But for those who don't, it could be a bit more complex, so here are the main issues to consider.
  • Must have blending: to blend nicely with the terrain under the shadow
  • No lights: the shadow affect the terrains appearance, we don't want apply lighting twice
  • Z-Buffering must be dealt with: this is the tricky part 
The most obvious solution would be to just draw the shadow on the ground.  The trouble is you get something like this:
Some bits of the quad are above the ground, some bits of the quad are in the ground.  Its caused by rounding errors in the Z-buffer.  We can try to fix this by moving the quad a little bit above the ground, but this then asks the question how much? 0.1 units? 0.01units? 0.00001?  Depending on various factors in your game this may (or may not) look good.

I experimented with disabling the Z-buffer write or just turning the whole Z-buffer off, and I found that turning the Z-buffer off worked better.  You just have to be careful in your draw order (my first attempt had the shadow drawn on top of my model).

So here is the quick summary in english:
draw the ground
turn off Z-buffer
turn off lights
turn on blend
draw the quad with the shadow on it
turn off blend
turn on lights
turn on Z-buffer
NOW draw the model over the shadow

In code it looks like this:
// draw the shadow quad
void DrawShadowQuad(IDirect3DDevice9* pDev,IDirect3DTexture9* pTex,
                      ShadowVertex quad[4])
{
 pDev->SetRenderState(D3DRS_LIGHTING,false); // lights off
 pDev->SetRenderState(D3DRS_ZENABLE,false); // Z-buffer off
 pDev->SetRenderState(D3DRS_ALPHABLENDENABLE,true); // blend on 
 pDev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
 pDev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
 pDev->SetTransform(D3DTS_WORLD,&IDENTITY_MAT); // world set with identity matrix
 pDev->SetFVF(ShadowVertex_FVF);
 pDev->SetTexture(0,pTex);
 pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,quad,sizeof(ShadowVertex)); // draw
 pDev->SetRenderState(D3DRS_LIGHTING,true); // lights back on
 pDev->SetRenderState(D3DRS_ZENABLE,true); // Z-buffer on
 pDev->SetRenderState(D3DRS_ALPHABLENDENABLE,false); // blend off
}

(Note on DrawPrimitiveUP: Yes, I KNOW it has a horrible performance penalty, but its the simplest way to get the code up.  It should certainly be done with a vertex buffer.  However, you try and make the vertex buffer code this simple!  I went for simplicity, not efficiency)


Final Code
The main code looks something like this (but it will vary depending upon your ground):
// draw the shadow quad
// draw ground...
D3DXVECTOR3 pos=players pos
float radius=players radius
UpdateShadowQuad(verts,pos,radius); // update the vertex position
// put the vertexes on the ground
for(int i=0;i<4;i++) verts[i].pos.y=0;
DrawShadowQuad(GetDevice(),mpTex,verts); // draw the shadow
// draw the player...

And there we have it.

Improvements
Nope: its not a true shadow, and it is just a circle, and its not very realistic.  But it was very simple.  To do this properly, we need to start messing around with stencil buffers and possibly shaders too.  Frank Luna (http://www.d3dcoder.net/) has some good books on the topic and there are probably some other references on the net somewhere else.

This is quick and it works, and I have not found any articles explaining this simple trick. So I hope it helps.

Happy Coding,
Mark

Version Control for Dummies - part 2


This will be a three part series. Part 1 is aimed at the project leader. It explains why you need version control and how to set it up. Part 2 is aimed at the developer who will need to work with the version control, so covers how to use it. Part 3 is about conflicts and other important topics.

Introduction
You have version control.  Either the team lead told you you use it, or you understand how useful it is. Or perhaps you just joined a sourceforge project and you need to get access to their repository.  Whatever the reasons are, this post is looking at how to use SVN (in particular tortoise SVN) in your development.

A few terms
I'm using the SVN terms as it will help later
  • Repository: The 'shared directory' where the code lives, usually on a hosted server somewhere
  • Import: take some brand new code & put it into the repository
  • Check out: Get a fresh set of the code (usually the latest version) from the repository onto your local machine
  • Update: Update the code on your local machine with the latest version in the repository
  • Commit: Copy the code from your local machine into the repository
  • Conflict: What happens when you try to commit some code and someone else has already made a modification to it
You will need
  • A copy of Tortoise SVN ( http://tortoisesvn.net/)
  • The URL of the SVN repository (the project lead will know this)
  • A username & password (probably)
    • Its worthwhile each developer having their own account, it encourages more responsible behaviour, as each commit has your name attached to it

The First Check Out
We need to get the latest code to work with, so this is where we start.
Get yourself a suitable directory.  It doesn't need to be 100% empty, but it cannot have a directory with the same name as your project.
Right click on the base directory and SVN->Check out
For the repository name, give it the information that you were given (remember, your project lead needs to set up the repository and give you the URL of it). As you want to copy the whole directory, you need to also give a directory name. I.E. we are copying https://whatever_the_SVN_repository_was/trunk/project_name
to d:\work\project_name So we will get all the code we need in a new directory.
(PS. The HEAD revision, means the latest copy).

After we hit OK, the SVN will get the latest copy of the code, create the directory and put all the code in it.
Currently its just the readme, but we will add some code later.  If you have a look on the hard disk, you will see the files added with a little green tick icon, which means they are up to date.
We now have the latest code.

General Usage: Adding, Ignoring and Committing
OK, so we have a version control up, what next?
Write code of course...
<some time later>

What next?
Lets have a look at my directory right now:
I have added in a Visual C++ project and put in a bit of code.  But life gets a little bit more complicated.
I don't want ALL of this stuff into the source control, mainly all the temp files and stuff, but especially the 100MB temp files which Visual Studio likes to generate.
As for knowing what to add & what not to add, this is down to the individual programming environment/language.  But in my case, I want to ignore the following:

  • Debug and Release folder
  • The .NCB, the .SUO and the .user files
Therefore I right click on them and mark them to be ignored.
After that, I add in the files I want to add again by right clicking.
You notice how it is now marked with a + to show its been added.  
However this does not mean its in the repository yet, that will not happen until we commit the directory to the server.  We do this by selecting the directory and doing a commit.
This will show which files are changed (& will be sent to the repository), at the same time it will show up which files are unversioned (not added or ignored), for you to decide what to do with them.  You can just right click & decide to add or ignore them.
(If you want to know what the changes are, just right click on the file & select 'compare')


Very Important: Use the text box to add some comments to explain what you did.  You want to know what other people have been doing to the code, so give the same feedback for them.
Most of the time it should work fine, unless you are working on old code.  In which case you may need to do an update (see below).


General Usage: Viewing and Updating
What happens if the others are working on the project and you need to find out what is going on?  Well, select the directory (or file), right click and select 'check log' which will give you the current history of the project:
Remember I said about adding the comments when you commit? Well you can see the comments listed here.
You can 'check for modifications' which will show you if your code if the most up to date, or if others have made changes to your code:
In this case, it seems that someone have updated one of the files, so what I can do is 'Update' to the latest copy of the code.


General Rules for use with Version Control
  1. Never check broken code into the version control, test it first
  2. Don't check in generated files (object code or similar), just the original source.
    • It should be easy to regenerate the files from the source
  3. Make sure you are careful with what you add into the version control, don't add in junk.
    • On one project, someone added a 200MB movie files into the version control. I was very unhappy with them
  4. Try to minimise the amount of non-text files which you add into your version control, as most systems don't handle them well & they take up a lot of space (compared with code)
    • Some teams run version control for the code and then use a shared drive for art assets
  5. On a similar note, If you are going to add art assets in, only add in the final items in a form which is useable in the project
    • Don't put in your raw photoshop files, just the final exported bitmap
    • Keep the raw photoshop files in the shared drive
  6. It should be possible for someone to check out a complete your code from the version control system and build it without errors.



Conclusion
There are quite a few other items which I could cover (reverting, comparing and such), but these are the most common operations you need.
In part 3, I will cover dealing with the issues.  In particular what happens when two people try to change the same piece for code at the same time?

Until then, Happy Coding,
Mark


 


Friday 27 January 2012

Version Control for Dummies - part 1


This will be a three part series.  Part 1 is aimed at the project leader.  It explains why you need version control and how to set it up.  Part 2 is aimed at the developer who will need to work with the version control, so covers how to use it.  Part 3 is about conflicts and an other important topics.


The problem?
When you are writing programs on your own its quite easy to do, but what happens when there are two (or more) people working on the project together.  What do you do?
  1. Everyone hack the code & hope
    • Never going to work
  2. Pass latest copies of the code about using email/thumb drives
    • Sort of workable, but its hard to know which bits have been updated
    • And you never know where the latest copy of the code is
  3. Everyone writes their own code & gives it to one person who holds the master copy of the code
    • I've tried this, its a lot of work for the one person
  4. Some kind of shared drive or drop box (http://www.dropbox.com/)
    • Getting there, but if you have to be careful, or you can overwrite each others code
  5. A Version Control System
    • This is what I'm talking about

So what is it?
Think about a shared drive somewhere, which holds all your code.
It also holds all the backup copies of your code, so that every time you make a change, it makes a backup (just in case you mess it up).
It also keeps track of who have been changing what so it will stop you from accidentally overwriting someone else's code if you both have been making a change to the same file.

This is a version control system.

Different types of version control
There are quite a few different types of version control: CVS, SVN, Perforce, GIT, Mercurial, Visual Source Safe and many others. See http://en.wikipedia.org/wiki/Comparison_of_revision_control_software
I'm currently using SVN, but they are all fairly similar.
(Note: those people who are familiar with distributed version control are entitled to scream at me for the previous statement.  I don't use DVCS I know they perform a similar but in a totally different way)

A few terms
See: http://betterexplained.com/articles/a-visual-guide-to-version-control/ for a good summary.
I'm using the SVN terms as it will help later
  • Repository: The 'shared directory' where the code lives, usually on a hosted server somewhere
  • Import: take some brand new code & put it into the repository
  • Check out: Get a fresh set of the code (usually the latest version) from the repository onto your local machine
  • Update: Update the code on your local machine with the latest version in the repository
  • Commit: Copy the code from your local machine into the repository
  • Conflict: What happens when you try to commit some code and someone else has already made a modification to it

Getting started
You will need:
  1. A repository
    • Since you want this to be accessible by your team all the time, its a bad idea to stick it on your machine (unless you have a spare server which you can use), so here are a few options.  They all have free plans and many have paid plans too.
    • You only need one person to set up the repository, but you will need accounts for all your developers
  2. A SVN client
  3. Some code (duh!)

Setting up the Repository and performing the initial import
This is a little tedious, but only need to do once, so its a good idea to have your senior/experienced developer do this.
My example will be using https://riouxsvn.com/ and http://tortoisesvn.net/, but its roughly the same for all.

1. Go to your host and set up the repository
You will have to figure this one out for yourself. But it should be simple enough.
While you are doing this, look out for an option to create 'trunk' and all the other default directories.
(I usually do this, but I'm not 100% sure I really need to)
Once you are done, look out for the URL of your SVN repository, it looks like a normal URL. You will need this later.

2. Create an (almost) empty directory to put your code into
Advise: Never start by putting 300 files into your repository on the first attempt. KISS.  If it doesn't work, its only one file.

As SVN cannot put empty directories into the repository, I always create a empty directory and put a readme.txt in there, then import this.
Note: I like to add the entire directory into source control. This gives me the option to put multiple project into one repository if I want.  I'm not sure if its a best practice, but it seems logical.

Right click on the new DIRECTORY (not the file), and import it.
When the dialog appears you will need to enter the URL of the repository which should be of the form:
https://whatever_the_SVN_repository_was/trunk/project_name
(Most will be https, though it might be http)
You need to get this first bit right, or you will hit all sorts of problems.  I always have project_name as the same as the directory, mainly for convenience.  I never have spaces or strange characters in it.  And remember to choose a suitable name too. (I have an SVN project called 'labtask', oops!)
It might ask you for your username & password, but you should soon see a result like this:
Take note of the full URL as you will need to pass this information to all your fellow developers.

At this point, I will usually delete/rename the directory away and perform the checkout (see part 2) to make sure it worked.

Continued in part 2

Mark