Jump to content
  • Advertisement
Sign in to follow this  
eektor

Need help with my Pong game

This topic is 4858 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone, I'm working with C++ and SDL to make my pong game. I have a first version of a pong game that works alright. Its just two paddles and a ball that moves back and forth. I tried to make a second version that's more modular. I was working with a SDL graphics, Input, Sprite, and Timer classes to set up a better pong game. I'm running into problems and would like someone with more experience to take a look and give me some advice. I think its kind of long to put the source here, so if you would like to help send me a pm with your e-mail address and I can send it to you. My main concern (for now, there's lots more I need to do) is that the user controlled paddle is not moving very smoothly. Also, I know I haven't put in the computer movement yet, but I wanted to take care of the user controlled paddle first. Thanks!

Share this post


Link to post
Share on other sites
Advertisement
Ok, I think I'll post the main and the HandleKeyboardInput, because I think the problem is somewhere in the order I put things.

void HandleKeyboardInput();

// Global Variables
bool g_quit = false;
SDL_Graphics* g_graphics = NULL;
SDL_Input* g_input = NULL;
Timer* g_timer = NULL;
Sprite* g_paddle1 = NULL;
Sprite* g_paddle2 = NULL;
Sprite* g_ball = NULL;

int main( int argc, char* args[] )
{
g_graphics = new SDL_Graphics(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,
WINDOW_TITLE, BACKGROUND_RED, BACKGROUND_GREEN, BACKGROUND_BLUE);

g_input = new SDL_Input();

g_paddle1 = new Sprite(g_graphics,0,0,20,100,255,255,255,"paddle.bmp",10.0,710,375);
g_paddle2 = new Sprite(g_graphics,0,0,20,100,255,255,255,"paddle.bmp",10.0,20,375);
g_ball = new Sprite(g_graphics,0,0,20,20,255,255,255,"ball.bmp",10.0,375,375,1.0,1.0);
g_timer = new Timer();

// While the user hasn't quit
while(g_quit == false)
{
g_timer->start();

g_input->readInput();

if (g_input->windowClosed())
{
g_quit = true;
}

// Get user input and move human paddle
HandleKeyboardInput();

// Check for any collision with paddles and bounce the ball accordingly
if(g_ball->checkCollision(g_paddle1) | g_ball->checkCollision(g_paddle2))
{
g_ball->changeVelocity(-(g_ball->get_Vx()),g_ball->get_Vy());
}

// Check for any collision with vertical walls and bounce the ball accordingly
if(g_ball->get_ypos() <= 0 | g_ball->get_ypos() >= SCREEN_HEIGHT)
{
g_ball->changeVelocity(-1,1);
}

g_ball->update(g_timer->get_ticks());
g_paddle1->update(g_timer->get_ticks());
g_paddle2->update(g_timer->get_ticks());

g_graphics->beginScene();

g_ball->draw();
g_paddle1->draw();
g_paddle2->draw();

g_graphics->endScene();

g_timer->stop();
}

delete g_timer;
delete g_ball;
delete g_paddle1;
delete g_paddle2;
delete g_input;
delete g_graphics;

return 0;
}

void HandleKeyboardInput()
{
bool* keysHeld = g_input->getInput();

if (keysHeld[SDLK_ESCAPE])
{
g_quit = true;
}

if (keysHeld[SDLK_UP])
{
g_paddle1->moveUp();
}
else if (keysHeld[SDLK_DOWN])
{
g_paddle1->moveDown();
}
else
{
// If neither arrow key is being held, the doom guy isn't moving.
g_paddle1->stopMoving();
}
}


Share this post


Link to post
Share on other sites
One of the problems is that you're using the bitwise OR operator | rather than the conditional OR operator ||.

For example, the line
if(g_ball->checkCollision(g_paddle1) | g_ball->checkCollision(g_paddle2))
should look like this:
if(g_ball->checkCollision(g_paddle1) || g_ball->checkCollision(g_paddle2))

Share this post


Link to post
Share on other sites
Hard to tell from what I see here, but is the timer object handling the loop speed? Usually I'll put in Sleep(35) in my game loop to conrol that. If the keyboard input seems choppy, perhaps it has something to do with the timer? Then again, I'm not too familiar with the library you're using, but you might check out what's going on in the beginScene() and draw() functions.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
We can help, but not from the above code. I like how you did OOP, but in that way we won't know what the functions do. Know what I mean? Like:

// This may be good, yet since you aren't showing us it might be bad.
input->read();



Post this code:

g_input->getInput();


And also, the timer code may be good to post. Just in case:
1) I suggest reading input from SDL_GetKeyState(NULL);. Like this:

