Sign in to follow this  
password

Pong help

Recommended Posts

I need help with the collision check on my pong game, it works fine until I try to change the error where the ball gets stuck in the paddle. I've been coding for about half an hour now to get it working and the ball goes the opposite direction when it hits the side of the paddle, that also prevents it from getting stuck in the paddle. The problem is that other errors mysteriously appear that shouldn't be there. Can someone post a working collision check for the side hits, i've tried from another source and edited but it won't work. My collision check is simply like this right now when it's working but gets stuck in the sides sometimes: // Changes the y direction on collision if (yDirection==1) { yDirection=0; ballBox.y-=ySpeed; } else if (yDirection==0) { yDirection=1; ballBox.y+=ySpeed; } I have tried the follow code:
[SOURCE]
// When the ball hits the right side on any of the paddles
if ((ballBox.x == playerClass->playerBox.x + BOARD_WIDTH) || (ballBox.x == playerClass2->playerBox.x + BOARD_WIDTH)) {
    if (xSpeed<=6)
        xSpeed+=2;  
                    
    ballBox.x+=xSpeed;
                    
    xDirection=1;                 
                
// When the ball hits the left side on any of the paddles    
} else if ((ballBox.x + OBJECT_WIDTH == playerClass->playerBox.x) || (ballBox.x + OBJECT_WIDTH == playerClass2->playerBox.x)) {
    if (xSpeed<=6)
        xSpeed+=2;
                
    ballBox.x-=xSpeed;
                    
    xDirection=0;    
}
[/SOURCE]
The two later if statements I posted where embedded in another if statement first which checked if the ball had the same or lesser y position as the board, when I had that it worked and didn't get stuck but other things got really buggy. How can I make it work when nothing seems to work whatever I do. It shouldn't act like this..

Share this post


Link to post
Share on other sites
looking at your code, what happens when (im assuming playerClass is the left paddle)
playerClass->playerBox.x + BOARD_WIDTH = 50
ballBox.x = 52
xSpeed = 6

and ballBox is about to update with the speed

Share this post


Link to post
Share on other sites
Yes, the playerClass is the upper paddle (computer) and playerClass2 is the lower paddle (player). ballBox is the ball rect, xDirection changes the x direction of the ball which is supposed to make the ball go the opposite direction if it hits the side of the paddle, else the direction is the same.

By the way, can post the full source here:

[SOURCE]
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>

const int FRAMES_PER_SECOND = 80;

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

const int OBJECT_WIDTH = 12;
const int OBJECT_HEIGHT = 12;

const int BOARD_WIDTH = 120;
const int BOARD_HEIGHT = 15;

SDL_Surface *gameover = NULL;
SDL_Surface *p1score = NULL;
SDL_Surface *p2score = NULL;
SDL_Surface *screen = NULL;
SDL_Surface *board = NULL;
SDL_Surface *dot = NULL;

SDL_Event event;

TTF_Font *font;
SDL_Color fontColor = {255, 255, 255};

int player1Score=0, player2Score=0;

class Player;
class Computer;

class Object {
public:
Object(int X, int Y);

void show(Computer *playerClass, Player *playerClass2);

SDL_Rect ballBox;

int xDirection, yDirection;
int xSpeed, ySpeed;

private:
int x,y;
};

class Player {
public:
Player(int X, int Y);

void handle_input();
void show();

SDL_Rect playerBox;

private:
int xVel;
};

class Computer {
public:
Computer(int X, int Y);

void show(Object *theBall);

SDL_Rect playerBox;

private:
int xVel;
};

class Timer {
public:
Timer();

void start();
void stop();
void pause();
void unpause();

int get_ticks();

bool is_started();
bool is_paused();

private:
int startTicks;
int pausedTicks;

bool paused;
bool started;
};

SDL_Surface *load_image(std::string filename) {
//The image that's loaded
SDL_Surface* loadedImage = NULL;

//The optimized image that will be used
SDL_Surface* optimizedImage = NULL;

//Load the image using SDL_image
loadedImage = IMG_Load(filename.c_str());

//If the image loaded
if(loadedImage != NULL) {
//Create an optimized image
optimizedImage = SDL_DisplayFormat(loadedImage);

//Free the old image
SDL_FreeSurface(loadedImage);

if (optimizedImage != NULL) {
SDL_SetColorKey(optimizedImage, SDL_RLEACCEL | SDL_SRCCOLORKEY, SDL_MapRGB(optimizedImage->format, 0, 0xff, 0xff));
}
}

//Return the optimized image
return optimizedImage;
}

