0
\$\begingroup\$

I'm making an Ultima spinoff which requires a lot of key strokes for actions. For example the arrow keys are for movement BUT once the player presses down the 'T' (talk) key the arrow keys are used for determining which NPC to talk to.

In summary, 'T' + arrow keys is the combination to initiate conversion with NPCs, and arrow keys alone are for movement. Right now I'm using a flag isInConversation whenever 'T' has been pressed, but this looks silly and can quickly increases the number of flags once other functionalities go online.

What do you think? Is a state machine a better option?

Here is the code:

        while (SDL_PollEvent(&e) != 0)
        {
            //User requests quit
            if (e.type == SDL_QUIT)
            {
                quit = true;
            }
            else if (e.type == SDL_KEYDOWN)
            {
                //Select surfaces based on key press
                switch (e.key.keysym.sym)
                {
                case SDLK_UP:
                    if (isInConversation) { // check NPCs in north direction }
                    else if (ai.canMoveDirection(&playerEntity, NORTH, currentMap)) {
                        updatePlayer(NORTH);
                        scroll(NORTH);
                    }
                    break;
                case SDLK_DOWN:
                    if (isInConversation) { // check NPCs in south direction }
                    else if (ai.canMoveDirection(&playerEntity, SOUTH, currentMap)) {
                        updatePlayer(SOUTH);
                        scroll(SOUTH);
                    }
                    break;
                case SDLK_LEFT:
                    if (isInConversation) { // check NPCs in west direction }
                    else if (ai.canMoveDirection(&playerEntity, WEST, currentMap)) {
                        updatePlayer(WEST);
                        scroll(WEST);
                    }
                    break;
                case SDLK_RIGHT:
                    if (isInConversation) { // check NPCs in east direction }
                    else if (ai.canMoveDirection(&playerEntity, EAST, currentMap)) {
                        updatePlayer(EAST);
                        scroll(EAST);
                    }
                    break;
                case SDLK_ESCAPE:
                    quit = true;
                    break;
                case SDLK_e:
                    // trigger map change
                    changeMap();
                    break;
                case SDLK_t:
                    // talk, should set keystate to ENTER_TALK
                    // So expecting an arrow key afterwards
                    inConversationState = true;
                default:
                    break;
                }
                // Each key down triggers npc movement
                for (auto n : currentMap->getNPC()) {
                    ai.moveRandomly(n, currentMap);
                }
            }
        }
\$\endgroup\$
3
  • 2
    \$\begingroup\$ It sounds like you already have an idea of a way you could improve this solution: using a state variable instead of multiple flags. Have you tried out that approach to see if you like it better? \$\endgroup\$
    – DMGregory
    Commented Feb 20, 2023 at 2:07
  • \$\begingroup\$ Thanks @DMGregory yeah gonna try it out if nothing else is recommended. I'm actually pretty new to state machine so will read some tutorials first. My only experience with state machine was when I studied parsing. \$\endgroup\$ Commented Feb 20, 2023 at 2:19
  • 1
    \$\begingroup\$ It doesn't have to be a huge engineering commitment. Even just an enum variable storing the current input mode that you can use in a switch statement would probably be plenty. \$\endgroup\$
    – DMGregory
    Commented Feb 20, 2023 at 3:30

1 Answer 1

1
\$\begingroup\$

This way is works, but in case you need more key strokes(like 3 or more keys pressed) this code are going to be more complicated. I suggest you to redesign your code to first detect events and then after that, update your game. You are doing both at the same time.

Simple example:

bool tPressed = false;
bool upPressed = false;

while(SDL_PollEvent(&event)) { //NOTE THIS CAN be runned more than one time at a game loop
//HANDLE t and up variables here
}

//NOTE Now all of your events are been handled, you can update your.
if(tPressed && upPressed) {
//Do the doings case both key are pressed
}

This design is pretty common to handle multiple keys pressed and also presented by official SDL documentation in this link: https://www.libsdl.org/release/SDL-1.2.15/docs/html/guideinputkeyboard.html

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .