SDL Tutorial Basics
SDL Tutorials October 17th, 2007These tutorials are meant to teach someone with some experience using C++, or perhaps another programming language. If you have a hard time following certain ideas related to the code itself and not conceptual ideas (those relating to games), then I urge you to first read our tutorials that explain the C++ programming language. It’s not vital to understand everything about C++, but every little bit will help later on.
In these tutorials we will be referncing to CodeBlocks as our IDE of choice, with gcc and mingw for compilation. If you wish to use another IDE and compiler that is up to you, but it may be harder to follow along if you have limited experience with linking libraries. If you wish to download CodeBlocks, you can do so for free at http://www.codeblocks.org (download the one including the mingw package). We recommend you use the stable version, unless you want to spend the extra time and use the nightly builds.
These tutorials will be heavily centered around SDL (Simple DirectMedia Layer), a 2D cross-platform graphics library. This library is going to allow us to draw fancy graphics to the screen, and do all sorts of fun stuff that allows us to make a game. You’re going to need to download this library at http://www.libsdl.org; be sure to download the Mingw32 tar file under “Development Libraries” and “Win32″ and the zip file under “Runtime Libraries” and “Win32.” If you are using Visual Studio download the appropriate version instead of the Mingw32 file. Once downloaded, we recommend you put the .dll found in the zip in your system32 folder. This way whenever we open an SDL application it can find the dll file it needs.
Open the tar file now (the one that was listed under “Development Libraries”) and decompress the contents to a folder (such as C:\SDL). Now, open up CodeBlocks so we can change some settings. Click “Settings” on the menu bar, and then click “Search Directories” tab. You’ll need to add C:\SDL\include to the “Compiler” tab, and C:\SDL\lib to the “Linker” tab (change C:\SDL to wherever you decompressed the files to). Once done, click Okay.
Start a new “blank” project, calling it whatever you want. Save it some place. Click on “Project” on the menu bar, and then click on “Properties.” A dialog will open; click on the “Project’s build options…” button on the bottom right. Click on the “Linker Settings” tab and add the following to the list under “Link libraries”:
mingw32
SDLmain
SDL
The order is important, so use the arrows to rearrange the list until it matches what is shown above. If you are having a little trouble figuring out what we are doing, we’re simply “linking” code together, or, in other words, we’re taking the SDL code and combining it with our own. We do this by using the include files to compile, and the lib files to link. And once done, our code is put together to make one application.
Click Ok twice, and you should be all set to go!
Let’s create two new files called CApp.h, and CApp.cpp; these will serve as the core for our program. First, open CApp.h and add the following code, in here is where our tutorial will really begin:
#define _CAPP_H_
#include <SDL.h>
class CApp {
public:
CApp();
int OnExecute();
};
#endif
Now, open up CApp.cpp and add the following code:
CApp::CApp() {
}
int CApp::OnExecute() {
return 0;
}
int main(int argc, char* argv[]) {
CApp theApp;
return theApp.OnExecute();
}
The CApp class is setting the stage for our entire program. Let me step aside to take special note of how games are typically setup. Most games consist of 5 functions that handle how the game processes. These processes are typically:
Initialize
This function handles all the loading of data, whether it be textures, maps, NPCs, or whatever.
Event
This function handles all input events from the mouse, keyboard, joysticks, or other devices.
Loop
This function handles all the data updates, such as a NPCs moving across the screen, decreasing your health bar, or whatever
Render
This function handles all the rendering of anything that shows up on the screen. It does NOT handle data manipulation, as this is what the Loop function is supposed to handle.
Cleanup
This function simply cleans up any resources loaded, and insures a peaceful quitting of the game.
It’s important to understand that games are one gigantic loop. Within this loop we find events, update data, and render pictures. Thus, the basic structure could be thought of as:
while(true) {
Events();
Loop();
Render();
}
Cleanup();
Each iteration of the loop we do something with data, and render accordingly. Events are extra, as a means for the user to manipulate data as well. In that sense, Events aren’t required to make a game, but are needed when you want the user to be able to manipulate data (such as move a NPC to the left).
Let’s clarify this idea with an example. Say we have our Knight, the hero of the game. All we want to do is simply have him move around. If I press left, he goes left. We need to figure out how to do this within a loop. Firstly, we know we want to check for events (keyboard events). Since Events are a means to manipulate data, we also know we’ll need some sort of variables to modify. Then we can use these variables to render our Knight appropriatly on the screen. We could have:
if(Key == RIGHT) X++;
if(Key == UP) Y–;
if(Key == DOWN) Y++;//… somewhere else in our code …
RenderImage(KnightImage, X, Y);
This works because each loop it checks if the key is LEFT, RIGHT, etc., and if so, we decrease or increase a variable. So, if our game is running at 30 frames per second and we press LEFT, then our guy would move to the left 30 pixels per second. If you don’t understand the game loop, you soon will. Games need them to function correctly.
Going back to our conceptual code (the 5 functions), we can add these additional pages to our project:
CApp_OnInit.cpp
CApp_OnEvent.cpp
CApp_OnLoop.cpp
CApp_OnRender.cpp
CApp_OnCleanup.cpp
Go back to CApp.h, and add the following functions and variables:
#define _CAPP_H_
#include <SDL.h>
class CApp {
private:
bool Running;
public:
CApp();
int OnExecute();
public:
bool OnInit();
void OnEvent(SDL_Event* Event);
void OnLoop();
void OnRender();
void OnCleanup();
};
#endif
Go through each of the 5 files we just created and create the function themselves:
bool CApp::OnInit() {
return true;
}
void CApp::OnEvent(SDL_Event* Event) {
}
void CApp::OnLoop() {
}
void CApp::OnRender() {
}
void CApp::OnCleanup() {
}
Now lets go back to our CApp.cpp code to link all of these functions together:
CApp::CApp() {
Running = true;
}
int CApp::OnExecute() {
if(OnInit() == false) {
return -1;
}
SDL_Event Event;
while(Running) {
while(SDL_PollEvent(&Event)) {
OnEvent(&Event);
}
OnLoop();
OnRender();
}
OnCleanup();
return 0;
}
int main(int argc, char* argv[]) {
CApp theApp;
return theApp.OnExecute();
}
You’ll notice some new variables, but let’s look at what is happening first. First, we try to Initialize our game, if it fails we return -1 (an error code), thus closing our program. If everything is good, we continue on to the game loop. Within the game loop we use SDL_PollEvent to check for events, and pass them one at a time to OnEvent. Once done with Events, we go to OnLoop for move data around and what not, and then render our game. We repeat this indefinitly. If the user exits the game, we proceed to OnCleanup cleaning up any resources. Simple enough.
Now, lets look at SDL_Event and SDL_PollEvent. The first is a structure that holds information about events. The second is a function that will grab any events waiting in the queue. This queue can have any number of events, which is the reason why we have to loop through them. So, for example, lets say the user presses A and moves the mouse during the OnRender() function. SDL will detect this and put two events in the queue, one for a key press and one for a mouse move. We can grab this event from the queue by using the SDL_PollEvent, and then passing it to OnEvent to handle it accordingly. Once there are no more events in the queue, SDL_PollEvent will return false, thus exiting out of the Event queue loop.
The other variable added, Running, is our own. This is our exit out of the game loop. When this is set to false, it will end the program, and in turn exit the program. So, for example, if the user presses the Escape key we can set this variable to false, quitting the game.
You should be able to compile everything so far just fine, but you may notice you can’t exit out. You’ll probably have to use the task manager to end the program.
Now that everything is setup, let’s start by creating the window our game will be drawn in. Jump over to CApp.h and add a SDL surface variable to the code:
#define _CAPP_H_
#include <SDL.h>
class CApp {
private:
bool Running;
SDL_Surface* Surf_Display;
public:
CApp();
int OnExecute();
public:
bool OnInit();
void OnEvent(SDL_Event* Event);
void OnLoop();
void OnRender();
void OnCleanup();
};
#endif
I suppose now would be a good time to explain exactly what a SDL Surface is. An SDL Surface is anything that can be drawn, or drawn to. Say we have a blank piece of paper, a pencil, and some stickers; this paper could be called our display “surface.” We can draw to it, put stickers on it, or whatever. The stickers we have are also surfaces; we can draw on them and put other stickers on them as well. So, Surf_Display is simply our “piece of blank paper” that we will draw all our stuff on.
Now, lets jump on over to CApp_OnInit to actually create this surface:
bool CApp::OnInit() {
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
return false;
}
if((Surf_Display = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL) {
return false;
}
return true;
}
The first thing we need to do is start up SDL itself, so we can access its functions. We are telling SDL to Initialize everything it has; there are other parameters you can pass, but understanding them at this point is not important. The next function we use is SDL_SetVideoMode. This bad boy is what creates our window, and our surface. It takes 4 parameters: The width of the window, the height of the window, the bit resolution of the window (recommended to be 16 or 32), and then display flags. There are quite a few display flags, but the ones shown above are fine for now. The first flag tells SDL to use hardware memory for storing our images and such, and the second flag tells SDL to use double buffering (which is important if you don’t want flickering on your screen). Another flag that may interest you now is SDL_FULLSCREEN, which makes the window go fullscreen.
Now that our display is setup, lets cleanup a little bit to make sure everything works smoothly. Open up CApp_OnCleanup.cpp and add the following:
void CApp::OnCleanup() {
SDL_FreeSurface(Surf_Display);
SDL_Quit();
}
The first thing we do is free the display surface, basically freeing any memory. Once that is done, we quit out of SDL. You should take note that in this function is where you would free other surfaces as well (probably before the Surf_Display). This keeps all your code centralized to the function its performing.
To keep things tidy, lets also set the Surf_Display pointer to NULL on the class destructor. Open up CApp.cpp and add the following:
Surf_Display = NULL;
Running = true;
}
Try compiling your code, and watching it work. You should have a nice blank window popup. You’ll notice you can’t close it though, so you’ll need to use the task manager to do so.
Now that we have a window all setup, we’re going to need a way to close it. Open up the CApp_OnEvent.cpp file, add the following:
void CApp::OnEvent(SDL_Event* Event) {
if(Event->type == SDL_QUIT) {
Running = false;
}
}
The SDL event structure is broken down into types. These types can range from keypresses, to mouse movements; what we simply are doing here is checking the event type. The type above we are looking for is the request to close the window (i.e., when the user clicks the X button). If that event happens to take place, we set Running to false, thus ending our program. Simple enough. We’ll look more into events in a later lesson.
Now, you should everything setup, and a good structure to work with later. It may be a good idea to take this project and turn it into an “SDL template” within CodeBlocks. I won’t go over how to do that, but feel free to Google it.
Once you have a good idea what’s going on with the code we covered in this lesson, jump over to the next game tutorial lesson to learn more about SDL surfaces.
SDL Tutorial Basics - Tutorial Files:
Win32: Zip, Rar
Linux: Tar (Thanks Gaten)














February 18th, 2008 at 2:44 pm
Ah, spotted a little mistake that prevents compiling:
while(Running) {
while(SDL_PollEvent(&Event)) {
OnEvent(&Event);
}
The amp;-thing is probably by Wordpress I assume? The source files that come with the .rar-package are fine though. Great tutorials I might add, I’d actually say that they’re definitely the easiest to fully understand out of all the SDL-tutorials I’ve seen.
February 18th, 2008 at 2:48 pm
Ah, sorry about that. Posting it as a comment seems to have erased the whole amp-thing from the source I pasted. Anyway, there’s a “amp;” after SDL_PollEvent which prevents compiling.
February 18th, 2008 at 2:50 pm
Thanks for the heads up. I got rid of those on the other tutorials, I must have missed this one. I appreciate your feedback, it’s nice to know that people are getting good use out of these tutorials. The more feedback = the more tutorials to expect in the future. Thanks again.
P.S.
I always check my RAR packages that they compile, so you can always rely upon them.
February 23rd, 2008 at 9:41 pm
Im a little curious as to why you break out seperate functions into their own source files. Would it not be better to put all the functions of CApp into the CApp.cpp file?
February 25th, 2008 at 7:32 am
That all depends, if you feel its more appropriate to have one file than feel free to do so. But, there are several reasons why I separate the functions into separate files. Firstly, depending on the size of your program it may become to impractical to have your main application in one file. Remember, CApp is the core and foundation of your program. Secondly, a key concept to learn here is “reusable code.” By having separate files it makes it easier to manage our code, and it helps create a discipline of formating our code in a more “reusable” fashion.
February 25th, 2008 at 8:54 pm
Wouldn’t it be better to keep classes in separate files but keep their member functions together? I’ve only seen it done that way.
February 25th, 2008 at 9:40 pm
Not necessarely, and it’s not a rule to do so. In most cases, yes, keep the class members together in one file. But like I stated above, we’re trying to make reusable code that is easy to manage. Have you ever seen the main App layer of a game before? Sometimes it’s horrendous in how long it is, and how hard it can be to find what you want. Keep in mind I only do this sort of thing in certain cases, you’ll notice OnExecute is tucked nicely in within the main CApp.cpp file, and doesn’t have its own file. The reason I did it for the other functions is because they will always be expanding and changing according to the game, which is not the case with other functions and classes used. It’s okay to think outside the box a little.
February 28th, 2008 at 12:02 am
Linux source: http://gaten.homelinux.net/sdltuts/sdl_basics.tar.gz
March 30th, 2008 at 4:12 pm
Hi, just a little problem with the setup. it works but it’s just that that when i’m trying to comple it i get this error message from wwindows claiming i’ve got no disk in my d: drive. if i just ignore this an endless amount of times the build finally completes and the app runs flawless. just wounder if there’s any way to get around it? it claims i lack “mingw.g++.exe” & “collect2″ in my drive. suggestions?
March 31st, 2008 at 7:11 am
It sounds like your paths are not setup correctly, so it’s trying to find those programs and it cannot. Are you using CodeBlocks? And if so, did you install with the Mingw package? If so, check your paths under settings, as actual coding and these tutorials wouldn’t be the problem of not being able to find files when compiling.
April 1st, 2008 at 5:02 pm
Hello!
I had made an SDL game 1 year ago and had forgotten lots of stuff about SDL so I am now doing a quick read of your tutorials to remember the basic stuff so I can resume the programming process.
Thing is I did it in codeblocks which I had already set to be as you describe in the tutorial but 1 year ago.The problem is that when I run the program a small console window pops up behind. I did not have this problem 1 year ago. Any quick idea as to what I did wrong this time?
April 1st, 2008 at 6:26 pm
Hi Lefteris!
I believe your problem is under your project settings (right click the project on your project tree and click settings). There is a dropdown to define what type of build on the 2nd tab. There are 4 options (doing this from memory), Console, GUI, Static Library, and Dynamic Library. You probably have it on Console; change it to GUI and your extra popup should go away.
April 2nd, 2008 at 7:41 am
Ah yeah that was it! Thanks for helping me mate
April 2nd, 2008 at 7:45 am
No problem!
April 5th, 2008 at 1:31 pm
I like the basic framework. In my version though, I made all of the member functions private except for onExecute. That made more sense to me since those should never be called outside of onExecute. “protected” would work too, but it’s unlikely you would ever derive from your app class - almost every app is going to need custom code for every function. Can’t wait to see new tutorials!
April 7th, 2008 at 6:56 am
Thanks Chris. That is something I tried to emphasize, take the framework I have here and make it your own. If you want stricter OOP go for it!
April 8th, 2008 at 1:41 pm
Great tutorial! Thanks!
April 12th, 2008 at 8:55 pm
This tutorial is one of the clearest tutorials on SDL init I’ve read. Thank you for this contribution.
May 1st, 2008 at 7:20 am
I’m puzzled why you use SDL_FreeSurface() to free the Surf_Display,it seems SDL_Quit will do that.Free a pointer twice may occur something unexcepted.
May 16th, 2008 at 10:51 am
No, nothing will happen if you do that. But you are quite right in stating that SDL_Quit will free it for you. I just like to know that the job got done.
May 31st, 2008 at 2:23 am
Linking executable: bin\SDL Tutorial 1.exe
CApp.h.gch\Release_CApp_h_gch: file not recognized: File format not recognized
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
0 errors, 0 warnings
May 31st, 2008 at 4:02 am
Linking executable: bin\SDL Tutorial 1.exe
CApp.h.gch\Release_CApp_h_gch: file not recognized: File format not recognized
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
0 errors, 0 warnings
And yep I’ve tried unchecking linker & compile settings in my header properties.
June 3rd, 2008 at 12:05 pm
I mentioned this to william in an email, but for those of you who might have a similar problem:
Okay, first, what people have told you are right. When you see that GCC is “precompiling [the] header” then that means you have the checkbox checked under the settings. So, make sure that is unchecked (all headers should be unchecked).
Next, you say you have an error about not finding lSDLmain. I assume you are Windows, so here’s what you do. Under your linker settings you need to have:
mingw32
SDLmain
SDL
First, make sure that you have your settings right (the order of the items above is important), and if it still doesn’t work, then that probably means you don’t have your directories setup right. If not, then check the first few paragraphs on the first tutorial:
http://www.sdltutorials.com/sdl-tutorial-basics/
I hope that helps.
June 14th, 2008 at 4:06 pm
Hello,
I tried doing the exactly same thing, exact same code, but I get several errors. I have set up the SDL for Visual Studio, but I dont have that mingw32 … is that my problem??
I tried getting the mingw 5.14 package from the sourceforge website but I cant find the mingw32 library
where can i find that library??
Or should I download the SDL-dev-mingw32 and set up that instead of the one I currently have (VC8 Visual Studio 2005 c++)
P.S.: My Compiler is the MS Visual Studio 2008!
June 17th, 2008 at 1:50 pm
Hi,
It seems that I’m having a similar problem, I can’t locate the mingw32 lib. I’m pretty sure I download the correct zip and tar files. I tried to look for it but still couldn’t find it.
June 20th, 2008 at 6:45 am
Kurama Kun and Lu Sien,
You guys brought up a good point that I should address on this site: That the setup within these tutorials are geared for cross-platform. Now, that doesn’t mean they won’t work in VC++. You see, the mingw is used when compiling with GCC on Windows. Hence the name, Minimalist GNU for Windows. Now, for VC++ compilations, you don’t need mingw, but what you do need is the VC++ files of SDL. Under development libraries these are labeled VC6 and VC8 (according to your version). Now, under your linker settings, you would add:
SDLmain.lib
SDL.lib
Notice you have .lib files, not .a files. Also, you don’t use mingw. Hopefully that helps!
Note: Since VC++ really is an IDE, you could have it setup to compile with GCC, and have it use mingw.
June 23rd, 2008 at 4:34 pm
[…] przygotowania rozpocząłem od użycia google;) I jakie było moje zdziwienie, kiedy trafiłem na SDL Tutorial Basics @ Dev Hub. To o czym pomyślałem - przynajmniej odnośnie SDL, pomijając narazie OpenGL - właśnie tam […]
June 26th, 2008 at 10:27 pm
Hey Tim Jones,
It still doesn’t work to me… my SDL library is set up correctly, I guess, because I did a test application (it draws a screen) and it works perfectly, but your program still give me errors.
The libraries are included in my “linker” and I am using the SDL 1.2.13 VC8 (Visual C++ 2005 service pack 1).
Do you know any other thing I should do to correct this, or should I “skip” this tutorial and focus more in the others that doesn’t use this “mingw32″.
Thanks for everything!
July 9th, 2008 at 2:01 pm
hello, tx for the tutorial, so far its been really rasy to follow and you keep the code organized wich is a big plus for me.
i was wondering, at the end you say “To keep things tidy, lets also set the Surf_Display pointer to NULL on the class destructor.” but then you put the Surf_Display = NULL in the constructor. i havent programmed in C++ in a log while so im a bit rusty, is there something im not getting there?
July 9th, 2008 at 2:07 pm
Nice keen eye Gismoser! I have a misspelling there, it should be: “… NULL on the class constructor.” Thanks!
Since I am not necessarily teaching on C++ in these tutorials, the rule is that you always set your pointers with some sort of value (hence, we set it to NULL). Accessing a pointer that doesn’t have a value leads to undefined behavior and seg faults!
July 18th, 2008 at 4:43 pm
Everything compiled fine but there is no .exe :\
Any ideas? I’m on Dev c++
July 28th, 2008 at 11:18 am
This is definately the best SDL website I’ve visited so far
You really explain what you are doing, and you’re doing it well
Keep up the good work
August 7th, 2008 at 11:13 pm
this is the warning i have when i compile it:
[Warning] cannot find entry symbol _WinMainCRTStartup; defaulting to 00401000
and when i open the compiled project, it says something about the memory could not be "written"
any help please?
August 8th, 2008 at 8:27 am
This is a good tutorial and very understandable,except I tried running this project and kept getting the message: "The procedure entry point SDL_strlcat could not be located in the dynamic link library SDL.dll."
Help.
August 8th, 2008 at 8:30 am
Oh, and I am using Code Blocks
August 14th, 2008 at 2:45 pm
Again, can you help me to solve this problem? i’m using dev cpp and i get this error
[Warning] cannot find entry symbol _mainCRTStartup; defaulting to 00401000
thanks
August 15th, 2008 at 5:40 pm
Sorry guys, I must have overlooked these comments.
Mr. Smith, Make sure you are compiling an executable, there are certain options in Dev-C++ to choose DLL, Static Lib, and others. Also, make sure the output file has the .exe on the end of the filename.
Havard, Thanks for the compliments!
armandito, Can you please list how you are linking the libraries, and the settings for your project? I believe the warning is related to a "Windows" type of build (think Visual Studio). Are you using mingw? If not, you need to be using mingw32. On Windows system there is a function that replaces "main()" called WinMain. We need mingw to handle this instead. Let me know if that helps.
Patty, Thanks! First, make sure your SDL libraries and DLLs are the same version (or at least have the DLLs be a higher version than your DLLs). If they are the same, can you tell me your CodeBlock settings? Also, let me know if that helps.
August 16th, 2008 at 11:36 am
Thanks for your answer, I am using dev-cpp and about the linking.. i do the order u have put, but in my dev-cpp isn’t any mingw32.lib or .a, and i looked for it a lot and i only found a lot of libs, but not that one. I tried with a file like libgcc.lib (dont remember the exact name) and i was still getting the same error.
I tried with Codeblocks and got like 50 weird errors.
If you can give me a link to get mingw32.lib, i’ll be very grateful because i’m loving SDL,
thanks.
August 18th, 2008 at 9:31 am
I got it! The problem was in the way i linked the libraries.. it had to be :
..\..\..\..\..\..\CodeBlocks\MinGW\lib\libmingw32.a
libSDLmain
libSDL
now it works, thanks for the help.
August 18th, 2008 at 12:24 pm
armandito,
This means that you downloaded Dev-C++ that doesn’t come with mingw, or Dev-C++ isn’t pointing to where mingw is installed.
If you go here, http://www.bloodshed.net/dev/devcpp.html, you’ll notice a download w/ Mingw and one without. Hopefully that clarifies the issue.
August 19th, 2008 at 6:35 pm
Thanks, but i had to put that with codeblocks, didn’t tried again with devcpp.
also, note that in the SDL w/mingw the SDL libraries aren’t called SDL and SDLmain, they are libSDL and libSDLmain, don’t know if that changes something.
August 20th, 2008 at 7:35 am
armandito,
You’re right, the actual files are called libSDL.a and libSDLmain.a (including any other lib file really). But the way it works with CodeBlocks is that it assumes lib already. So putting SDL and SDLmain works. For you makefile people, -lSDL -lSDLmain also assumes you mean lib in front of the file.