SDL Tutorial Series - Part 5 - Dealing with Time


Timing information is essential for video game programming. The programmer must keep track of how much time has elapsed since the last frame for the video game simulation to run properly. Timing must be used to properly run animations, run physics for game objects, and trigger events such as a scripted sequence. Your games will need to access timing information and this tutorial will show you how by using the SDL.

There are only four functions in the SDL that relate to time. The one that we are most interested in is this one:
Uint32 SDL_GetTicks(void)
This function will return the number of milliseconds that have elapsed since the SDL was initialized. A millisecond is defined as a thousandth (1/1000) of a second. This will provide us with enough accuracy for use in games. At first glance this does not seem all that useful but you will soon see how great this function is.

We will be adding onto the code from the previous tutorial. If you have not done so already, open the code in your compiler and we will begin.

First, find this line:
// Main loop
SDL_Event event;

After it add the following:
// Image motion variables
float x = 0.1f, y = 0.1f;
float xVel = 50.0f, yVel = 40.0f;

// Timing variables
Uint32 old_time, current_time;
float ftime;

// Need to initialize this here for event loop to work
current_time = SDL_GetTicks();

Change the while loop to this:
while(1)
{
   // Update the timing information
   old_time = current_time;
   current_time = SDL_GetTicks();
   ftime = (current_time - old_time) / 1000.0f;

   // Check for messages
   if (SDL_PollEvent(&event))
   {
      // Check for the quit message
      if (event.type == SDL_QUIT)
      {
         // Quit the program
         break;
      }
   }
   // Update the image position
   x += (xVel * ftime);
   y += (yVel * ftime);

   // Check boundaries
   if (x <= 0.0f)
      xVel *= -1.0f;
   if (x >= (display->w - image->w))
      xVel *= -1.0f;
   if (y <= 0.0f)
      yVel *= -1.0f;
   if (y >= (display->h - image->h))
      yVel *= -1.0f;

   // Clear the screen
   if (SDL_FillRect(display, NULL, SDL_MapRGB( display->format, 0,0,0)) != 0)
   {
      cerr << "SDL_FillRect() Failed: " << SDL_GetError() << endl;
      break;
   }

   SDL_Rect dest;
   dest.x = static_cast<int>(x);
   dest.y = static_cast<int>(y);

   // Apply the logo to the display
   if (SDL_BlitSurface(image, NULL, display, &dest) != 0)
   {
      cerr << "SDL_BlitSurface() Failed: " << SDL_GetError() << endl;
      break;
   }

   //Update the display
   SDL_Flip(display);
}

Alright, that is it. Be sure to save your progress. You should now be able to compile and run the program. Select 'Build' from the menu bar and click on 'Build Solution'. There should not be any errors or warnings. Now, select 'Debug' from the menu bar and click on 'Start Without Debugging'. You should see the image we used from the previous tutorial moving around the screen and bouncing off the sides. Now that you have seen the program in action, lets examine how it works.

Notice we used three variables to hold timing information: old_time, current_time, and ftime. The old_time and current_time variables are both 32 bit unsigned integers while the ftime variable is a floating point decimal number. Every time we begin the while loop, we record the number of ticks that have elapsed since the SDL was initialized in the current_time variable. We save the old value of current_time in the old_time variable. This is done in order to measure the amount of ticks it took us to complete the previous frame (the one currently being displayed). We take the difference of current_time and old_time, then divide by 1000 to calculate the delta time, which is stored in the variable ftime. If you have taken a physics class you should be familiar with delta time. Remember, there are 1000 ticks per second. If the difference between current_time and old_time was 500 ticks and we divide by 1000, the result would be 0.5 or 1/2 of a second. As you can see, by using SDL_GetTicks() we have a way of measuring the amount of ticks that has elapsed since the last frame and can convert that value to a decimal value.

