2009
01.06

Welcome back!

Now, assuming you have follow the first blog post, or already have your system setup ready to compile against SDL and OpenGL, let’s create our First Window!

I am going to keep this code as structured as possible, using classes from the outset, i want this code to be as clean to navigate as possible, so it’s also therefore more expandable and re-usable. At first it seems a pain, but in the long run, it proves it’s worth.

First off, this is a template i use for all my projects now, it’s simple to follow. Download this zip file, and extract it somewhere, this will be where we build our version of Pong. I have already created the Makefile’s and the main.cpp we will use to start with. This is the same zip as the last blog, so it should compile straight out of the box!

Now we have this extracted somewhere, let’s start adding to it! As i said before, i’m trying to keep this as structured as possible, so first off, i’m going to create a class called ‘Pong’, original huh? I will also store these files inside the same as directory as main.cpp (the src folder).

Here are the definitions of the files.

Pong.h

#ifndef PONG_H_
#define PONG_H_
 
#include <iostream>
#include <gl/glew.h>
#include <sdl/SDL.h>
#include <sdl/SDL_ttf.h>
 
class Pong
{
private:
        //Width and the Height of the Window
	int _width, _height;
 
        //This is it, THE screen, this is effectively what we will be rendering everything to.
	SDL_Surface *_screen;
 
	bool InitialiseGraphics();
	void InitialiseGeometry();
 
public:
 
	Pong(int width, int height);
 
	bool Initialise();
 
	void Run();
 
	void Uninitialise();
 
};
 
#endif /* PONG_H_ */

Pong.cpp (Part of it…)

#include <cstring>
#include "Pong.h"
 
using namespace std;
 
Pong::Pong(int width, int height)
{
	_width = width;
	_height = height;
}
 
bool Pong::Initialise()
{
	if (!InitialiseGraphics())
		return false;
 
	InitialiseGeometry();
 
	return true;
}
 
void Pong::InitialiseGeometry()
{
 
}

Now, if you save both of those files. So you directory should look like this…

pong-step2-directory

As it is at the moment, that won’t compile. We are still missing a few functions, i missed them out on purpose, so you could understand what they do.

Let’s start with the Pong::InitialiseGraphics method. You will need to place this code into the Pong.cpp file we created earlier.

bool Pong::InitialiseGraphics()
{
	//We only want video, no need for audio/network or even the CD-Rom...
	if (SDL_Init(SDL_INIT_VIDEO) != 0)
		return false;
 
	//We want to double buffer the screen
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
 
	//Create the actual screen for SDL/OpenGL to render to
	_screen = SDL_SetVideoMode(_width, _height, 32, SDL_OPENGL);
 
	std::cout << "SDL Initialised" << std::endl;
 
	glEnable(GL_TEXTURE_2D);
 
	//Set the ViewPort (what we can see) to the same resolution as the actual screen, in this case, 640x480
	glViewport(0, 0, _width, _height);
 
	//Clear the screen again
	glClear(GL_COLOR_BUFFER_BIT);
 
	//Set the Matrix into Projection mode
	glMatrixMode(GL_PROJECTION);
 
	//Load the Projection Matrix
	glLoadIdentity();
 
	//Create an Orthogonal matrix, meaning 2D basically, so we only really work in X and Y
	glOrtho(0, (float) _width, (float) _height, 0, -1.0f, 1.0f);
 
	//Set the Matrix back into Model View mode
	glMatrixMode(GL_MODELVIEW);
 
	//Load the ModelView Matrix
	glLoadIdentity();
 
	//Set the Clear Colour, this is the colour the screen will be cleaered to every time we call glClear(...);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
	return true;
}

Now, with a quick read through that method, we can see what it’s doing just by reading the comments. This is what will create our SDL window, so that we can render objects to the screen. One current flaw with this method, is that the Bit Depth is locked to 32bit, this could be changed to work the same way as width/height from the constructor. But, you shouldn’t need to worry about that just yet.

Next up, we have the Run method. This is where the good stuff happens, this is the loop for the entire game. Everything that has anything to do with the logic of our game happens in here, if the ball moves, it’s because of this method. This calls the render method on all the objects we want to display, and handles input. So, let’s see it.

void Pong::Run()
{
        //This is a bit we can just use to determine if we want to continue rendering or not
	bool isRunning = true;
        //This is where SDL will provide us with an event, so we can check for KB input, etc
	SDL_Event theEvent;
 
        //Loop forever, until isRunning is false.
	while (isRunning)
	{
                //Poll through as many events as there are available from SDL
		while (SDL_PollEvent(&amp;theEvent))
		{
                        //Check the key that was pressed down...
			switch (theEvent.key.keysym.sym)
			{
			case SDLK_ESCAPE:
                                //If they pushed the ESC key, lets stop the main loop from looping, they want to quit...
				isRunning = false;
				break;
			default:
				break;
			}
		}
 
                //Clear the screen to the colour we defined in the InitialiseGraphics method earlier.
		glClear(GL_COLOR_BUFFER_BIT);
 
	        //This is where everything will get rendered....eventually
 
                //Swap the buffers around, so we can now show one and draw to another, hence Double Buffering
		SDL_GL_SwapBuffers();
	}
}

Thats it for our Run method at the moment, exciting huh? All we do is check for the enter key, and clear the screen. It’ll get a bit more involved soon, i promise ;)

Now, our last method, and one of the important ones. Cleanup! We should let the operating system have it’s resources back, it did give them to use in the first place.

So here it is, as always, well commented for your reading pleasure.

void Pong::Uninitialise()
{
        //Free the Screen surface, basically unload it from memory, we have no need for it now
	SDL_FreeSurface(_screen);
 
        //Tell SDL we are leaving, it should pack up it's bits and come with us.
	SDL_Quit();
}

Now, you have a complete Pong class as a nice little building block for our game, but you have no means of using it at the moment, as main.cpp isn’t at all aware of it, come to think of it, neither is the Makefile.

So, lets update main.cpp, so we can use the Pong class!

Update your Main.cpp to look like this…

#include "Pong.h"
 
int main(int argc, char *argv[])
{
        //Create a new instance of our Pong class
        Pong myPong(640, 480);
 
        //Try an Initialise the SDL and OpenGL APIs
        if (myPong.Initialise())
        {
                //Remember this method? This will block the thread until the game is over.
                myPong.Run();
 
                //Free all those resources we used up.
                myPong.Uninitialise();
        }
}

Now, if you try to compile it, you should get this error.

g++ -O2 -g -Wall -fmessage-length=0   -c -o src/main.o src/main.cpp
g++ -o Pong	 src/main.o -lSDL -lGL -lSDL_ttf
src/main.o: In function `main':
/your_path_here/Pong/src/main.cpp:12: undefined reference to `Pong::Pong(int, int)'

What this means is, it doesn’t know where to find the actual code for that method. Pong(int, int) which is the constructor. Now, we have to make a quick edit to our Makefiles, to point to this object.

Open up the Makefile, in the Pong folder with your favourite text editor, and replace this line

OBJS =          src/main.o

with

OBJS =          src/main.o src/Pong.o

Now open up the Makefile in the ’src’ folder with your favorite text editor, and replace this line

OBJS =          main.o

with

OBJS =          main.o Pong.o

Now, back to our command line, try running ‘make’ now, it should compile fine, with the following output.

g++ -O2 -g -Wall -fmessage-length=0   -c -o src/main.o src/main.cpp
g++ -O2 -g -Wall -fmessage-length=0   -c -o src/Pong.o src/Pong.cpp
g++ -o Pong	 src/main.o src/Pong.o -lSDL -lGL -lSDL_ttf

Now, run the application by typing in

./Pong

And you will have a nice 640, 480 window, with a black background.

Congratulations, you have now created a Window using SDL that supports OpenGL Extensions.

Here is the final product, won’t learn anything just by taking this though!! Most of the comments are missing.

Pong.zip

2 comments so far

Add Your Comment
  1. hey man, i liked your tutorial…
    i was into c# game dev, but thought about trying to learn c++ now.. so i followed your tutorials and setup a vm with ubuntu as my dev station. But on virtualbox i couldn’t find a way to increase my view, even if i maximize the window it stays that res 800×600 i think? on the os thats the only option availabe(800×600)
    Do you know how could i get my view bigger?
    thanks and keep up the good work.

  2. Hey Thiago,

    Thanks for the comments!

    I currently use my ubuntu virtualbox in 1024×768 (host is 1600×1200).

    What version of VirtualBox are you using? 2.1 was released just recently, worth upgrading to.
    Have you installed the Guest Additions? Devices -> Install Guest Additions.

    Once you have done both of those, i see no reason why it shouldn’t allow you to set a bigger resolution, i have a Windows 2008 VM too that i use full screen, so it should be OK.

    Also, do you have your Graphics Card drivers install on your Host? (Are you windows/linux on the host?)

    Cheers!
    Dean

    p.s. Just posted another article in the pong series ;)

Spiked Software Coding Articles is Digg proof thanks to caching by WP Super Cache