// at the beginning
Uint8 *pKeys;

pKeys = SDL_GetKeyState(NULL);

// reading
if (pKeys[SDLK_ESCAPE])
break; // just and example!

// and at the end of your loop
SDL_PumpEvents();



2) Make sure your timer isn't too slow. Timers like these:

int start_point; // or delta or something

while (1) // forever
{
start_point = static_cast<int>(SDL_GetTicks()); // get the beginning

//...

// while the loop isn't long enough
// I'm not sure about the 1000 / FPS part, but I'm sure you can use a
// thousand. Remember, SDL_GetTicks() returns in milliseconds
while (static_cast<int>(SDL_GetTicks()) - start_point < 1000 / FPS)
;
}


May cause slowdowns, depending on what you do.

Good luck.

C++

Share this post


Link to post
Share on other sites
Ok first of all

@nsto119 Thank you for pointing that out. I think you might have saved me 2 hours trying to figure out why that was wrong :)

@vinb The timer class is just like a stop watch. It just tells me the ticks from when I started to when I get_ticks. It has a pause function too. I was going to put a cap frame rate later on, but I was trying to make the game update based on the time that has passed.

Oh that might be it in Sprite::update I did this


void Sprite::update(float deltaTime)
{
// This needs to be changed so the value is rounded
m_x += (int)(m_Vx * deltaTime);
m_y += (int)(m_Vy * deltaTime);
}



Is there a way I can round it into an int value?

@Anonymous Poster
Here's my SDL_Input::getInput and SDL_Input::readInput


void SDL_Input::readInput()
{
if (SDL_PollEvent(&m_event))
{
if (m_event.type == SDL_QUIT)
{
m_windowClosed = true;
}

if (m_event.type == SDL_KEYDOWN)
{
m_keysHeld[m_event.key.keysym.sym] = true;
}

if (m_event.type == SDL_KEYUP)
{
m_keysHeld[m_event.key.keysym.sym] = false;
}
}
}

bool* SDL_Input::getInput()
{
return m_keysHeld;
}



Thanks for all the replies too!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by eektor
Ok first of all

@nsto119 Thank you for pointing that out. I think you might have saved me 2 hours trying to figure out why that was wrong :)

@vinb The timer class is just like a stop watch. It just tells me the ticks from when I started to when I get_ticks. It has a pause function too. I was going to put a cap frame rate later on, but I was trying to make the game update based on the time that has passed.

Oh that might be it in Sprite::update I did this

*** Source Snippet Removed ***

Is there a way I can round it into an int value?

@Anonymous Poster
Here's my SDL_Input::getInput and SDL_Input::readInput

*** Source Snippet Removed ***

Thanks for all the replies too!


Gotcha...

Well, I think it might be from the bool. I tried that once and the input messed up. I don't know why, it just does. Try something like this:

// your class
class input
{
public:
bool GetKey(int numKey);

// whatever you have
};

bool input::GetKey(int numKey)
{
return (SDL_GetKeyState(NULL)[numKey]);
}


You can also use a variable, but theres no need for it. Something like this:

private:
Uint8 *m_pKeys;

public:
void Update();

// later on

bool input::GetKey(int numKey)
{
return (m_pKeys[numKey]);
}

void input::Update()
{
m_pKeys = SDL_GetKeyState(NULL);
}



Good luck!

C++

Share this post


Link to post
Share on other sites
Just to make sure I understand you. If I do what you did the first time, each time I use getInput (or in your case getKey) I would have to use a for loop and run it 323 times to fill up the array?

So in my HandleKeyboardInput function, I would have to do

bool* keysHeld;

for (int i=0;i<323;i++)
{
keysHeld = g_input->getInput(i);
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by eektor
Just to make sure I understand you. If I do what you did the first time, each time I use getInput (or in your case getKey) I would have to use a for loop and run it 323 times to fill up the array?

So in my HandleKeyboardInput function, I would have to do

bool* keysHeld;

for (int i=0;i<323;i++)
{
keysHeld = g_input->getInput(i);
}


Oh, no no no.

It's much, much simpler. All you do is (for example):

input myIn; // or whatever

if (myIn.GetKey(SDLK_ESCAPE)) // or whatever
; // something



Oh, I forgot to add something. At the end of your main loop make sure you add:

//main loop end:
SDL_PumpEvents();

This makes sure everything is up-to-date.

When you declare and 'input' you can just use GetKey(SOME_KEY_THAT_YOU_WOULD_NORMALLY_WANT) and be over with it. No messing with anything.

-Good luck!-

C++

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!