2009
08.22

Usually, i write software in ASP.NET/C#, because this is what my job requires, however i always lilke to play with other technology to keep myself up-to-date. I’ve been writing alot of Ajax enabled websites in ASP.NET recently, and have to say Microsoft have made it very easy to integrate with an ASP.NET Aplpication. It got me wondering how difficult would it be with PHP? Surely just as easy?

Well, there isn’t much in it. And it didn’t take me long at all to get a simple AJAX POST running on a PHP Page, which returned me some data that i would be able to re-use.

I will assume you have a PHP (5.2) enabled apache server that you have access to dump a couple of files that we are going to want to use. Fire up your favourite PHP Editor (I use Eclipse PDT).

Lets start by creating an index.php, which will initiate our call to the backend. It should look similar to this…

<html>
<head>
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
</head>
<body>
	<script type="text/javascript">
		function runPost()
		{
			$.post('service.php',
			   {
				   data: 2
  			   },
			   function(response, status)
			   {
				   alert(status);
				   for ( var i = 0; i < response.length; i ++)
	    				alert(response[i].Data);
			   },	
			   'json');
		}
	</script>
	This is our test page.<br />
	<button id="testButton" onclick="runPost();">Make Ajax Post</button>
</body>
</html>

As you can see, a pretty simple page, with an external link to the wonderful google which’ll host jQuery for us (saves us hosting it, users can download it faster). We also have a simple method which uses the jQuery post method. This is what we will be using to talk to our web service. Let’s have a quick look at the post method. It takes upto 4 parameters, all of which we are interested in.

First up, we have the URL we want to post to (this is our web service!), we then have the data we want to send to the server. There is some magic going on here, because we can just throw an Javascript Object at it, it will then serializa that into a JSON formatted string, which PHP will understand. Then we have a callback, this is the method that will be called when the request has finished, succesful or not. Last but not least, we have the data type, for this example we use JSON, because that’s the data we want to send/receive. That’s it, it’s a simple method that does everything we want to do! So let’s create our service page.

Create another page called service.php in the same folder as the index.php file, for simplicity.

<?php
 
	class data
	{
		public $Index;
		public $Data;
	};
 
	$myObj = json_decode(stripslashes($_POST['data']));
	$returnObj = array();
 
	for ($i = 0; $i < $myObj; $i ++)
	{
		$newData = new data();
		$newData->Index = $i;
		$newData->Data = 'This is a Test, ' . $i . '.';
		$returnObj[] = $newData;
	}
 
	echo json_encode($returnObj);
 
?>

As you can see, we take the POST’ed data argument, and transform it into the integer that we actually passed, then loop through the amount that it is equal to, creating an array that we want to serialize to json and send back to the client! Simples!

If you now run the index page in your favourite browser (Should be FireFox!) then click the button, you should get 3 message boxes pop up.

The first should say Success, then we should get ‘This is a test, 0.’ and ‘This is a test, 1.’. And that’s it, that is just how easy it is to post data to the server and deal with a response using jQuery & PHP. Try changing the data parameter we pass back in the runPost() JavaScript method in index.php to see how it varies.

A plugin i highly suggest for FireFox is FireBug, this will allow you to view all the POST’s and the Responses in a nice little window, so you can ensure that data you are sending/receiving is exactly as you want to see.

I hope this helped someone!

2009
08.21

I have a MySQL 5 Database, running inside Ubuntu 9.04. I have around 10 databases that are modified reasonably frequently, so obviously they need to be backed up incase something terrible happens.

There is a very nice command called ‘mysqldump’, which can do pretty much everything we are after for us! Brilliant, let’s see how it works! Fire up your favourite command line, i’ll assume we are using gnome-terminal for this post.

As you can see, it’s got a pretty simple syntax, just like the actual mysql command itself, where it accepts a host, user and password.

$ mysqldump -uUSER -pPASSWORD -hHOST

For this tutorial, i will also assume you have a local database, as i will be running this off of localhost.

Let’s run a backup of everything inside of our MySQL database locally! This will not alter any data in your mysql database, it is only a read, there is no writing.

