Sign in to follow this  
metal_kid43

Pong SDL

Recommended Posts

Ok, so I've got my pong game setup, but want to add some finishing touches on it like sound FX, and opening screen, and a scoreboard. Right now when you open the .exe it goes straight into the game and the ball starts moving right away and play commences. Im wondering how to add a screen before the game starts to have the user press spacebar to continue and start playing the game.
#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>

using namespace std;

const int WINDOW_WIDTH = 720;
const int WINDOW_HEIGHT = 480;
const char* WINDOW_TITLE = "Pong";
float ballXVel = 1;
float ballYVel = 1;
int main(int argc, char *argv[])
{
	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER );
	SDL_Surface* screen = SDL_SetVideoMode( WINDOW_WIDTH, WINDOW_HEIGHT, 0, 
      SDL_HWSURFACE | SDL_DOUBLEBUF );
	SDL_WM_SetCaption(WINDOW_TITLE, 0);
	SDL_Surface* paddle1 = SDL_LoadBMP("paddle1.bmp");
	SDL_Surface* paddle2 = SDL_LoadBMP("paddle2.bmp");
	SDL_Surface* ball = SDL_LoadBMP("ball.bmp");
    SDL_SetColorKey(ball, SDL_SRCCOLORKEY, SDL_MapRGB(ball->format, 
      255, 0, 0)); 
	
    SDL_Rect paddle1_source;
	paddle1_source.x = 0;
	paddle1_source.y = 0;
	paddle1_source.w = 20;
	paddle1_source.h = 100;
	
	SDL_Rect paddle1_destination;
    paddle1_destination.x = 75;
    paddle1_destination.y = 240;
    paddle1_destination.w = 20;
    paddle1_destination.h = 100;
    
    SDL_Rect paddle2_source;
    paddle2_source.x = 0;
    paddle2_source.y = 0;
    paddle2_source.w = 20;
    paddle2_source.h = 100;
    
    SDL_Rect paddle2_destination;
    paddle2_destination.x = 645;
    paddle2_destination.y = 240;
    paddle2_destination.w = 20;
    paddle2_destination.h = 100;
    
    SDL_Rect ball_source;
    ball_source.x = 0;
    ball_source.y = 0;
    ball_source.w = 25;
    ball_source.h = 25;
    
    SDL_Rect ball_position;
    ball_position.x = WINDOW_WIDTH/2;
    ball_position.y = WINDOW_HEIGHT/2;
    ball_position.w = 25;
    ball_position.h = 25;
    