The motion of the image is controlled by taking the velocity and multiplying it by ftime, then adding it to the position. This is called Frame Rate Independent Movement because no matter how long it takes in between frames, the object moves correctly. The velocity is specified in screen pixels and here the x velocity is 50 pixels a second and the y velocity is 40 pixels a second. If it took 1/10 of a second to render the previous frame then 50 * (1/10) would be 5 pixels in the x direction and 4 pixels in the y direction (40 * 1/10). It is important to note here that the SDL places the origin (0, 0) at the upper left-hand corner of the window. So an increase in x position moves the image to the right and an increase in y moves the image down.

If we let the image move in the same direction without changing its course, it would move off screen. To prevent this, we use 4 if statements to check that it stays inside the window. Remember, SDL measures screen space from the upper left so we have to subtract the width in order to see if the image went too far to the right. It is the same for the y direction.

You will notice that we added this function before we blit the image to the screen.
int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
This function clears every pixel on the screen to the color specified (pure black in our case). Here we use another function, SDL_MapRGB(), to generate the color for us. SDL_MapRGB() will generate a color that is in the same format as our screen so when we call SDL_FillRect(), it should be really fast (in theory). The reason we call this function is to clear the last frame we drew into this buffer. The screen buffer is really just an array of memory and this buffer holds the values we previously copied into it. We need to erase these values and this is how we do it. We set every value in this array to black. Try commenting out this function and then recompile your program to see what happens.

One more item to mention and then we are done. We modified the fourth parameter in SDL_BlitSurface() to use the SDL_Rect structure specified. This allows us to specify where we want to blit the image (in screen coordinates). Here, we cast the x and y position from float to int in order to properly specify the screen coordinates.

This is the end of this tutorial. You have learned how to use SDL_GetTicks() to get timing information from the system to use in your video games. Getting objects to move properly is essential to programming video games and you can now say with pride that you know how to do that. I encourage you to play around a little with this tutorial. Try changing the x and y velocity variables to see how it affects the movement of the image. Also, try clearing the screen to different background colors.

Back to SDL Tutorial Index

Back to Main Page

SDL Tutorial Series - Part 4 - How to Load and Display Images


In part 4 of this tutorial series, you will learn how to load an image from a file and display it on the screen using the SDL. This tutorial will build off of part 3 in this tutorial series so be sure you understood everything that was covered.

Arguably one of the most important parts of any video game are the graphics. The visuals are what will grab your players' attention and draw them into your video game. It is essential to creating a video game that you know how to properly display images on the players screen. We will be adding onto the code from part 3 so open the project in your compiler and we will begin.


First, find this line:

// Set the title bar
 SDL_WM_SetCaption("SDL Tutorial", "SDL Tutorial");

After it add this line:

// Load the image
SDL_Surface* image;
image = SDL_LoadBMP("gptutorials.bmp");
if (image == NULL)
{
     cerr << "SDL_LoadBMP() Failed: " << SDL_GetError() << endl;
     exit(1);
}

gptutorials
This is the image we will display on the screen. Right click on it and select 'Save image as'. Type in "gptutorials.bmp" without the quotes. Make sure where it says 'Save as type:' you select 'All Files'. This is very important! Save the bmp file in the same folder as your source code. If you named your project 'SDLTutorial', then it will be the 'SDLTutorial'->'SDLTutorial' folder. If you see your source code file (Main.cpp) in the folder then that is the correct folder. After you have done that find this line:
// Game loop will go here...
Right after that line add the following:
// Apply the image to the display
if (SDL_BlitSurface(image, NULL, display, NULL) != 0)
{
 cerr << "SDL_BlitSurface() Failed: " << SDL_GetError() << endl;
 exit(1);
}

//Update the display
SDL_Flip(display);
Alright, that is it! As you can see, the SDL makes complex tasks easy. All we had to do in order to load a bmp file was call one function. It does not get any easier than that. Your Main.cpp file should now look like this:
#include <iostream>
#include "SDL.h"

using std::cerr;
using std::endl;

int main(int argc, char* args[])
{
    // Initialize the SDL
    if (SDL_Init(SDL_INIT_VIDEO) != 0)
 {
  cerr << "SDL_Init() Failed: " << SDL_GetError() << endl;
  exit(1);
 }

 // Set the video mode
 SDL_Surface* display;
 display = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
 if (display == NULL)
 {
  cerr << "SDL_SetVideoMode() Failed: " << SDL_GetError() << endl;
  exit(1);
 }

 // Set the title bar
 SDL_WM_SetCaption("SDL Tutorial", "SDL Tutorial");

// Load the image
 SDL_Surface* image;
 image = SDL_LoadBMP("gptutorials.bmp");
 if (image == NULL)
 {
     cerr << "SDL_LoadBMP() Failed: " << SDL_GetError() << endl;
     exit(1);
 }

 // Main loop
 SDL_Event event;
 while(1)
 {
  // Check for messages
  if (SDL_PollEvent(&event))
  {
   // Check for the quit message
   if (event.type == SDL_QUIT)
   {
    // Quit the program
    break;
   }
  }
  // Game loop will go here...
  // Apply the image to the display
  if (SDL_BlitSurface(image, NULL, display, NULL) != 0)
  {
 cerr << "SDL_BlitSurface() Failed: " << SDL_GetError() << endl;
 exit(1);
  }

  //Update the display
  SDL_Flip(display);

 }

    // Tell the SDL to clean up and shut down
    SDL_Quit();
    
    return 0;    
}
Make sure to save your progress. You should now be able to compile and run the program. Select 'Build' from the menu bar and click on 'Build Solution'. There should not be any errors or warnings. Now, select 'Debug' from the menu bar and click on 'Start Without Debugging'. You should see the window popup and the image applied in the upper left hand corner of the window. Lets look at the 3 functions we added to the program.
SDL_Surface *SDL_LoadBMP(const char* file);
This function loads the specified file into memory and converts it into an SDL_Surface structure which we can use for blitting to the screen. For now, do not worry about the SDL_Surface structure, we will examine it more in a future tutorial. If the function succeeds, it returns a valid pointer to an SDL_Surface structure. If it failed, it returns a NULL pointer and a description of the error can be obtained by calling SDL_GetError().
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
This function copies our image data to the screen. The first argument specifies where the image data is coming from and the third argument specifies where you want the data to go. In our case the source is the bmp file we loaded and the destination is the screen. You probably noticed we did not use the second and fourth arguments in this program. The second parameter (srcrect) can be used to blit sub-images from the source. The fourth argument can specify the position on the screen to copy the image to.
int SDL_Flip(SDL_Surface *screen);
Remember when we called SDL_Init(), we specified we wanted double buffering? This function will swap the buffers for us. This is not all that useful to us since we just copy a static image to the screen, but in future tutorials we will be adding animation. Double buffering is essential to animation to prevent flickering. I did not bother checking the return value of this function but you should. It returns -1 if there was an error or 0 on success. I leave adding error checking for this function as an exercise to the reader.

That is it for this tutorial. You now know how to display images on the screen by using the SDL library. This is essential to being able to program video games and we will build on this foundation in future tutorials. I hope you are enjoying using the SDL and can see the simplicity in its design. The next tutorial will introduce you to the SDL timing functions and how they can be used for simple animation.

Back to SDL Tutorial Index

Back to Main Page

SDL Tutorial Series - Part 3 - Your First Application

This tutorial will help you create your first SDL application using Microsoft Visual C++ Express 2008. You are going to learn how to initialize and shutdown the SDL and how to create a window. Also, you will see how the SDL handles events that are sent from the system. If you have not done so already, open up Microsoft Visual C++ Express so we may begin.

Once you have opened Visual C++, click on File and select New, then Project...


NewProject


In the 'New Project' dialog box, select Win32 Console Application. At the bottom of the dialog box enter a name for the project, 'SDLTutorial' should be fine. Also, select a location for the project. Important! Remember where you saved the project because this will be important later on.


NewProjectDialog