void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect *clip = NULL) {
SDL_Rect offset;

offset.x=x;
offset.y=y;

SDL_BlitSurface(source, clip, destination, &offset);
}

bool check_collision(SDL_Rect &A, SDL_Rect &B) {
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;

leftA = A.x;
rightA = A.x+A.w;
topA = A.y;
bottomA = A.y+A.h;

leftB = B.x;
rightB = B.x + B.w;
topB = B.y;
bottomB = B.y + B.h;

if (bottomA <= topB) {
return false;
}

if (topA >= bottomB) {
return false;
}

if (rightA <= leftB) {
return false;
}

if (leftA >= rightB) {
return false;
}

return true;
}

bool init() {
//Initialize 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 in error in setting up the screen
if (screen == NULL) {
return false;
}

if (TTF_Init() < 0) {
return false;
}

//Set the window caption
SDL_WM_SetCaption("Pong Game - Version 1.0", NULL);

//If everything initialized fine
return true;
}

void Shutdown() {
SDL_FreeSurface(gameover);
SDL_FreeSurface(p1score);
SDL_FreeSurface(p2score);
SDL_FreeSurface(board);
SDL_FreeSurface(dot);

TTF_CloseFont(font);
TTF_Quit();

SDL_Quit();
}

Object::Object(int X, int Y) {
ballBox.x = X;
ballBox.y = Y;

ballBox.w = OBJECT_WIDTH;
ballBox.h = OBJECT_HEIGHT;

xSpeed=3;
ySpeed=1;

xDirection=1;
yDirection=1;
}

void Object::show(Computer *playerClass, Player *playerClass2) {
if (xDirection==1)
ballBox.x+=xSpeed;
else if (xDirection==0)
ballBox.x-=xSpeed;
else
ballBox.x+=0;

if ((ballBox.x<0) || (ballBox.x+OBJECT_WIDTH > SCREEN_WIDTH)) {
if (xDirection==1) {
xDirection=0;
ballBox.x-=xSpeed;
} else if (xDirection==0) {
xDirection=1;
ballBox.x+=xSpeed;
}
}

if (yDirection==1)
ballBox.y+=ySpeed;
else if (yDirection==0)
ballBox.y-=ySpeed;
else
ballBox.y+=0;

if ((ballBox.y<0) || (ballBox.y+OBJECT_HEIGHT > SCREEN_HEIGHT)) {
SDL_Delay(200);
ballBox.x = SCREEN_WIDTH-(SCREEN_WIDTH/2);
ballBox.y = SCREEN_HEIGHT-(SCREEN_HEIGHT/2);

if (yDirection==0) {
player2Score++;
} else if (yDirection==1) {
player1Score++;
}

yDirection=1;
xDirection=1;

xSpeed=2;
ySpeed=1;
}


if (check_collision(ballBox, playerClass->playerBox) || check_collision(ballBox, playerClass2->playerBox)) {
if (!xSpeed>5)
xSpeed+=rand()%2;

if (ySpeed!=3 || !ySpeed>3)
ySpeed=rand()%3;

// If the ball is the same height or lower tham any of the paddles
if ((ballBox.y + OBJECT_HEIGHT >= playerClass2->playerBox.y)) {
// When the ball hits the right side on any of the paddles
if (ballBox.x == playerClass2->playerBox.x + BOARD_WIDTH) {
if (xSpeed<=6)
xSpeed+=2;

ballBox.x+=xSpeed;

xDirection=1;

// When the ball hits the left side on any of the paddles
} else if (ballBox.x + OBJECT_WIDTH == playerClass2->playerBox.x) {
if (xSpeed<=6)
xSpeed+=2;

ballBox.x-=xSpeed;

xDirection=0;
}
}

// Changes the y direction on collision
if (yDirection==1) {
yDirection=0;
ballBox.y-=ySpeed;
} else if (yDirection==0) {
yDirection=1;
ballBox.y+=ySpeed;
}
}

apply_surface(ballBox.x, ballBox.y, dot, screen);
}

Player::Player(int X, int Y) {
playerBox.x = X;
playerBox.y = Y;

playerBox.w = BOARD_WIDTH;
playerBox.h = BOARD_HEIGHT;

xVel=0;
}

