views:

99

answers:

4

Hello, I am writing a small console adventure game and I faced a few problems.
1. The input is kinda laggy, I'm using while loop ( while(getch() == 'w') ). After a key is pressed the first time, nothing happens (you have to press it 2 times) and if you switch directions (press key A/D/S) it also doesn't react the 1st time. If you hold a key, it works fine. How can this be fixed?
2. Here's the function I use to refresh game (render the game scene when a key is pressed):

    void refresh(char map[Y][X])
{
    system("cls");
    for (int i = 0; i<UP; i++)
    {
        cout<<endl;
    }
    for (int i = 0; i<Y; i++)
    {
        for (int k = 0; k<LEFT; k++)
        {
            cout<<" ";
        }
        for (int j = 0; j<X; j++)
        {
            cout<<map[i][j];
        }
        cout<<endl;
    }
}

When I use this function once, it's ok, but when they key is pressed or held multiple times - the game field starts to flash. I figured that I need to redraw only a part of the field (where changes are made/movements are done), not the whole field. Can you offer any ideas how to do that?

The sample code for input:

while(getch() == 'w')
    {
        if (map[y-1][x]!= WALL)
        {
        map[y-1][x] = CHARACTER;
        map [y][x] = ' ';
        y--;
        refresh(map);
        Sleep(SPEED); // this is unnecessary, SPEED is 0, I just kept it for tests
        }
    }

Basically, the main function looks like this:

int main()
{
    (...) Variables (...)
    generateMap(FROM FILE);
    refresh(); // First initialization of the field
    while (getch() != 'q') // While not quitting
    {
    while(getch() == 'w')
    {
        if (THE FIELD ABOVE IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    while(getch() == 's')
    {
        if (THE FIELD BELOW IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    while(getch() == 'a')
    {
        if (THE FIELD ON THE LEFT IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    while(getch() == 'd')
    {
        if (THE FIELD ON THE RIGHT IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    return 0;
}
+2  A: 
  1. The code should have only one getch() in the whole code (if possible) and inside a switch you do the action for each input. So, it is switch inside the loop, and not loops inside the switch. Something like this:

    while ((ch = getch()) != 'q') { switch (ch) { case 'a': GoLeft(); break; ... } }

  2. There is a library called ncurses that you can use to move the cursor around the screen, and write anything anywhere.

Dialecticus
1. I've added the code now.2. Thank you, I'll use ncurses if there's no other alternatives, but I'd like to stick to the default libraries.
Winis
There is no default library for display drawing, as there might not be a display at all in some hardware. And I think this is not the whole relevant code. Do you have more than one getch in the code?
Dialecticus
Yup, I have 5 of them (W,A,S,D for controls and Q for quit).Should I paste the whole code? Most of the variables aren't in english, so it might be complicated to understand some of them.
Winis
In the code you posted there is a "master getch" while loop that checks if the input key is 'q'. This getch is "eating up" your first key. Change the code according to my edited answer. Unfortunately code formatting stopped working, but the code is still valid.
Dialecticus
A: 

Why do you have so many loops? I'm not fimiliar with your code style, but surely its slow because of so many loops. Cant you use IF's instead?

TAkinremi
How can an if statement be a substitute for a loop?
PigBen
That's not what I'm asking. If he is looping every frame, he should be able to use an IF statement to check a button as been pressed. EDIT: Further if he does that he can hold the buttons state on the pervious frame so if its down for two frames he knows if its being held down
TAkinremi
I don't believe C++ standard libraries allow that kind of access to the keyboard state. He'd have to use a framework like SDL.
luqui
I'm looping to check if a key is pressed and, if a key is pressed, I set some values and run the refresh function.
Winis
A: 

Don't use system("cls"), it is really slow, instead set the cursor on the beginning of the screen with the following code:

COORD cur = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cur);

You should call getch() only one time in the loop, like this:

char key;

do
{
    key = getch();

    if(key == 'w')
    {
        //do something
    }

    //the other if statements

}while(key != 'q');
Flagbug
What library do those functions come from?
luqui
@luqui Windows SDK
Dialecticus
you have to include windows.h
Flagbug
A: 

It looks like your problem is calling getch() multiple times. Have only one loop, and call getch() once per loop, and store the result. Test that result for each value (q, w, s, ...) for each iteration of the loop.

luke
Thank you! Your and flagbug's solutions worked, I'd accept both answers if it was possible.
Winis
You can still upvote ;)
luke
I can't - it requires 15 reputation :/
Winis