After you click 'OK', you will see a new dialog box labeled 'Win32 Application Wizard'. Click on the 'Next >' button and you should see this dialog box.


ApplicationSettings


Make sure that you select the 'Empty Project' check box. This should be the only change you need to make. Click on the 'Finish' button.

Now, click on 'Project' from the menu bar and select 'Add New Item...'. You should see a dialog box like this.


NewItem


Be sure to select C++ File (.cpp) and enter a name for the file. 'Main' will suffice for our purposes, so click on the 'Add' button to add it to your project.

Paste the following code into the source code file you just created:
#include <iostream>
#include "SDL.h"

using std::cerr;
using std::endl;

int main(int argc, char* args[])
{
    // Initialize the SDL
    if (SDL_Init(SDL_INIT_VIDEO) != 0)
 {
  cerr << "SDL_Init() Failed: " << SDL_GetError() << endl;
  exit(1);
 }

 // Set the video mode
 SDL_Surface* display;
 display = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
 if (display == NULL)
 {
  cerr << "SDL_SetVideoMode() Failed: " << SDL_GetError() << endl;
  exit(1);
 }

 // Set the title bar
 SDL_WM_SetCaption("SDL Tutorial", "SDL Tutorial");

 // Main loop
 SDL_Event event;
 while(1)
 {
  // Check for messages
  if (SDL_PollEvent(&event))
  {
   // Check for the quit message
   if (event.type == SDL_QUIT)
   {
    // Quit the program
    break;
   }
  }
  // Game loop will go here...
 }

    // Tell the SDL to clean up and shut down
    SDL_Quit();
    
    return 0;    
}

In the menu bar, select 'Project' and then 'Properties' at the bottom of the menu.


SDLTutorialProperties


We need to modify some settings in order for the SDL program to run. Expand the 'C/C++' list and select 'Code Generation'. On the right, select 'Runtime Library' and set it to 'Multi-threaded DLL (/MD)'.

Go back to the list box on the left and expand the 'Linker' category. Select the 'Input' field and on the right select 'Additional Dependencies'. Type in the following:

SDL.lib SDLmain.lib

Note: This is case sensitive so be sure to type this exactly as shown.

Click on the 'OK' button. You should now be able to compile and run the program. Select 'Build' from the menu bar and click on 'Build Solution'. If everything worked as it should there should be no errors and no warnings. You need to copy SDL.dll to the same folder as the .exe file you just created. It should be in the 'Debug' sub-folder inside where you saved your project. Now, select 'Debug' from the menu bar and click on 'Start Without Debugging'. You should get a black window to popup and the title should be 'SDL Tutorial'.

Congratulations! You have just built and run your first SDL application. It does not do much of anything interesting but in future tutorials we will be adding elements to it. Let me explain some of the SDL functions to you.

The first function of interest is:
int SDL_Init(Uint32 flags)
This function initializes and loads the SDL library. All you need to know is if it was successful in loading the SDL library. If it was successful it will return 0. If there was an error, it will return -1. Information about the error can be obtained by the next function.

char* SDL_GetError(void)
This function will return a null terminated string that has information about the last internal error generated by the SDL library. This can be very useful in discovering errors in our program code.

The next function allows us to set our video mode.
SDL_Surface* SDL_SetVideoMode(int width, int height, int bitsperpixel, Uint32 flags)
With this function we can set the width and height of our window and the bits per pixel (16 or 32 are the most common). The flags parameter is of special note here. In this tutorial we set the flags to SDL_HWSURFACE and SDL_DOUBLEBUF by ORing them together. These will be most useful to us in future tutorials since we are interested in making games. We could have selected a software surface by specifying SDL_SWSURFACE instead of SDL_HWSURFACE but the hardware surface should be faster. Also, we selected double buffering for our application because this allows us to display one buffer to the user while we perform all drawing operations on the back buffer. Once we are finished drawing the current frame on the back buffer, we swap the buffers and display the one we just finished to the user. This allows us to provide the user with smooth animation and prevents him or her from seeing the frame being drawn which will break the immersion. Note: if you want a full screen window, you can pass SDL_FULLSCREEN to attempt full screen at the specified resolution.