void Player::handle_input() {
if (event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_LEFT: xVel -= 2; break;
case SDLK_RIGHT: xVel += 2; break;
}
} else if (event.type == SDL_KEYUP) {
switch (event.key.keysym.sym) {
case SDLK_LEFT: xVel += 2; break;
case SDLK_RIGHT: xVel -= 2; break;
}
}
}

void Player::show() {
playerBox.x+=xVel;

if ((playerBox.x<0) || (playerBox.x+BOARD_WIDTH > SCREEN_WIDTH)) {
playerBox.x-=xVel;
}

apply_surface(playerBox.x, playerBox.y, board, screen);
}

Computer::Computer(int X, int Y) {
playerBox.x = X;
playerBox.y = Y;

playerBox.w = BOARD_WIDTH;
playerBox.h = BOARD_HEIGHT;

xVel=0;
}

void Computer::show(Object *theBall) {
playerBox.x+=xVel;

// if the ball is going upwards to the right
if ((theBall->yDirection==1) && (theBall->xDirection==1)) {
if (playerBox.x + BOARD_WIDTH-(BOARD_WIDTH/2) < theBall->ballBox.x) {
xVel=2;
} else if (playerBox.x + BOARD_WIDTH-(BOARD_WIDTH/2) > theBall->ballBox.x) {
xVel=-2;
}

// if the ball goes upwards to the left
} else if ((theBall->yDirection==1) && (theBall->xDirection==0)) {
// if the player paddle's x position is greater than the balls, decrease xVel
// else if it is less than the balls x position, increase it
if (playerBox.x + (BOARD_WIDTH/2) > theBall->ballBox.x) {
xVel=-2;
} else if (playerBox.x < theBall->ballBox.x) {
xVel=2;
}
}

if (playerBox.x < theBall->ballBox.x)
xVel=2;
else
xVel=-2;



apply_surface(playerBox.x, playerBox.y, board, screen);
}

Timer::Timer() {
startTicks=0;
pausedTicks=0;
paused=false;
started=false;
}

void Timer::start() {
started=true;
paused=false;

startTicks = SDL_GetTicks();
}

void Timer::stop() {
started=false;
paused=false;
}

int Timer::get_ticks() {
if (started==true) {
if (paused==true) {
return pausedTicks;
} else {
return SDL_GetTicks() - startTicks;
}
}

return 0;
}

void Timer::pause() {
if (started==true && paused==false) {
paused=true;
pausedTicks = SDL_GetTicks() - startTicks;
}
}

void Timer::unpause() {
if (paused==true) {
paused=false;

startTicks = SDL_GetTicks() - pausedTicks;

pausedTicks=0;
}
}

bool Timer::is_started() {
return started;
}

bool Timer::is_paused() {
return paused;
}

int main(int argc, char* args[]) {
if (init()==false) {
std::cout << "Error: " << SDL_GetError() << std::endl;
}

srand(time(0));

font = TTF_OpenFont("arial.ttf", 14);

gameover = load_image("gameover.png");
board = load_image("board.png");
dot = load_image("dot.png");

Timer fps;

Computer player1(SCREEN_WIDTH-(SCREEN_WIDTH/2), 5);
Player player2(SCREEN_WIDTH-(SCREEN_WIDTH/2), SCREEN_HEIGHT-(BOARD_HEIGHT+5));

Object ball(SCREEN_WIDTH-(SCREEN_WIDTH/2), SCREEN_HEIGHT-(SCREEN_HEIGHT/2));

bool done=false;

while (!done) {
fps.start();

while (SDL_PollEvent(&event)) {
player2.handle_input();

if (event.type == SDL_QUIT) {
done=true;
}
}

SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0x00, 0x00, 0x00));

char score[64];
sprintf(score, "Computer: %d", player1Score);

p1score = TTF_RenderText_Solid(font, score, fontColor);

sprintf(score, "Player: %d", player2Score);
p2score = TTF_RenderText_Solid(font, score, fontColor);

apply_surface(5, 5, p1score, screen);
apply_surface(5, 20, p2score, screen);

if ((player1Score>=10) || (player2Score>=10)) {
apply_surface(0, 0, gameover, screen);
} else {
player1.show(&ball);
player2.show();

ball.show(&player1, &player2);
}

SDL_Flip(screen);

while (fps.get_ticks() < 1000/FRAMES_PER_SECOND) {

}
}

Shutdown();

return 0;
}
[/SOURCE]

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