Key event problem after collision detection

I’m just getting started with some basic game programming using SDL. Right now I’m working on a primitive 2D football game. The player moves the ball around using the arrow keys to get the ball into the endzone. I’m trying to add obstacles, which is currently just a box on the field. The collision detection between the ball and this box is working properly, but the problem lies right after they collide. I have a function which upon detection of collision, resets the ball to its starting position and velocity(0). However what happens is the ball is reset to that position, but immediately starts moving in the opposite direction from the direction it was moving when it collided with the box.

My thoughts are that something is getting stuck in the event queue, as this issue happens when an arrow key is held down and the ball hits the box. The weird thing though is that it’s the opposite arrow key that seems to be ‘virtually stuck’ after the reset. I’ve tried moving my reset function around in the code as well as throwing in a temporary ignore to the key press. Anyway, any and all help would be greatly appreciated. I’ll copy some of my code below(sorry its messy) that I think might be helpful in identifying the problem. If anyone needs to see more of it, just let me know…Thanks in advance!!!

Here is part of the main loop where the issue happens:
fps.start();
while( SDL_PollEvent( &event ) )
{
ball.handle_input();//moves the ball according to key presses

            if( event.type == SDL_QUIT )
            {quit = true;}
        }
        ball.move();
        if (ball.boxcollide()){
           SDL_EventState(SDL_KEYDOWN, SDL_IGNORE);
           ball.reset();
           SDL_EventState(SDL_KEYDOWN, SDL_ENABLE);
}
        SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) );
        apply_surface( 0,0, field, screen );
        ball.endzoneright();
        ball.endzoneleft();
        ball.showball();
        ball.showbox();

Here is the reset function that causes the problem(I think, because it happens whenever this function gets called in the above loop)
void Ball::reset(){
fball.x = 360 - (BALL_WIDTH / 2);
fball.y = 160 - (BALL_HEIGHT / 2);
fball.w = BALL_WIDTH;
fball.h = BALL_HEIGHT;
xVel = 0;
yVel = 0;
}

Here are the handle events and move functions since the problem might lie in here:

void Ball::handle_input(){
    if( event.type == SDL_KEYDOWN ){
        switch( event.key.keysym.sym ){
            case SDLK_UP: yVel -= BALL_HEIGHT / 2; break;
            case SDLK_DOWN: yVel += BALL_HEIGHT / 2; break;
            case SDLK_LEFT: xVel -= BALL_WIDTH / 2; break;
            case SDLK_RIGHT: xVel += BALL_WIDTH / 2; break;
        }
    }
    else if( event.type == SDL_KEYUP ){
        switch( event.key.keysym.sym ){
            case SDLK_UP: yVel += BALL_HEIGHT / 2; break;
            case SDLK_DOWN: yVel -= BALL_HEIGHT / 2; break;
            case SDLK_LEFT: xVel += BALL_WIDTH / 2; break;
            case SDLK_RIGHT: xVel -= BALL_WIDTH / 2; break;
        }
    }
}

     
     
void Ball::move(){
    fball.x += xVel;
    if( ( fball.x < 0 ) || ( fball.x + BALL_WIDTH > SCREEN_WIDTH ) )
    {fball.x -= xVel;}
    
    fball.y += yVel;
    if( ( fball.y < 0 ) || ( fball.y + BALL_HEIGHT > SCREEN_HEIGHT ) ) 
    {fball.y -= yVel;}
    
}

Once again, thanks in advance for any help you guys can offer. I know this code has some weird naming conventions so feel free to ask me to explain what stuff is if needed or if you need to see more of the code.

I’m just getting started with some basic game programming using SDL. Right now I’m working on a primitive 2D football game. The player moves the ball around using the arrow keys to get the ball into the endzone. I’m trying to add obstacles, which is currently just a box on the field. The collision detection between the ball and this box is working properly, but the problem lies right after they collide. I have a function which upon detection of collision, resets the ball to its starting position and velocity(0). However what happens is the ball is reset to that position, but immediately starts moving in the opposite direction from the direction it was moving when it collided with the box.

My thoughts are that something is getting stuck in the event queue, as this issue happens when an arrow key is held down and the ball hits the box. The weird thing though is that it’s the opposite arrow key that seems to be ‘virtually stuck’ after the reset. I’ve tried moving my reset function around in the code as well as throwing in a temporary ignore to the key press. Anyway, any and all help would be greatly appreciated. I’ll copy some of my code below(sorry its messy) that I think might be helpful in identifying the problem. If anyone needs to see more of it, just let me know…Thanks in advance!!!

Here is part of the main loop where the issue happens:
fps.start();
while( SDL_PollEvent( &event ) )
{
ball.handle_input();//moves the ball according to key presses

            if( event.type == SDL_QUIT )
            {quit = true;}
        }
        ball.move();
        if (ball.boxcollide()){
           SDL_EventState(SDL_KEYDOWN, SDL_IGNORE);
           ball.reset();
           SDL_EventState(SDL_KEYDOWN, SDL_ENABLE);
}
        SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) );
        apply_surface( 0,0, field, screen );
        ball.endzoneright();
        ball.endzoneleft();
        ball.showball();
        ball.showbox();

Here is the reset function that causes the problem(I think, because it happens whenever this function gets called in the above loop)
void Ball::reset(){
fball.x = 360 - (BALL_WIDTH / 2);
fball.y = 160 - (BALL_HEIGHT / 2);
fball.w = BALL_WIDTH;
fball.h = BALL_HEIGHT;
xVel = 0;
yVel = 0;
}

Here are the handle events and move functions since the problem might lie in here:

void Ball::handle_input(){
    if( event.type == SDL_KEYDOWN ){
        switch( event.key.keysym.sym ){
            case SDLK_UP: yVel -= BALL_HEIGHT / 2; break;
            case SDLK_DOWN: yVel += BALL_HEIGHT / 2; break;
            case SDLK_LEFT: xVel -= BALL_WIDTH / 2; break;
            case SDLK_RIGHT: xVel += BALL_WIDTH / 2; break;
        }
    }
    else if( event.type == SDL_KEYUP ){
        switch( event.key.keysym.sym ){
            case SDLK_UP: yVel += BALL_HEIGHT / 2; break;
            case SDLK_DOWN: yVel -= BALL_HEIGHT / 2; break;
            case SDLK_LEFT: xVel += BALL_WIDTH / 2; break;
            case SDLK_RIGHT: xVel -= BALL_WIDTH / 2; break;
        }
    }
}

     
     
void Ball::move(){
    fball.x += xVel;
    if( ( fball.x < 0 ) || ( fball.x + BALL_WIDTH > SCREEN_WIDTH ) )
    {fball.x -= xVel;}
    
    fball.y += yVel;
    if( ( fball.y < 0 ) || ( fball.y + BALL_HEIGHT > SCREEN_HEIGHT ) ) 
    {fball.y -= yVel;}
    
}

Once again, thanks in advance for any help you guys can offer. I know this code has some weird naming conventions so feel free to ask me to explain what stuff is if needed or if you need to see more of the code.

if I am reading this right
vVel = 0
UP: KEY_DOWN) vVel -= BALL_HEIGHT / 2 (eg, 32 / 2 = 16)
// vVel now equals -16
UP: KEY_UP) vVel += BALL_HEIGHT / 2 (eg, 32 / 2 = 16)
// vVel now equals 0 (-16 + 16 = 0)
UP: KEY_DOWN) vVel -= BALL_HEIGHT / 2 (eg, 32 / 2 = 16)
// vVel now equals -16

Then it colides and gets reset to 0
vVel = 0
// UP is still in KEY_DOWN
UP: KEY_UP) vVel += BALL_HEIGHT / 2 (eg, 32 / 2 = 16)
// vVel now equals 16
UP: KEY_DOWN) vVel -= BALL_HEIGHT / 2 (eg, 32 / 2 = 16)
// vVel now equals 0 (16 + -16 = 0)

So the ball is moving up, then it resets and then moves down.

As for a solution, there was an SDL tutorial I had read that said you really shouldn’t bind movement to key events, perhaps for this exact reason. Rather, you use flags.
in the Input function:
UP: KEY_DOWN) Ball.GoUp = 1
UP: KEY_UP) Ball.GoUp = 0

In the Update function:
if (Ball.GoUp == 1)
Ball.y -= BALL_HEIGHT / 2

Give it a shot and see if that works.
I hope it helps.

I didn’t see ball_move get called so I’m not sure what’s up. It’s hard for me to follow the logic path here. I suspect it is for you as well. I would design a flow of logic with well named variables that break down the work into easily understood parts like:
/////////////////
//includes
//defines
//variables
//load stuff
//init stuff

//start game loop////////////////
//events

[poll events code]
//state machine
[state code]>running blocking attacking current_target
//move objects
[motion code]>direction speed acceleration mass
//draw objects
[draw code]>action_type amination_set animation_frame frame_speed
//show screen
[update screen code]
//end game loop/////////////////

//clean up
//exit
/////////////////
You can make it cleaner and smaller later, but for now lots of small parts organized by basic parts should help. Variables that help each part know what to do and how to do it are the life blood of the code. Im used to seeing much more blood. That sounded wrong… anyway I hope this helps. I’d google “C++ state machine motion example” for examples.