$ mysqldump -uroot -piamroot -hlocalhost --all-databases

What?! What was that mess it just printed all over my screen? Is probably what your thinking. That ‘mess’ is an entire sql script that will restore your database back to it’s current state. Not very helpful if we can only see it on the command line right? We need it stored in a file some place. So let’s pipe out that data to a SQL file, that we could load up and read over if we really wanted to.

$ mysqldump -uroot -piamroot -hlocalhost --all-databases > all-databases.sql

This will now dump all of that output into a file called ‘all-databases’ which will be placed in the current folder you are in inside your shell.We can confirm this by typing..

$ ls -allh | grep all-databases.sql
#Should print out something simlar...
-rw-r--r--  1 dean dean 420K 2009-08-21 16:55 all-databases.sql

So we know we can back up our database now, but we don’t really want to back it up to the same file name every time, one backup is never enough. Someone will delete something and want a backup from 3 days ago to bring back one row of data, i know, it’s happened too many times to me. So let’s timestamp it, that way we can have months worth (i suggest a weeks worth, and then 1 a week for 3 months, but thats for another post).

$ mysqldump -uroot -piamroot -hlocalhost --all-databases > mysql-`date -I`-backup.sql

This will now dump our database to a file wth a naming convention of ‘mysql-YYYY-MM-DD-backup.sql’, so it should be easily found and very archivable.

Great, so we can backup a database, we can timestamp it… we’re done? No, not yet. We should probably compress the output, just to save some more space. Yet another pretty simple process.

$ mysqldump -uroot -piamroot -hlocalhost --all-databases | gzip -9 > mysql-`date -I`-backup.sql.gz

As you can see, we now pipe the output of mysqldump into this new fancy gzip command. Which will compress the output from mysqldump into a compressed file. gzip takes a parameter for how much compression we want, it ranges from 1 to 9, 9 being the best (slowest) and 1 being the worst (fastest). I use 9, because i want to save as much space as possible. I’m tight like that.

If we run another ls to see how big our backup is… it should be much smaller now.

$ ls -allh | grep mysql-*-backup.sql.gz

We should see…

-rw-r--r--  1 dean dean 112K 2009-08-21 17:18 mysql-2009-08-21-backup.sql.gz

As you can see, that compared to my previous file, is almost 4 times as small! We’ve gone from 420kb to 112kb! That’s quite a save.

Upto this point, we have a backup of every database in our MySQL server, it is compressed and time stamped… now we should schedule it every night. I run my backups from Midnight to 1am, so we’ll set it to run at 10 past midnight using cron. I only use cron, so if you use something else, please consult the manual in setting this up. I also want my cron jobs to run as root, in this example at least.

$ sudo crontab -e

There is our cron tab file, it could be empty, it could have some cron jobs already in it, the least you should see is…

# m h  dom mon dow   command

Let us add in our cron job, that will backup the entire mysql database at 10 past midnight, every night.

# m h  dom mon dow   command
10 00 * * * mysqldump -uroot -piamroot -hlocalhost --all-databases | gzip -9 > /mnt/backup/mysql-`date -I`-backup.sql.gz

Save this file and exit. That’s it, all done. At 10 past midnight, that command will execute.

There are just a few thigs to note…

1) I have changed the path of the exported file, i mount a drive under the name backup where i store all my backups. You should change this to suite your needs.
2) You should create a mysql user with read-only rights to your database to prevent anything malicious happening to your database by accident.
3) I Also suggest creating a new user on the machine which has only read access, but write access to your backup folder which has the job scheduled on their crontab.

That’s all from me… i hope this helps someone how it helped me!

2009
04.04

If, like me, you have alot of MKV’s lying around on your machine, my PS3 will play them using the PS3 Media Server (which is awesome by the way, nothing comes close as far as i’m concerned) as it will use mplayer or tsMuxeR to transcode them on the fly to the PS3.

But, why bother? Why put my PC through the stress of re-encoding video on the fly, just so my PS3 can play them. MKV is just a container, it contains a perfectly playable Mpeg stream and a DD 5.1 sound track, that the ps3 can play flawlessly, it just doesn’t understand the MKV format (yet, come on Sony…).

So, let’s just remux the video to an M2TS, as these can be played by the PS3. Remuxing means, taking the audio/video stream we are after from the file, and not re-encoding them at all, just repackaging them. As i said before, MKV is just a container, it is a method of storing video/audio content.

First off, you will need some MKV tools, lets get those quickly.

% sudo apt-get install mkvtoolnix

To remux, you will need a tool called tsMuxeR, which is freeware, thankfully. It has also been recently updated to include the up-till-now windows only gui. Which is great!

So, let’s download it, fire up a terminal of your choice, and lets get cracking. We’ll be working in your home folder first.

% cd ~/
% mkdir tsmuxer
% cd tsmuxer
% wget http://www.smlabs.net/tsMuxer/tsMuxeR_1.8.35\(b\).tar.gz
% tar zxvf ts*.gz

Now, you will have a few files in that folder, we are only interested in one of them for this post, but feel free to have a play with the GUI. Let’s move the tsMuxeR into the bin folder so our script we’re about to write will be able to access it.

% sudo mv tsMuxeR /usr/bin/

Now, tsMuxeR, should be accessible from anywhere on your machine. Test it just by typing tsMuxeR and it should spit out the version number, and some usage information.

So lets get onto our script, we want to be able to convert any MKVs, to M2TS, whilst also pulling out the language that we speak, with the best track. I.e. if there is a 5.1 channel track, use that instead of stereo.

This is a script that i have modified that was written a while ago, but it does the job, quite well too.

# /bin/bash
# - a simple wrapper around the tsmuxeR
# Creates a m2ts from a "standard" mkv (assuming video is MPEG4, and sound is AC3 or DTS)
#
# v0.1 initial version
# v0.2 added DTS support
# v0.3 changed to tsmuxer linux version + added multiple audio lang support
#
# Usage: mkvtom2ts filename.mkv
#
 
# Change this variable here, to change the languages it will strip from the MKV video.
AUDIO_LANGS="und eng"
 
#Loop through all MKVs in the current directory
for f in ./*.mkv
do
BASENAME=$(basename "$f" .mkv)
DEST_FILE=$BASENAME.m2ts
 
MPEG4_TRACK_NO=`mkvinfo "$f" | grep V_MPEG4/ISO/AVC -B10 | grep Track\ number\:\ | awk '{ print $5 }'`
 
for AUDIO_LANG in $AUDIO_LANGS
do
AC3_TRACK_NO=`mkvinfo "$f" | grep A_AC3 -B10 -C3 | grep Language\:\ $AUDIO_LANG -B13 | grep Track\ number\:\ | awk '{ print $5 }'`
DTS_TRACK_NO=`mkvinfo "$f" | grep A_DTS -B10 -C3 | grep Language\:\ $AUDIO_LANG -B13 | grep Track\ number\:\ | awk '{ print $5 }'`
if [ -n "$AC3_TRACK_NO" -o -n "$DTS_TRACK_NO" ]
then
break
fi
done
 
echo "Video(V_MPEG4/ISO/AVC) track no : $MPEG4_TRACK_NO"
echo "Audio(A_AC3) $AUDIO_LANG track no      : $AC3_TRACK_NO"
echo "Audio(A_DTS) $AUDIO_LANG track no      : $DTS_TRACK_NO"
 
#audio ac3->direct muxing
if [[ $AC3_TRACK_NO -gt "0" ]]
then
echo "Found ac3 track, muxing directly..."
rm -f mux.meta
echo "MUXOPT --no-pcr-on-video-pid --new-audio-pes --vbr" >> mux.meta
echo "V_MPEG4/ISO/AVC, "$f", level=4.1, insertSEI, contSPS, track=$MPEG4_TRACK_NO, lang=eng.meta" >> mux.meta
echo "A_AC3, "$f", track=$AC3_TRACK_NO, lang=eng" >> mux.meta
tsMuxeR mux.meta $DEST_FILE
rm -f mux.meta
else
if [[ $DTS_TRACK_NO -gt "0" ]]
then
echo "No ac3 but dts, converting to ac3.."
mkvextract tracks "$f" $DTS_TRACK_NO:"$BASENAME.dts" $MPEG4_TRACK_NO:"$BASENAME.mpeg4"
dcadec -r -o wavall "$BASENAME.dts" > "$BASENAME.wav"
aften "$BASENAME.wav" "$BASENAME.ac3"
echo "Muxing..."
rm -f mux.meta
echo "MUXOPT --no-pcr-on-video-pid --new-audio-pes --vbr" >> mux.meta
echo "V_MPEG4/ISO/AVC, "$BASENAME.mpeg4", level=4.1, insertSEI, contSPS, track=1, lang=eng" >> mux.meta
echo "A_AC3, "$BASENAME.ac3", track=1, lang=eng" >> mux.meta
tsMuxeR mux.meta $DEST_FILE
rm -f mux.meta $BASENAME.dts $BASENAME.wav $BASENAME.ac3 $BASENAME.mpeg4
else
echo "No ac3 or dts, exiting..."
fi
fi
 
if (disaster-condition)
then
#Abandon the loop.
break
fi
 
done

Have a quick read over the script, don’t worry about not understanding it, it’s not important, so long as it works :)

Lets make this file, and put it somewhere we can always use it.

% gedit allmkv2m2ts

Now copy all the code above which does the converting, and paste it into that file, then save and close gedit.

% sudo mv allmkv2m2ts /usr/bin/mkvall2m2ts
% sudo chmod 777 /usr/bin/allmkv2m2ts

It is now in the bin folder, so can be accessed anywhere, it can also used and edited by anyone.

And thats it. Now navigate yourself to your folder with all the MKVs in the root, and just type..

% allmkv2m2ts

Asif by magic, it should now start re-muxing all your MKVs to M2TS.

Please feel free to comment, and if you wrote the original script, please contact me and i will link to you.

2009
01.09

Well, if you followed the previous tutorial, we have a nice window, with nothing at all related to Pong inside it. Let’s create some paddles!

OK, So, sticking with the whole ‘modular’ process we have followed to so far, we aren’t just going to render a quad and throw a texture on it. We need to create an Entity Class, which will be the base class for any Entity (Ball, Paddles, Walls) we are going to need to use. Again, i know it’s a bit of hassle, but it’s all for the greater good, it means we’ll be able to add objects in and have certain standard functionality for any object, making rendering them much easier. Let’s see the class definition.

Entity.h

#ifndef ENTITY_H_
#define ENTITY_H_
 
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
 
#include <gl/glew.h>
#include <sdl/SDL.h>
#include <sdl/SDL_ttf.h>
 
//This isn't actually used yet really, but we will use it later, for checking what type of entity we are
enum ObjectType
{
	Type_Object, Type_Wall, Type_Ball, Type_Paddle, Type_Goal
};
 
class Entity
{
protected:
	float _width, _height;
	GLuint _texture;
	GLfloat _r, _g, _b;
	ObjectType _type;
 
	//Load up a bitmap from the provided filename so we can texture the quad with it.
	void CreateTextureFromFile(const char *filename);
 
	//Run a check to see if two entitys are colliding
	bool CollideBoundingBox(SDL_Rect a, SDL_Rect b);
 
public:
	float xVel, yVel;
	float _x, _y, _z;
 
	Entity();
 
	//Overrideable, so we know that Type of object this is (Enum ObjectType)
	virtual ObjectType Type();
 
	//Set the type of this object
	void SetType(ObjectType theType);
 
	//Check against another Entity if there is a collision occuring
	bool IsColliding(Entity *targetObject);
 
	//Default render method, just renders a quad
	void Render();
 
	//Initialise this Entity, with the following values...
	void Initialise(float width, float height, float x, float y);
	void Initialise(float width, float height, float x, float y, const char *texturelocation);
 
	//Give it a pretty colour? Not required...
	void SetColour(GLfloat r, GLfloat g, GLfloat b);
};
#endif /* ENTITY_H_ */

And there it is, all the methods have been commented enough to make them clear. They should be more understandable when we go through the declaration.

Now this is going to be quite long, as we are also going to support texturing in this class. So i will be taking you through that too.

First off, create a file in the same folder (Pong/src) called Entity.cpp, this is where all the logic will be held! For now, just throw this code into it, it should be fairly understandable as is.

Entity.cpp

#include "Entity.h"
 
Entity::Entity()
{
        //Initialise all the variables we are going to use...
	this-&gt;_x = this-&gt;_y = this-&gt;xVel = this-&gt;yVel = this-&gt;_r = this-&gt;_g = this-&gt;_b = 0.0f;
	this-&gt;_texture = 0;
}

Let’s get onto the definitions of the fun stuff! I say we start with Initialise, as it’s really the first method(s) that get called. So let’s see it.

void Entity::Initialise(float width, float height, float x, float y)
{
        //Literally just set the variables, these won't get used again until render.
	_width = width;
	_height = height;
	_x = x;
	_y = y;
}
 
void Entity::Initialise(float width, float height, float x, float y, const char *texturelocation)
{
        //Call the other Initialise method, just so we can set the values
	this-&gt;Initialise(width, height, x, y);
 
        ///Create a texture, using the textureLocation variable passed in
	CreateTextureFromFile(texturelocation);
}
 
void Entity::SetColour(GLfloat r, GLfloat g, GLfloat b)
{
	this->_r = r;
	this->_g = g;
	this->_b = b;
}

Now, any bright spark will know this won’t now compile, because i haven’t given you the definition for CreateTextureFromFile, well thats next, so be patient! ;) It’s quite long, so i have commented it in detail…

void Entity::CreateTextureFromFile(const char *filename)
{
	//We will use this Surface to load the image onto, before we create a texture out of it.
	SDL_Surface *surface;
 
	//This will store the texture format for OpenGL, i.e. RGB, RGBA, BGR, etc
	GLenum texture_format;
 
	//This stores how many colours we have in the image, i.e. if it's only got RGB, we have 3
	GLint nOfColors;
 
	//Lets load up the image provided by the filename parameter
	if ((surface = SDL_LoadBMP(filename)))
	{
		//Whoo, we have loaded it, let's find it's format!
		nOfColors = surface-&gt;format-&gt;BytesPerPixel;
 
		//Do we have 4 colours? Red, Green, Blue and Alpha
		if (nOfColors == 4)
		{
			//Yes, which order is it? Red First?
			if (surface-&gt;format-&gt;Rmask == 0x000000ff)
				texture_format = GL_RGBA;
			else
				texture_format = GL_BGRA;
		}
		else if (nOfColors == 3)
		{
			//Oh, we only have 3 colours? OK, again, which order are those 3 colours in?
			if (surface-&gt;format-&gt;Rmask == 0x000000ff)
				texture_format = GL_RGB;
			else
				texture_format = GL_BGR;
		}
		else
			printf("warning: the image is not truecolor..  this will probably breakn");
 
		// Have OpenGL generate a texture object handle for us, using our _texture Member variable, so we always have access to it
		glGenTextures(1, &amp;_texture);
 
		// Bind the texture object to our _textureMember variable
		glBindTexture(GL_TEXTURE_2D, _texture);
 
		// Set a few parameters on our Texture, so it displays as we want it to.
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 
		// Set all the image data of the texture, here we set it's width, it's height, the format, and the actual data (surface-&gt;pixels)
		glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface-&gt;w, surface-&gt;h, 0, texture_format, GL_UNSIGNED_BYTE, surface-&gt;pixels);
	}
	else
	{
		//General error message if file could not be found
		std::cout &lt;&lt; "SDL could not load " &lt;&lt; filename &lt;&lt; ": " &lt;&lt; SDL_GetError() &lt;&lt; std::endl;
		SDL_Quit();
	}
 
	// Free the SDL_Surface only if it was successfully created
	if (surface)
	{
		//Free the memory used by the surface, as we have now loaded all the data up into OpenGL, it has it's own copy of the image in memory
		SDL_FreeSurface(surface);
	}
}

So, now we have can create an Entity, give it a texture, but we still can’t see it? Damn, i guess we should render it then.

void Entity::Render()
{
	//If we have an xVelocity or a yVelocity, then increment the X or Y position based on their velocity
	if (xVel != 0 || yVel != 0)
	{
		_x += this-&gt;xVel;
		_y += this-&gt;yVel;
	}
 
	//Check to see if we have a texture loaded up, if we do, then enable texturing and bind the texture, so that the next thing
	//we render with texturing, it will get this texture.
	if (_texture != 0)
	{
		//Enable Texturing
		glEnable(GL_TEXTURE_2D);
		//Bind the Texture to this object
		glBindTexture(GL_TEXTURE_2D, _texture);
	}
 
	//Stack the current settings for colour, so we can set the colour for this object, then pop the settings back when we are done
	glPushAttrib(GL_CURRENT_BIT);
 
	//Draw this object the correct colour, notice we set the _r, _g, _b color. This WILL effect the colour of your textures.
	glColor3f(_r, _g, _b);
 
	//Move the object to the correct location in space, we are only working in 2D so don't need to worry about the Z Value
	glTranslatef(_x, _y, 0);
 
	//Tell OpenGL we want to render a quad, which is a 4 sided polygon
	glBegin(GL_QUADS);
 
	//Now, here we need to check to see if we loaded up a texture, if we did then we need to tell opengl how to render the texture
	//i.e. where the top left is. I won't comment the others, as this one should explain them all. We set 0,0 because that is the
	//upper left of the quad, and that is how we want our Image to appear. We could render it upside down of course, but thats silly.
	if (_texture != 0)
		glTexCoord2i(0, 0);
 
	//So, now we have told opengl where to render our texture, we need to give it something to render it onto. We want to create vertex
	//which is just a point in 3d space, of course as we are creating a quad, we need to specify 4 of them. This is the top left corner
	//of the box, we next do the bottom left, then the bottom right, then the top right. OGL will then render that as a 4 sided polygon.
	glVertex3f(0, 0, 0);
 
	//Texturing again
	if (_texture != 0)
		glTexCoord2i(0, 1);
 
	//Bottom Left Corner, see how we specify the height. This will create an object which is _height pixels high.
	glVertex3f(0, _height, 0);
 
	//Texturing again
	if (_texture != 0)
		glTexCoord2i(1, 1);
 
	//Bottom left, again, with the height, also now with the width
	glVertex3f(_width, _height, 0);
 
	//Texturing again
	if (_texture != 0)
		glTexCoord2i(1, 0);
 
	//Now for the top right, just need to tell it the width
	glVertex3f(_width, 0, 0);
	glEnd();
 
	//Pop the colour settings back from the stack
	glPopAttrib();
 
	//Disable Texturing again, so nothing else gets this texture applied to them.
	if (_texture != 0)
		glDisable(GL_TEXTURE_2D);
}

There is the beast, this will now allow us to render a 2D object (technically it is a 3d object) onto the screen, with a designated texture. Should we so with, this is just preparation for the future, we aren’t going to be texturing anything in this tutorial

So, we can create an entity, give it a texture, and now render it, what else is there?! Well, we need to know when two Entity’s are touching each other, otherwise how will we know when we’ve scored a goal? Or even worse, the ball won’t bounce off the wall and it’ll just float into space, and then no-one wins. And nobody likes a draw.

Let’s do some collision detection, it’s only simple 2D stuff. This function was taken from GPWiki, which is brilliant for Game Programming. This is the exact link to the article i used. I didn’t see the point in-reinventing the wheel, even though it is a very simple wheel.

Here’s the definition of the Collision methods.

bool Entity::CollideBoundingBox(SDL_Rect a, SDL_Rect b)
{
	if (b.x + b.w &lt; a.x)
		return false;
	if (b.x &gt; a.x + a.w)
		return false;
 
	if (b.y + b.h &lt; a.y)
		return false;
	if (b.y &gt; a.y + a.h)
		return false;
 
	return true; //bounding boxes intersect
}
 
bool Entity::IsColliding(Entity *targetObject)
{
        //This isn't the most optimal way of doing this, but it does the trick for pong. We just create two rectangles
        //for this entity and the target one, so we can see if they are overlapping
	SDL_Rect thisRect;
	thisRect.h = this-&gt;_height;
	thisRect.w = this-&gt;_width;
	thisRect.x = this-&gt;_x;
	thisRect.y = this-&gt;_y;
 
	SDL_Rect targetRect;
	targetRect.h = targetObject-&gt;_height;
	targetRect.w = targetObject-&gt;_width;
	targetRect.x = targetObject-&gt;_x;
	targetRect.y = targetObject-&gt;_y;
 
        //Run the check, to see if they are colliding
	return CollideBoundingBox(thisRect, targetRect);
}

Now we can check to see if two objects are colliding. I.e. the Ball with the Wall, or the Ball with a paddle.

Here are the other two methods, that are really simple and won’t actually get used just yet. This again, is for future use. It’s just for storing and retrieving the Entity’s type, i.e. Ball

ObjectType Entity::Type()
{
	return _type;
}
 
void Entity::SetType(ObjectType theType)
{
	_type = theType;
}

Right, let’s get a paddle on our screen, that’s enough preperation! Note: Don’t forget, we need to add this class to the Makefiles! Don’t remember how? Follow the previous tutorial, but instead of adding Pong.o we want Entity.o. I will attach the entire folder at the end so you could just take those makefiles.

In your Pong.h, you will now need to create a Two Entity instances and include the Entity header.

/*Add this Line*/
#include "Entity.h"
/*Add this Line*/
 
class Pong
{
        /*Add this Line*/
	Entity player1, player2;
        /*Add this Line*/
};

These will be both the paddles, for the left and the right of the screen.

Now, in our Pong classes InitialiseGeometry method, we need to do just that, Initialise the Entity Instances.

void Pong::InitialiseGeometry()
{
	//As the height of our Paddles, is 80 pixels, we need to determine where the center of the window would be for our paddles.
	//Simple as ((height / 2) - (paddle_height - 2))
	float playerStartY = ((_height / 2) - 40);
 
	//Now Initialise our objects we want to be showing, we set their Width and Height, the their position, fairly simple
       player1.Initialise(15, 80, 20, playerStartY);
 
       //Now we set Player1's color, for this tutorial they both will be white.
       player1.SetColour(1, 1, 1);
 
       //Exactly the same again, except this one is drawn on the right hand side
       player2.Initialise(15, 80, (_width - 35), playerStartY);
       player2.SetColour(1, 1, 1);
}

So we have 2 Paddles now (effectively), both are white, one on the left, one on the right. Both centered vertically. Great! Oh wait, we can’t see them!

Let’s render them!! Can you guess which method we want to render them in? (I’ll give you a hint…Render.)

glClear(GL_COLOR_BUFFER_BIT);
 
//glPushMatrix, will store the current state of the matrix in a special little box, so we can't mess it up. Which gives us a license to do
//what ever we like to it, as we can just pop it back out of the box, and restore it back to the way it was. This is especially useful when
//we are moving objects around space. You may be thinking, we aren't moving them, they are static. Actually, they're not. We are creating
//the boxes at 0,0 (top left in this perspective), then we are moving them to their location.
glPushMatrix();
 
//Call the Entity's render method, which creates a quad, set's it's colour and renders it
player1.Render();
 
//Pop the matrix back to it's previous state, so now any objects we create, will be in the top left, and our first object will be where we left it.
glPopMatrix();
 
//Same as above, but with Player2.
glPushMatrix();
player2.Render();
glPopMatrix();
 
SDL_GL_SwapBuffers();

Now, compile your game. Run it, just like in the previous tutorials.

make
./Pong

IF compile was a success, you should be presented with a black window and two Paddles. Like this…

pongstep3

If you are, then great! Well done. If not, leave a comment with the problem and i’ll try and see what happened.

As always, here is the entire project source. Also as always, limited comments. Learn from reading the blog, not from taking code ;)

Pong Step 3.zip

Enjoy! Look forward to seeing you again soon. Well, your stat on my web logs anyway!

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