SDL Tutorial Series - Part 8 - Simple Keyboard Input using SDL Continued


The last tutorial showed you how to get keyboard input from the player using a technique called polling. As promised, this tutorial will show you how to get input from the player using the event-driven approach. Polling works pretty good if we only need to check a few keys each frame. But what if we had to check for a lot of keys? We would have a lot of if statements in our input logic. The SDL offers an easy way for us to use the event-driven approach in our video games.

We will be modifying the last tutorial so open it up in your compiler. Scroll down to this section of the code.
// Gain access to keystate array
Uint8 *keys = SDL_GetKeyState(NULL);

Remove those two lines and add this:
// Movement variable;
bool move_left = false;
bool move_right = false;
bool move_up = false;
bool move_down = false;

Now, scroll down to the main loop and find these lines:
// Check for messages
if (SDL_PollEvent(&event))
{

Add the following after the curly brace:
// Check for keys
if (event.type == SDL_KEYDOWN)
{
   SDLKey key = event.key.keysym.sym;
   if (key == SDLK_LEFT)
      move_left = true;
   if (key == SDLK_RIGHT)
      move_right = true;
   if (key == SDLK_UP)
      move_up = true;
   if (key == SDLK_DOWN)
      move_down = true;
}
if (event.type == SDL_KEYUP)
{
   SDLKey key = event.key.keysym.sym;
   if (key == SDLK_LEFT)
      move_left = false;
   if (key == SDLK_RIGHT)
      move_right = false;
   if (key == SDLK_UP)
      move_up = false;
   if (key == SDLK_DOWN)
      move_down = false;
}

One more modification and we are done. Scroll down and find this block of code:
// Handle input
if (keys[SDLK_LEFT])
   x -= MOVE_SPEED * ftime;
if (keys[SDLK_RIGHT])
   x += MOVE_SPEED * ftime;
if (keys[SDLK_DOWN])
   y += MOVE_SPEED * ftime;
if (keys[SDLK_UP])
   y -= MOVE_SPEED * ftime;

Change it to this:
// Handle input
if (move_left)
   x -= MOVE_SPEED * ftime;
if (move_right)
   x += MOVE_SPEED * ftime;
if (move_down)
   y += MOVE_SPEED * ftime;
if (move_up)
   y -= MOVE_SPEED * ftime;

Alright, that is it. You should be able to compile and run the program. You will notice that the program behaves exactly like it did before. You might be wondering why we used more lines of code to do the same thing. The answer to that question is to show a different technique for input. Lets say our video game displays a menu when the player presses the F10 button. In the previous tutorial, we would have to check every frame if the F10 button was being pressed. Now, we could just add a check in the event structure to display the menu when the key gets pressed. This is better because we respond to an action taking place instead of checking for an action every frame.

Another note of importance is we are using the same SDLKey definitions as before. This shows the versatility of the SDL library. In the next tutorial you will see how to get mouse input into your game by using the SDL.


See Also:


Back to SDL Tutorial Index

Back to Main Page

SDL Tutorial Series - Part 7 - Simple Keyboard Input using SDL


Every video game needs to get input from the player in order to respond to his or her actions. Without input, there would be no interaction with the user and it would not be a game. This tutorial will teach you a simple method for getting keyboard input from the player by using the SDL library.


We are going to use a technique called polling instead of the event-driven approach. Think of polling like taking a survey. Every frame of our game simulation, we survey which keys are being pressed at that particular time. This is the simplest way to get keyboard input into our application. SDL provides us with a very nice function for this. Here it is:

Uint8 *SDL_GetKeyState(int *numkeys);

This function returns a pointer to an array that holds the state of every key on the keyboard. If a key is being pressed, its value will be one and if not its value will be 0. SDL defines constants to access this array. For example, the space key is defined as SDLK_SPACE. A full list of these constants can be found here. Lets look at the code for this tutorial to see how this all works. I am going to assume at this point that you know how to set up an SDL project in your compiler/platform.

#include <iostream>
#include <SDL.h>

#define MOVE_SPEED 100.0f

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");

   // Gain access to keystate array
   Uint8 *keys = SDL_GetKeyState(NULL);

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

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

   // Box
   float x = 35.0f, y = 35.0f;
   SDL_Rect rect;
   rect.h = 30;
   rect.w = 30;

   // Main loop
   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;
         }
      }

      // Handle input
       if (keys[SDLK_LEFT])
         x -= MOVE_SPEED * ftime;
       if (keys[SDLK_RIGHT])
         x += MOVE_SPEED * ftime;
       if (keys[SDLK_DOWN])
         y += MOVE_SPEED * ftime;
       if (keys[SDLK_UP])
         y -= MOVE_SPEED * ftime;

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

      // Draw box
      rect.x = static_cast<int>(x);
      rect.y = static_cast<int>(y);
      if (SDL_FillRect(display, 
                       &rect,
                       SDL_MapRGB(display->format, 255,255,255))
                       != 0)
      {
         cerr << "SDL_FillRect() Failed: " << SDL_GetError() << endl;
         break;
      }
        //Update the display
      SDL_Flip(display);

   }

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

After you have copied the source code into your program be sure to save your progress. Go ahead and compile and run the program. You should see a white box on the screen. Press the arrow keys on your keyboard to move this box around. As you can see, it is incredibly easy to get keyboard input into your program by using the SDL. In the next tutorial, you will see how to get keyboard input using the event-driven approach.


See Also:


Back to SDL Tutorial Index

Back to Main Page

SDL Tutorial Series - Part 6 - Displaying Text with SDL_ttf


This tutorial will show you how to display text in your SDL applications. Almost every video game needs to display text to the player at some point. We will be using the SDL_ttf library because the standard SDL library does not contain the ability to draw text directly. In order to do this you will have to download and install the SDL_ttf library here. If you are developing on Windows, click on the link labeled 'SDL_ttf-devel-2.0.9-VC8.zip'.

We need to setup the SDL_ttf library so extract the contents of the zip file. Inside the folder there should be a 'include' and 'lib' folder. Copy the SDL_ttf.h header file to the same folder you put SDL.h in tutorial 2. Now, go to the lib folder and copy SDL_ttf.lib to the same folder you placed SDL.lib and SDLmain.lib. Since we already set Visual C++ to include these folders it makes sense to place these files with the main SDL library files.

Create a new project in Visual C++ just like you did in tutorial 3. After you have created your project and have a blank 'Main.cpp' file copy this code.

#include <iostream>
#include <SDL.h>
#include <SDL_ttf.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");

   // Initialize SDL_ttf library
   if (TTF_Init() != 0)
   {
      cerr << "TTF_Init() Failed: " << TTF_GetError() << endl;
      SDL_Quit();
      exit(1);
   }

   // Load a font
   TTF_Font *font;
   font = TTF_OpenFont("FreeSans.ttf", 24);
   if (font == NULL)
   {
      cerr << "TTF_OpenFont() Failed: " << TTF_GetError() << endl;
      TTF_Quit();
      SDL_Quit();
      exit(1);
   }

   // Write text to surface
   SDL_Surface *text;
   SDL_Color text_color = {255, 255, 255};
   text = TTF_RenderText_Solid(font,
   "A journey of a thousand miles begins with a single step.",
   text_color);

   if (text == NULL)
   {
      cerr << "TTF_RenderText_Solid() Failed: " << TTF_GetError() << endl;
      TTF_Quit();
      SDL_Quit();
      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;
         }
      }

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

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

        //Update the display
      SDL_Flip(display);

   }

   // Shutdown the TTF library
   TTF_Quit();

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

There are a couple of steps left before we can run this program. First, we need to download some true type fonts. Go here and scroll all the way to the bottom. Download the file 'freefont-ttf.zip', it should be the second one up from the bottom. Extract the contents of this file and copy 'FreeSans.ttf' inside your project folder to where your source code is. This is very important! I named my file 'Main.cpp' and the 'FreeSans.ttf' file is in the same folder. I named my project 'SDLTutorial6' so folder structure looks like this:

SDLTutorial6\SDLTutorial6

You will also need to copy SDL.dll, SDL_ttf.dll, libfreetype-6.dll, and zlib1.dll to the same folder as your exe file. My exe file is in the SDLTutorial6\Debug folder since I am building a debug version. Yours should be in the same.

The last step is to tell the linker to include the SDL.lib, SDLmain.lib and SDL_ttf.lib files. We did this in tutorial 3 so if you need to, refer back to that tutorial. Also, set your project to use the 'Multi-threaded DLL (/MD)' like we did before.

You are now ready to compile and run your program. If all went well you should see the following:

Photobucket


Lets look at the new functions we used in this tutorial.
int TTF_Init()

We have to initialize the TTF library just like the SDL. If there were no errors, 0 is returned and we can use the library. We also have to shut down the library with this function.
void TTF_Quit()
Error information can be obtained by calling this function.
char *TTF_GetError()
This behaves just like SDL_GetError(). The SDL_ttf library is meant to be an extension of SDL and is designed in a similar manner.

The next two functions are the heart of this tutorial.
TTF_Font *TTF_OpenFont(const char *file, int ptsize)
This function opens a true type font file specified by the first parameter in the size specified by the second parameter. It returns a pointer to a TTF_Font structure which can be used for rendering text to SDL_Surfaces by the rendering functions. The rendering function we use in this tutorial is this one.
SDL_Surface *TTF_RenderText_Solid(TTF_Font *font, const char *text, SDL_Color fg)
This function renders the text specified by the second parameter by using the font we previously loaded. It can be rendered in any color specified by the third parameter. It renders the text to an SDL_Surface structure which can then be blitted to the screen. What is nice about this is that we do not have to do this every frame as long as the text remains the same. You will notice in the code that we create the SDL_Surface before the loop. In the loop, we just blit the surface to the screen and do not have to render the text again.

That is it for this tutorial. I encourage you to experiment with this tutorial and play around with the code. Try changing the text, font, color, etc. I find it is best to learn through experimentation. The SDL_ttf library is a nice extension for the SDL library and is a simple way to get text rendered on the screen.


See Also:


Back to SDL Tutorial Index

Back to Main Page