Click here to Skip to main content
Click here to Skip to main content

Game Programming - One

By , 8 May 2008
Rate this:
Please Sign up or sign in to vote.

Introduction

The aim of these tutorials is, initially, to show you how to create a simple game, from scratch, without the help of higher level APIs like XNA or DirectX which automate half the process for you. All we will be using is a Windows Form and GDI+ to do some basic drawing, and for a little extra convenience, a few of the Form's events.

Next »

Background

There will be a few slightly odd things with the game loop and the flow of logic; this is because Windows Forms are event based, while on the whole, games are generally not. I will point out the differences there may be between some 'regular' code and the code that must be used for the Windows Form.

Step 1: Setting Up The Game

A Basic Loop

Since games are not usually event driven, we use a loop and perform any logic and drawing from this loop. So, in each loop, we will perform the game's logic, check for input, and draw graphics to the screen. Look at the below code. Can you see any problems?

bool runGame = true;
while(runGame)
{
  GetInput();
  PerformLogic();
  DrawGraphics();
}

If you noticed that the game will run as fast as possible, then well done. With this loop, the game will run as fast as it can, which could be anything from 1fps to upwards of 1000fps. The speed of the game may vary as enemies or objects are added to the game, and the game may simply run too quickly for a player to react in time.

It's All About Timing

We need to control the speed at which the game runs; for this we use a timer. The timer will set a flag so that we know when to run the logic in our main loop; that way the game will run at a much more manageable pace.

Timer MainTimer;
//The timer’s interval is in milliseconds, so we need to work out
//how long each interval should be
MainTimer.Interaval = 1000/60;
bool runGame = true;
volatile bool doStuff = false;
Main()
{
  while(runGame)
  {
    if(doStuff)
    {
      GetInput();
      PerformLogic();
      DrawGraphics();
      doStuff = false;
    }
  }
}

Timer()
{
  doStuff = true;
}

We Can Do Better Than That!

Although this will limit the game's speed to an acceptable level, there is still more we can do. Drawing graphics to the screen is usually the slowest part in a game, so if the scene takes too long to render, it will cause the logic to run slowly and the whole game will slow down. To avoid this problem, we need to separate drawing the graphics from the rest of the logic, and then we need to make sure that the logic gets priority over rendering the scene. This means that if the logic is falling behind, we should not update the graphics during that loop, so we drop the frame.

This is the setup that we will be using to manage our game:

Timer MainTimer;
//The timer’s interval is in milliseconds, so we need to work out
//how long each interval should be
MainTimer.Interaval = 1000/60;
bool runGame = true;
volatile uint speedCounter = 0;
Main()
{
  while(runGame)
  {
    if(speedCounter >0)
    {
      GetInput();
      PerformLogic();
      speedCounter--;
      if(speedCounter == 0)
        DrawGraphics();
    }
  }
}

Timer()
{
  speedCounter++;
}

In this loop, the logic will only run if the counter is greater than zero. After all of the logic has been run, we decrease the counter by one, and if the counter is back at zero, we will update the scene. If the entire loop takes longer than one frame (the interval of the timer), then when we decrease the counter; it will still be greater than zero, so we drop the frame and see if we can get back some time.

Changes For A Form

If we use a while loop on our Windows Form, then Windows will never update the screen, and the application will hang. For this reason, we will be putting the logic within the callback function of our timer, for now anyway - later on, we will put it in its own thread. Apart from this, everything will remain the same. The final code will look similar to this:

bool drawGraphics = false
void TimerElapsed()
{
  //Increase the counter
  speedCounter++;

  GetInput();
  PerformLogic();
  speedCounter--;

  //If the counter is 0, then the logic is not running slow
  //we can therefore get on with drawing the graphics
  if(speedCounter == 0)
    drawGraphics = true;
}

We also need to override the OnPaint and OnPaintBackground methods so that Windows will not do any drawing itself and we can handle it ourselves. Remember, we will not be calling base.OnPaint or base.OnPaintBackground.

protected override void OnPaint(PaintEventArgs e)
{
   //We do our drawing here
}

protected override void OnPaintBackground(PaintEventArgs e)
{
  //Do nothing
  //base.OnPaintBackground(e);
}

GDI+

Since we will be using it to draw our graphics, I thought it best we go over how to use it. To start drawing, we need a few things:

  1. A graphics object (this will do the drawing).
  2. A surface to draw onto.
  3. A pen or brush to draw with - no, really.

If we override the OnPaint method of our form, we can use the Graphics object in the PaintEventArgs which already has the form as the surface. You can then use the methods in the Graphics object to draw onto the screen:

override void OnPaint(PaintEventArgs e)
{
  //We can draw with e.Graphics

  //Brushes are used to fill areas
  Brush myBrush = new SolidBrush(Color.Red);
  e.Graphics.FillRectangle(myBrush,0,0,100,100);
  
  //Pens are used to draw lines
  Pen myPen = new Pen(Color.Green);
  e.Graphics.DrawLine(myPen, 50, 250, 65, 15);
}

The Demo

The demo contains the game loop we've been talking about, plus a little drawing code so we can see things on the screen.

What? Homework!

Before I write up the next article (or before you just go and read it), why not try to edit the demo so that the circle moves around on the screen? Oh come on, it's not that difficult, I know you can do it if you try.

Coming Up

Well, that's all I've got time for. But on the bright side, now that we have our basic game code, we can start to do stuff with it. Coming up in the next article:

  • Double Buffering
  • Getting Input
  • Setting Up An FPS Counter
  • Drawing And Animating A Sprite

What Do You Want?

Feel free to post about what you'd like to see in these articles. I am here trying to help, so if I know how to do what you are asking, I'll try and include it. These articles are heading through the world of 2D games, and up into the realms of 3D - though we might have to hop over to C++ and OpenGL for that one. I've never much liked DirectX, and I've never used XNA for 3D. Remember, I'm not trying to give you code to make a game, but showing you how to construct code that can be used to make a game - if you follow, the language shouldn't be so important.

History

  • 8th May 2008 - Article submitted.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Anthony Mushrow
Software Developer
England England
*blip*

Comments and Discussions

 
GeneralMy vote of 5 PinmemberMember 990888013-Mar-13 23:53 
GeneralMy vote of 5 Pinmemberbitzhuwei7-Feb-13 0:30 
GeneralMy vote of 5 PinmemberNergal_Perm23-Dec-10 22:36 
Generalsuweeeet!! Pinmemberwilliam h johnson iii17-May-08 9:18 
GeneralCool! PinmemberThiago Azevedo Falcao14-May-08 7:46 
Jokegood for explaination abt the timer using in loop Pinmemberhusoso13-May-08 15:20 
GeneralCPU consumption PinmemberTomáš13-May-08 1:16 
GeneralRe: CPU consumption PinmemberSK Genius13-May-08 2:09 
GeneralRe: CPU consumption Pinmembersoft213-May-08 9:38 
GeneralClear and Simple PinmemberDurga Prasad Dhulipudi10-May-08 18:24 
Generalcool PinmemberNiiiissssshhhhhuuuuu9-May-08 4:35 
Generalgood job Pinmembersean13329-May-08 1:25 
GeneralNice and simple PinmemberIshitori8-May-08 20:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140421.2 | Last Updated 8 May 2008
Article Copyright 2008 by Anthony Mushrow
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid