Table of Contents

Project: Tutorials for making pong

A project for systems programming by Matt Witter during the Spring 2013 semester.

This project was begun on January 23 and is anticipated to take most of the spring semester. You can find most of the tutorials I did in my systemprog folder.

Objectives

This wasn't originally suppose to be a project but it turned in to one when I ran out of time to make another game. The point of this project is to work up to making pong. The tutorials will help build up the ideas or concepts that we need to make a game.

Prerequisites

In order to successfully accomplish/perform this project, the listed resources/experiences need to be consulted/achieved:

Background

State the idea or purpose of the project. What are you attempting to pursue? I'm attempting to get through tutorials 1-18 and then move on to making pong. I got through the tutorials but I didnt get very far in pong.

Scope

Well this wasn't really meant to be a project but once it got close I kind of turned it into one. I just went through the tutorials until I got to 18 and attempted pong. I didn't get very far in pong mostly because I had about a week left and I was trying to get it but I had to catch up on some of Joe's stuff.

Procedure

The procedure was just going through the tutorials on lazyfoo.net

Code

Here's one of the final tutorials for lazyfoo.net. It is one of the final collision detection tutorials either 17 or 18

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>
 
//screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
 
//the frame rate
const int FRAMES_PER_SECOND = 20;
 
//the dimenions of the square
const int SQUARE_HEIGHT = 20;
const int SQUARE_WIDTH = 20;
 
//the surfaces
SDL_Surface *square = NULL;
SDL_Surface *screen = NULL;
 
//the event structure
SDL_Event event;
 
//the wall
SDL_Rect wall;
 
//the square
class Square
{
	private:
	//the coolision box of the square
	SDL_Rect box;
 
	//the velocity of the square
	int xVel, yVel;
 
	public:
	//initalizes the variables
	Square():
 
	//take key presses and adjusts the squares velocity
	void handle_input();
 
	//moves the square
	void move();
 
	//shows the square on the screen
	void show();
};
 
//timer class
class Timer
{
	private:
	//the clocks time when the timer started
	int startTicks;
 
	//the ticks stored when the timer was paused
	int pausedTicks;
 
	//the timer status
	bool paused;
	bool started;
 
	public:	
	//initalized the variables
	Timer();
 
	//the various clock actions
	void start();
	void stop();
	void pause();
	void unpause();
 
	//gets the timers time
	int get_ticks();
 
	//checks that status of the timer
	bool is_started;
	bool is_paused;
};
 
SDL_Surface *load_image(std::string filename)
{
	//the image thats loaded
	SDL_Surface* loadedImage = NULL;
 
	//the optimized surface taht will be used
	SDL_Surface* optimizedImage = NULL;
 
	//load the image
	loadedImage = IMG_Load(filename.c_str());
 
	//if the image loaded
	if(loadedImage != NULL)
	{
		//create the optmized surface
		optimizedImage = SDL_DisplayFormat(loadedImage);
 
		//free the old surface
		SDL_FreeSurface(loadedImage);
 
		//if the surface was optimized
		if(optimizedImage != NULL)
		{
			//color key surface
			SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF));
		}
	}
 
	//return the optimized surface
	return optimizedImage;
}
 
void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination, SD:_Rect* clip = NULL)
{
	//holds offsets
	SDL_Rect offset;
 
	//get offsets
	offset.x = x;
	offset.y = y;
 
	//blit
	SDL_BlitSurface(source, clip, destination, &offset);
}
 
bool init()
{
	//initalize all sdl subsystems
	if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
	{
		return false;
	}
 
	//set up the screen
	screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,SDL_SWSURFACE);
 
	//if there was an error in setting up the screen
	if(screen == NULL)
	{
		return false;
	}
 
	//set the window caption
	SDL_WM_SetCaption("move square", NULL);
 
	//if everything initialized fine
	return true;
}
 
bool load_files()
{
	//load the background image
	square = load_image("square.bmp");
 
	//if there was a problem loading image
	if(square == NULL)
	{
		return false;
	}
 
	//if everything loaded fine
	return true;
}
 
void clean_up()
{
	//free the surface
	SDL_FreeSurface(square);
 
	//quit SDL
	SDL_Quit();
}
 
//the square
class Square
{
	private:
	//the collision box of the square
	SDL_Rect box;
 
	//the velocity of the square
	int xVel, yVel;
 
	public:
	//initalize the variables
	square();
 
	//takes key presses and adjusts the squares velocity
	void handle_input();
 
	//moves the square
	void move();
 
	//shows the square on the screen
	void show();
};
 
bool check_collision(SDL_Rect A, SDL_Rect B)
{
	//the sides of the rectangles
	int leftA, leftB;
	int rightA, rightB;
	int topA, topB;
	int bottomA, bottomB;
 
	//calculate the sides of rect A
	leftA = A.x;
	rightA = A.x + A.w;
	topA = A.y;
	bottomA = A.y + A.h;
 
	//calculate the sides of rect B
	leftB = B.x;
	rightB = B.x + B.w;
	topB = B.y;
	bottomB = B.y + B.h;
 
	//if any of the sides from A are outside B
	if( bottomA <= topB)
	{
		return false;
	}
 
	if( topA >= bottomB)
	{
		return false;
	}
 
	if( rightA <= leftB)
	{
		return false;
	}
 
	if(leftA >= rightB)
	{
		return false;
	}
 
	//if none of the sides from A are outside B
	return true;
}
 