void SDL_WM_SetCaption(const char *title, const char *icon);
This function sets the caption for our window. The first parameter is the string to display in the title bar of our window and the second parameter will be displayed when the window is minimized.

int SDL_PollEvent(SDL_Event *event)

This function will check to see if any events have been posted to the event queue. If there are events in the queue, the function pops the event off the queue and stores it in the SDL_Event data structure pointed to by event. It returns 1 if there is an event or 0 if there are none in the queue. The only event we care about for now is if the quit message has been posted. This will occur when the user clicks the 'x' button on the title bar. We will learn more about events that can occur in our SDL applications in a future tutorial. If you are not familiar with event driven programming I suggest you check out the tutorial on this site here.

void SDL_Quit(void);
This function should always be called if you are using the SDL before exiting your program. It shuts down all the subsystems, unloads all the dynamically linked libraries, and frees any allocated resources.

You have now successfully completed your first SDL application. You should have gained an understanding of the basic functions of the SDL and how they work together to create a functional application. The next tutorial will cover displaying graphics on the screen which will be fundamental in creating video games using the SDL.

Back to SDL Tutorial Index

Back to Main Page.

An introduction to Event-Driven Programming

Event-driven programming or Event-based programming refers to a computer programming technique that involves controlling the flow of a program by receiving signals (also called messages or events) from an outside source. The source of the message can be anything from another program, a thread, or it could be generated from within the program. There are two necessary data structures for the construction of an event-driven system: an event listener and an event handler.

An event listener will store messages that are passed to it from an outside source. This is usually implemented as a queue or stack. Messages are stored for later dispatching by the event handler. Observe the following diagram.


Event Driven Diagram


Messages A, B, and C get passed to the event listener which will then be retrieved by the event handler. These messages could be generated from a variety of sources and generated at different time intervals. It is important to note that until the event handler processes the messages, the event listener will store them.

Event Driven programming is heavily used in Graphical User Interfaces (GUIs). Imagine what happens when you move the mouse and press the left mouse button. First, a mouse move message would be sent to the window that has the focus. Maybe the window will want to know the new x and y coordinate of the mouse position. Second, a mouse click message will be sent to the window. If the mouse cursor is over a button then the left click would trigger another event that would get sent to the event listener. Imagine writing a program that had to check for each of the possible actions a user could perform in your program. You would waste CPU cycles checking for events that did not happen. Event driven programming solves this problem.

Event driven programming is a different way to think about the flow of your program. Usually when one sets out to learn programming, he or she thinks of the flow of the program as a linear progression from beginning to end. Using event driven programming, you can think in terms of events that happen to your program.

Back to Main Page

SDL Tutorial Series - Part 1 - What is the SDL?

SDL Logo
So what is the SDL? The SDL home page states that, "Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer." The key-word in that description is cross-platform. SDL provides us with a platform independent way to access multimedia resources that we can use for making games. By using the SDL, we can share a common codebase across multiple platforms like Windows, Linux, and Mac OS X.

A fine example of a video game that uses the SDL is World of Goo. This critically acclaimed game was made by a small team of developers who used the SDL in their development process. Because they used the SDL, they were able to release the game for Windows, Mac OSX, and Linux with little modification to the underlying code base. Here is a short video trailer for the game.



Besides being cross-platform, the SDL is intuitive and very easy to use. It is written in the C programming language and has a function based syntax. The programmer controls the API by passing parameters to functions. Although written in the C programming language, SDL works with C++ and has bindings for many other languages including: C#, Python, Java, Objective C, D, and many others. The best part of the SDL is that it is FREE! As long a you link to the dynamic libraries you can use the SDL in your programs free of charge. For more information about the SDL, check out the SDL home page.

Back to SDL Tutorial Index

Back to Main Page