SDL_Event event;

	bool gameRunning = true;
	bool keysHeld[323] ={false};
	while (gameRunning)
	{
		
        
        if (SDL_PollEvent(&event))
		{
			if (event.type == SDL_QUIT)
			{
				gameRunning = false;
			}
			if (event.type == SDL_KEYDOWN)
			{
				keysHeld[event.key.keysym.sym] = true;
			}
			if (event.type == SDL_KEYUP)
			{
				keysHeld[event.key.keysym.sym] = false;
			}	
		}
		
		
        if (keysHeld[SDLK_ESCAPE])
		{
			gameRunning = false;
		}
        if (keysHeld[SDLK_UP])
        {
            paddle1_destination.y -= 2;
        }
        if (keysHeld[SDLK_DOWN])
        {
            paddle1_destination.y += 2;
            if (paddle1_destination.y + paddle1_destination.h > WINDOW_HEIGHT)
            {
                paddle1_destination.y = 480 - paddle1_destination.h;
            }
        }
        if (keysHeld[SDLK_KP2])
        {
            paddle2_destination.y += 2;
            if (paddle2_destination.y + paddle2_destination.h > WINDOW_HEIGHT)
            {
                paddle2_destination.y = 480 - paddle2_destination.h;
            }
        }
        if (keysHeld[SDLK_KP8])
        {
            paddle2_destination.y -= 2;
        }
        
        
        ball_position.x += ballXVel;
        ball_position.y += ballYVel;


        
        if (ball_position.x  + ball_position.w >  WINDOW_WIDTH)
        {
             gameRunning = false;
        }
        if (ball_position.x  < 0)
        {
             gameRunning = false;
        }
        if (ball_position.y  + ball_position.h >  WINDOW_HEIGHT)
        {
             ballYVel *= -1;
        }
        if (ball_position.y  <0  )
        {
             ballYVel *= -1;
        }
        if (ball_position.x   == paddle1_destination.x + paddle1_destination.w && ball_position.y + ball_position.h >= paddle1_destination.y )
        {
             ballXVel *= -1.0;  
        }
        if (ball_position.x +ball_position.w  == paddle2_destination.x  && ball_position.y + ball_position.h  >= paddle2_destination.y && ball_position.y <= paddle2_destination.y + paddle2_destination.h)
        {
             ballXVel *= -1.0;
        }
        SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 0));
        SDL_BlitSurface(paddle1, &paddle1_source, screen, &paddle1_destination);
        SDL_BlitSurface(paddle2, &paddle2_source, screen, &paddle2_destination);
        SDL_BlitSurface(ball, &ball_source, screen, &ball_position);
        
        SDL_Flip(screen);
	    
    }
    SDL_FreeSurface(paddle1); 
    SDL_FreeSurface(paddle2);
    SDL_FreeSurface(ball);
    
    SDL_Quit();
	return 0;
}

Share this post


Link to post
Share on other sites
you could define different game states:


#define GAME_STATE_INTRO 0
#define GAME_STATE_RUN 1
#define GAME_STATE_SCOREBOARD 2

int game_state = GAME_STATE_INTRO;

while (game_state < 3)
{
if(KEYDOWN(ESCAPE))
game_state++;

...

switch(game_state)
{
case GAME_STATE_INTRO:
// fill backbuffer with intro image or whatever...
break;
case GAME_STATE_RUN:
// fill backbuffer with next game frame (ofcourse)
break;
case GAME_STATE_SCOREBOARD:
// fill backbuffer with scores and stuff...
break;
}

// render screen (flip)
}




Maybe use the ESCAPE key to exit the intro and start running,
and ESCAPE again to quit the game and go to the score board :p
Just an idea

Share this post


Link to post
Share on other sites
Hmmm, i think i understand now. So, i just blit my intro scree under case GAME_STATE_INTRO and put the rest of the code under case GAME_STATE_RUN:? In that case, im inclined to ask, where do i put the main () function?

Share this post


Link to post
Share on other sites
Everything stays as it is as I see it.

Only set up a switch right after the key event stuff, and
put all the game render and collision stuff under GAME_STATE_RUN
(basically all the stuff you have there now)
Except

SDL_Flip(screen);

that must be after the switch

Share this post


Link to post
Share on other sites
What I typically do is have the main program run a program manager class. Within that class is a subclass manager for each game state. Something like this:

-----------------------

MAIN LOOP:

{
programManager.Run(); //called every frame
}

-----------------------

PROGRAM MANAGER:

int gameState;

.
.
.

bool CProgramManager::Run()
{

.
.
.
//runs the submanager for the appropriate game state.
switch(gameState)
{
case GAMEPLAY :
gameplayManager.Run();
break;
case SPLASH :
splashScreenManager.Run();
break;
case SCORE :
scoreScreenManager.Run();
break;

}
.
.
.

}

-----------------------

The program manager class works as sort of a facade. As your games get bigger, you'll be glad to have the code for each state ecapsulated separately.

Share this post


Link to post
Share on other sites
Yes, and also when using different game states, you have full control of each state.
If you want you could give the keys on the keyboard different meaning based on the current game state, which can come in very handy, say if you need the user to type in an ip address in the init state, while in run state the same keys would write text to a game chat or something.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this