Square::Square()
{
	//initialize the offsets
	box.x = 0;
	box.y = 0;
 
	//set the squares dimensions
	box.w = SQUARE_WIDTH;
	box.h = SQUARE_HEIGHT;
 
	//initialize the velocity
	xVel = 0;
	yVel = 0;
}
 
void Square::move()
{
	//move the square left or right
	box.x += xVel;
 
	//if the square went too far to the left or right or has collided with the wall
	if((box.x < 0) || (box.x + SQUARE_WIDTH > SCREEN_WIDTH ) || (check_collision(box, wall)))
	{
		//move back
		box.x -= xVel;
	}
 
	//move the square up or down
	box.y += yVel;
 
	//if the square went too far up or down or has collided with the wall
	if((box.y < 0) || (box.y + SQUARE-HEIGHT > SCREEN_HEIGHT) || (check_collision(box, wall)))
	{
		//move back
		box.y -= yVel;
	}
}
 
void Square::handle_input()
{
    //If a key was pressed
    if( event.type == SDL_KEYDOWN )
    {
        //Adjust the velocity
        switch( event.key.keysym.sym )
        {
            case SDLK_UP: yVel -= SQUARE_HEIGHT / 2; break;
            case SDLK_DOWN: yVel += SQUARE_HEIGHT / 2; break;
            case SDLK_LEFT: xVel -= SQUARE_WIDTH / 2; break;
            case SDLK_RIGHT: xVel += SQUARE_WIDTH / 2; break;
        }
    }
    //If a key was released
    else if( event.type == SDL_KEYUP )
    {
        //Adjust the velocity
        switch( event.key.keysym.sym )
        {
            case SDLK_UP: yVel += SQUARE_HEIGHT / 2; break;
            case SDLK_DOWN: yVel -= SQUARE_HEIGHT / 2; break;
            case SDLK_LEFT: xVel += SQUARE_WIDTH / 2; break;
            case SDLK_RIGHT: xVel -= SQUARE_WIDTH / 2; break;
        }
    }
}
 
void Square::show()
{
    //Show the square
    apply_surface( box.x, box.y, square, screen );
}
 
Timer::Timer()
{
    //Initialize the variables
    startTicks = 0;
    pausedTicks = 0;
    paused = false;
    started = false;
}
 
void Timer::start()
{
    //Start the timer
    started = true;
 
    //Unpause the timer
    paused = false;
 
    //Get the current clock time
    startTicks = SDL_GetTicks();
}
 
void Timer::stop()
{
    //Stop the timer
    started = false;
 
    //Unpause the timer
    paused = false;
}
 
void Timer::pause()
{
    //If the timer is running and isn't already paused
    if( ( started == true ) && ( paused == false ) )
    {
        //Pause the timer
        paused = true;
 
        //Calculate the paused ticks
        pausedTicks = SDL_GetTicks() - startTicks;
    }
}
 
void Timer::unpause()
{
    //If the timer is paused
    if( paused == true )
    {
        //Unpause the timer
        paused = false;
 
        //Reset the starting ticks
        startTicks = SDL_GetTicks() - pausedTicks;
 
        //Reset the paused ticks
        pausedTicks = 0;
    }
}
 
int Timer::get_ticks()
{
    //If the timer is running
    if( started == true )
    {
        //If the timer is paused
        if( paused == true )
        {
            //Return the number of ticks when the timer was paused
            return pausedTicks;
        }
        else
        {
            //Return the current time minus the start time
            return SDL_GetTicks() - startTicks;
        }
    }
 
    //If the timer isn't running
    return 0;
}
 
bool Timer::is_started()
{
    return started;
}
 
bool Timer::is_paused()
{
    return paused;
}
 
int main( int argc, char* args[] )
{
    //Quit flag
    bool quit = false;
 
    //The square
    Square mySquare;
 
    //The frame rate regulator
    Timer fps;
 
    //Initialize
    if( init() == false )
    {
        return 1;
    }
 
    //Load the files
    if( load_files() == false )
    {
        return 1;
    }
 
    //Set the wall
    wall.x = 300;
    wall.y = 40;
    wall.w = 40;
    wall.h = 400;
 
    //While the user hasn't quit
    while( quit == false )
    {
        //Start the frame timer
        fps.start();
 
        //While there's events to handle
        while( SDL_PollEvent( &event ) )
        {
            //Handle events for the square
            mySquare.handle_input();
 
            //If the user has Xed out the window
            if( event.type == SDL_QUIT )
            {
                //Quit the program
                quit = true;
            }
        }
 
        //Move the square
        mySquare.move();
 
        //Fill the screen white
        SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) );
 
        //Show the wall
        SDL_FillRect( screen, &wall, SDL_MapRGB( screen->format, 0x77, 0x77, 0x77 ) );
 
        //Show the square on the screen
        mySquare.show();
 
        //Update the screen
        if( SDL_Flip( screen ) == -1 )
        {
            return 1;
        }
 
        //Cap the frame rate
        if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
        {
            SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
        }
    }
 
    //Clean up
    clean_up();
 
    return 0;
} 

Execution

Again, if there is associated code with the project, and you haven't already indicated how to run it, provide a sample run of your code:

lab46:~/src/cprog$ ./collision
lab46:~/src/cprog$ 

Reflection

Comments/thoughts generated through performing the project, observations made, analysis rendered, conclusions wrought. What did you learn from doing this project? I mostly learned that making little games has a lot more to it than I thought before doing this. Pong is a pretty hard game to make.

References

In performing this project, the following resources were referenced: