Simple Race Game

In the last quarter of this year in college, I am studying Interactive Systems. In this course we started working with OpenFrameworks, which is nothing more than a framework that makes it easy to use OpenGL and development of 2D and 3D Applications. The first project that we are developing is a 2D multiplayer racing game.

Framework

First we have to download from OpenFrameworks website the latest release for the IDE we use, in this case we use Code Blocks. Once downloaded and unzipped wherever you want, go to the folder /apps/myApps/emptyExample, there you will find what you need to start immediately. If we open the file emptyExample.workspace with Code Blocks, we can see 3 files created in the folder /src.

In the main.cpp file, basically is created a window with the dimensions in which the game will run. Once created the application runs.

In the testApp.h, we can see the basis for every application, and some key, mouse and windows events.
The setup() method, sets all the elements of the application, this method will only be called at the beginning of the application.
The update() method, updates all the elements of the application, this method will be called in every iteration of the application.
The draw() method, draw all the elements of the application for the next frame that is going to show at screen, this method will be called after every update().

At setup(), enable Alpha Blendhighlighting for rendhighlightering with transparency, here what oF does is call glEnable(GL_BLendhighlight); to rise OpenGL Blengin flag; and set the frame rate at 60FPS. Later we’ll see what objects we set up, we must first create them.
For the moment, the methods update() and draw() are empty. We could paint the window background in white or black (or whatever we wanted) using ofBackground(r,g,b);

Car

Once we have an area to play, we need a toy. As we saw at class testApp, we create a new class with the 3 basic methods, setup(), update() and draw(), and some necessary attributes.

We give values to the setup() to configure the car. Setting the initial position (x,y) in the window and the texture size of the car (width,height), and the initial speed as 0 (we don’t want the car run like crazy) and rotation to where it should be aimed initially in degrees (45º = diagonal up-right)..
These data will be stored in the attributes of the class, in addition to the car’s speed, the rotation and its texture.
To modify all attributes also implement their getters and setters. With the only difference set_texture(), which will load the texture in memory.

rotation.png

Now that we have set the car, we have to make it move. To calculate the position in the next frame, which must be the car when in motion, we will consider the current position, rotation, and the speed at which the car moves.
First we calculate the direction in which we should move, using the cosine and sine of the car’s rotation, it will provide us a unit vector (length = 1) which will be multiplied by the car’s speed to get the distance advanced in the cycle. And we will add to the current position.

The dt component, is the delta-time that is to correct the frame rate fluctuation.

Once we know what position should be the car when moving, we have to draw it on the screen. To do this, we will move the object in the 2D world, translating to the position that we calculated before, and also rotating to aim according to need.

Scenario

What would be a racing game without a track where to compete? As each class in the class Scenario, we define the 3 basic methods, in addition to its attributes and functions needed for the class.

The texture array stores all different tiles to draw the track, the scenario array gives shape to the track with the indices from the texture array, also we define a vector to draw some trees. The width and height atributes are given by the number of tiles that fill the screen, it will have width*height tiles. And it is necessary set the width and height of the tiles.
At the constructor, we reserve the space in memory for the instantiation of the class.

We allocate memory for 7 different tiles to draw the track, which will have 8*6 tiles. To draw the tiles so that they fill 100% of the screen, we divide the width of the screen by the number of tiles widthwise, and the same for the height. And finally allocate memory for 8*6 indices that will define the shape of the track.
With the allocated memory, we load the textures and set the scenario in the setup() method.

First we load the 7 different tiles for later drawing the scenario given by the scenario array. The sequence to load the images are used for indices that we use in the scenario array. Will place the trees in different positions of the screen. Initialize the scenario with 8*6 indices, according to the tiles we want to use to shape the track. (I’m copying from temp to scenario_array because an int* can’t be initialized as a list)

SRC-Tiles.jpg

As the scenario represents the track where cars run, and it is an inanimate object, that will not change over time, the update() method will be empty.

In the draw() method has to loop the scenario array to get wich texture should be rendhighlighter, then draw it in the expected position. To draw the tree we iterate over the tree vector using an iterator to go through, iterators tendhighlight to be the most efficient way to search through a data container. For each position we do a push and popMatrix() so the call to ofTranslate() will not affect the posterior rendhighlighter in the game loop. By calling the ofTranslate(), we can pass as x and y arguments to ofImagen().draw() the values 0, 0.

Gameplay & Fixes

Now that we have ready the Scenario and Car classes, we should add them to the framework and initialize in the setup() method of the testApp class. We only need one instance of Scenario, but we could need more than one car if we want to play with friendhighlights, so they will be instantiated in an array of Car.
The initialization is quite simple, just call the setup() method of the scenario and the cars, passing to each car its initial position and size of the texture.

Red.png
Right now, if we draw the scenario and cars in the method draw () and run the project, we have running our game, but we can not move the car. In order for the car move using the keyboard, we need to capture the event that happens when any key is pressed and when is released. The framework has already implemented these methods, but we have to tell them what to do when a button is pushed and released.

Quite simple, we store a boolean array wich key was pressed or not, using as index the int value of the key. Doing this way, we can press more than one key at the time.
Now that we have the keys pressed or not, the game has to tell the car what to do on every frame for each key pressed.

Since for each frame we want the car to move, we will check in the update() if keys are pressed to move the car. Also if we want that when we do not press any key the car breaks, we have to check that the keys to accelerate and reverse are not pressed. The methods we use are pretty obviuos, accelerate, break and reverse increments or decrements the car speed atribute, and turn_right and turn_left increments or decrements the car rotation atribute.

Now that we can move our car across the scenario, problems arise. The most important thing to fix is the fact that we can get out of the screen. To fix that exists an OpenFramework method that returns true if a value is between a range, we use this method to check if our car will be outside the screen when we update its position, if it is true it won’t move to the new position. This check has to be done every time that we want to move our car, so we add it at car’s update() method.

From this point that we already have implemented the basic elements of game, simply must be added features like controlling the car goes through all the tiles forming the track, or when the car moves by the grass tiles, the speed is reduced, and even control the collisions between cars and trees.

SRC-Track.jpg

Here you have the source code. SRG – src
Here you have the textures used and some extras. SRG – Tiles