0
\$\begingroup\$

i'm trying to make a two player console snake game. One of the snakes is controled by 'wasd' and other 'uhjk'. I have two function to get the keys getKEYS1() and getKEYS2(). Only difference is the expected chars.

void Snake::getKEYS1()
{
    if (_kbhit())
    {
        switch (_getch())
        {
        case 'w':
            if (dir1 != down)  // 1
                dir1 = up;
            break;
        case 'a':
            if (dir1 != right) // 3
                dir1 = left;
            break;
        case 's':
            if (dir1 != up) // 2
                dir1 = down;
            break;
        case 'd':
            if (dir1 != left)  // 4
                dir1 = right;
            break;
        case 'r':  //to kill
            dir1 = kill;
            break;
        }
    }
    return;
}

And to move the head i use the Move() function for both snakes.

void Snake::Move(Directions dir)
{

    //getKEYS1();
    //getKEYS2();

    switch (dir)
    {
    case Snake::stop:
        break;
    case Snake::up:
        headY--;
        break;
    case Snake::down:
        headY++;
        break;
    case Snake::left:
        headX--;
        break;
    case Snake::right:
        headX++;
        break;
    case Snake::kill:
        exit(0);
        break;
    default:
        break;
    }

    //adjusting & balancing speed
    if (dir == down || dir == up) Sleep(30);
    else Sleep(7.5);

    //if sneake goes out of borders
    if (headX > width - 2) headX = 1;
    else if (headX < 1) headX = width - 1;

    if (headY > height - 2) headY = 1;
    else if (headY < 1) headY = height - 1;

    //return;
}

I can print both snakes to screen but when i try to move, they move with a huge delay.

    Snake s;

    std::vector<Snake> Snakes;
    Snakes.push_back(s);
    Snakes.push_back(s);

    bo.Render(screenBuffer);  //render borders to inner buffer
    Snakes[0].Render(screenBuffer);  //render snake1 to inner buffer
    Snakes[1].Render(screenBuffer);  //render snake2 to inner buffer
    screenBuffer->RenderToScreen();  //render all to screen
    screenBuffer->Clear();  //updating the screen
    Snakes[0].getKEYS1();
    Snakes[0].Move(Snakes[0].dir1);
    Snakes[1].getKEYS2();
    Snakes[1].Move(Snakes[1].dir2);

I think i call getKEYS2() but program tries to run getKEYS1() too and that's why reaction is slow. Am i wrong? What causes this problem? And what to do to avoid it? If you need more info to understand the problem, please let me know.

I'm new to C++ so i stuck a little here. Thanks in advance.

\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

I think i call getKEYS2() but program tries to run getKEYS1() too and that's why reaction is slow. Am i wrong?

You are wrong. C++ does not randomly call a completely different function with a similar name unless you ask it to.

The problem here is your logic. In each of these methods you get a key, any key that's been pressed, but then check only if it's a particular player's input. If that key you detected was for the opposite player, it's ignored. You're counting on _kbhit and _getch to filter to only return you one player's keys, but those functions don't know anything about that.

You perceive a delay because you're leaving it up to chance which key presses you act on, based on the order they come in.

Let's say player 1 presses and holds w at the same moment player 2 presses and holds u. For whatever hardware reason, the u gets detected first, so your console input buffer this frame reads uw.

You run getKeys1() and pull the first character out of the buffer, u, then check if it's any of player 1's keys. It's not, so you don't do anything with it. Then you run getKeys2() and pull the next character out of the buffer, w, and check if it's any of player 2's keys. It's not, so this input is also unhandled.

If the players keep holding the keys, the console will read uwuwuwuwuw with new characters getting added at the configured key repeat rate. So this pattern will repeat every frame until one player lets go of a key.

Player 2's input will only ever be correctly handled on frames where you're lucky enough that player 1 also pressed a key and it was added to the buffer before player 2's.

So, you need to rethink the way you're handling this input. Read the input buffer in a loop, and check the resulting character against both players' keys. That way, the input gets handled correctly no matter how many keys were pressed this frame, or the order they were detected and stored.

\$\endgroup\$

You must log in to answer this question.

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