[SDL2] A (yet another) simple Pong clone to review

Started by
15 comments, last by adrian17 10 years, 10 months ago

I've seen the video, went through your code a bunch of times, checked the SDL documentation, and i still can't explain why it happens...

By the way, the examples above are basically what MIX_FreeChunk() does, and the reason why the 2nd might crash the game, if because is "point->allocated" isn't 1, then it doesn't contain the audio buffer and the "point->abuf" shouldn't be deleted.

Sorry, but i can't really help anymore.

Thanks anyway. I guess the only thing left for me right now is asking at the SDL Forums.

Advertisement


The only thing I really don't like is how I had to divide paddle's input functions to InputRight() and InputLeft(), but I didn't know any other good way of doing this (aside from making subclasses for left and right paddle, which didn't seem worth the effort to me).

A simple way to solve this would be to pass the SDLKey values that are being listened for to the Paddle constructor:

int leftX = /* ... */;
int rightX = /* ... */;
 
Paddle left(leftX, SDLK_w, SDLK_s);
Paddle right(rightX, SDLK_UP, SDLK_DOWN);

However, another way to think about this is that the paddle is too "low level" to be worrying about this. It shouldn't need to care whether it is controlled by keyboard, or maybe by tilt for a mobile device, responding to incoming packets from a remote network player or even by the output of some A.I. decision logic.

We can do this by exposing a Paddle interface that can be "bound" to any of the above:

class Paddle
{
public:
    void MoveUp();
    void MoveDown();
    void StopMoving();
 
    // ...
};

Now, the higher level code can be responsible for dispatching input events into game logic:


while(SDL_PollEvent(&event))
{
    if( event.type == SDL_KEYDOWN )
    {
        SDLKey key = event.key.keysym.sym;
        if(key == SDLK_UP)
        {
            leftPaddle->MoveUp();
        }
        else if(key == SDLK_DOWN)
        {
            leftPaddle->MoveDown();
        }
        else if(key == SDLK_w)
        {
            rightPaddle->MoveUp();
        }
        else if(key == SDLK_s)
        {
            rightPaddle->MoveDown();
        }
    }
    else if(event.type == SDL_KEYUP)
    {
        SDLKey key = event.key.keysym.sym;
        if(key == SDLK_UP || key == SDLK_DOWN)
        {
            leftPaddle->StopMoving();
        }
        else if(key == SDLK_w || key == SDLK_s)
        {
            rightPaddle->StopMoving();
        }
    }
}

A simple way to solve this would be to pass the SDLKey values that are being listened for to the Paddle constructor:


int leftX = /* ... */;
int rightX = /* ... */;
 
Paddle left(leftX, SDLK_w, SDLK_s);
Paddle right(rightX, SDLK_UP, SDLK_DOWN);

That sounds good, although with my current setup I can't make it work - I can pass SDLK values to the constructor, but the problem arises then I try to use it in the case statement - because case needs constant values to work with. It doesn't want to compile even when I define key values as const int.


void Paddle::InputLeft()
{
    if( event.type == SDL_KEYDOWN )
    {
        switch( event.key.keysym.sym)
       {
            case keyUp:       {vy =- basev; up=1;} break; //error: "this" it not a constant expression
            case keyDown:     {vy = basev; down=1;} break;
            default: ;
       }
    }
    if( event.type == SDL_KEYUP )
    {
        switch( event.key.keysym.sym )
        {
            case keyUp:       {up=0; if(down==1) vy=basev; else vy = 0;} break;
            case keyDown:     {down=0; if(up==1) vy=-basev; else vy = 0;}; break;
            default: ;
        }
    }
}

(by the way, the above code shows why I don't think that the second approach you've shown would work with my current setup - in your code the paddle would stop moving as soon as any key release is detected - it would work fine until a player presses both keys at the same time and releases only one of them. That's why I've added the extra "if(down==1)" statements. )

I will think about this more, but I have some stranger issues right now, like SDL_SetTextureAlphaMod stopping working after toggling fullscreen/window and problems with detecting special keys (for some reason, shift key gets detected with a second of lag and its release isn't detected at all).


That sounds good, although with my current setup I can't make it work - I can pass SDLK values to the constructor, but the problem arises then I try to use it in the case statement - because case needs constant values to work with. It doesn't want to compile even when I define key values as const int.

Don't use "switch" in that case, use "if/else". Note that "const" is different from a compile time constant, which is what switch/case reqyures.


(by the way, the above code shows why I don't think that the second approach you've shown would work with my current setup - in your code the paddle would stop moving as soon as any key release is detected - it would work fine until a player presses both keys at the same time and releases only one of them. That's why I've added the extra "if(down==1)" statements. )

It is perfectly possible to handle this too, I gave a very simple interface and implementation in my example.

Okay, thanks. It looks really nice, actually. I've used your example and moved all in-game input handling directly to Game::HandleEvents.Right now it's in a side branch Here.

Unfortunately, I'm still having problems with scanning keymods. It's definitely my fault, but I don't know how to implement this properly. Right now my experiments looks like this:


    while(SDL_PollEvent(&event))
    {
        SDLsystem->Input();
        if( event.type == SDL_KEYDOWN )
        {
            if(event.key.keysym.mod == SDLK_LALT) {SDL_SetWindowTitle(window, "alt down");}
            SDL_Keycode key=event.key.keysym.sym;
            if(key == SDLK_ESCAPE )
                {nextState = State::MAINMENU;}
            //checking normal keys
        }
        else if(event.type == SDL_KEYUP)
        {
            if(event.key.keysym.mod == SDLK_LALT) {SDL_SetWindowTitle(window, "alt up");}
            SDL_Keycode key = event.key.keysym.sym;
            //checking normal keys
        }
    }

And the key isn't detected at all.

If I change the operator in the statement to & (like shown in some code examples):


if(event.key.keysym.mod & SDLK_LALT) 

It detects Shift (?) being pushed and released but only when Ctrl is pushed at the same time (??). Something very similar happens if i try to detect the Shift key.

How am I supposed to do it? It works properly when I try to check if Alt and Enter are pushed together, but not when I'm checking for Alt alone.

What are you trying to check? If you just want to check if someone pressed an ALT key, use event.key.keysym.sym == SDLK_LALT. If you want to check if the ALT key is being held while another key is pressed, use event.key.keysym.sym == SDLK_WHATEVER && (event.key.keysym.mod & KMOD_LALT).

Oh, I see... I was convinced that the only way to check the special keys was was by using event.key.keysym.mod, I didn't even try scanning it as any other key. Thanks a lot!

This topic is closed to new replies.

Advertisement