How do I reduce input lag in an NCurses C Application

此生再无相见时 提交于 2019-12-01 07:17:11

I believe the reason is because getch() will only release one input-character at a time (even if there are many queued up in the input stream) so if they queue up faster than you 'remove' them from the stream, the loop will continue until the queue is emptied even after you release the key. Also, you'll want to go (1000 / FRAMES_PER_SECOND) to get your desired delay-time in milliseconds (this creates 60 frames per second).

Try this in your while loop instead.

while (1)
    {
        char in;
        /* We are ready for a new frame. Keep calling getch() until we hear a keypress */
        while( (in = getch()) == ERR) {}

        if (in == 'w')
            objs[0].y -= objs[0].ySpeed * ASPECT_RATIO_Y;
        if (in == 's')
            objs[0].y += objs[0].ySpeed * ASPECT_RATIO_Y;
        if (in == 'a')
            objs[0].x -= objs[0].xSpeed * ASPECT_RATIO_X;
        if (in == 'd')
            objs[0].x += objs[0].xSpeed * ASPECT_RATIO_X;
        render(objs, 1);

        /* Clear out any other characters that have been buffered */
        while(getch() != ERR) {}

        napms(1000 / FRAMES_PER_SECOND);
    }

From the top of your loop: while( (in = getch()) == ERR) {} will call getch() rapidly until a keypress is detected. If a keypress isn't detected, getch() will return ERR. What while(getch() != ERR) {} does is keep calling getch() until all buffered input characters are removed from the queue, then getch() returns ERR and moves on. Then the loop should sleep ~17ms and repeat. These lines should force the loop to only 'count' one keypress every ~17ms, and no more often than that.

See: http://linux.die.net/man/3/getch

Ncurses does not detect key presses and key releases separately. You cannot move an object while a key is being held, and stop immediately after it is released.

The phenomenon you observe results from a ximbination of two factors: an auto-repeating keyboard, and a buffering keyboard driver. That is, the user holds a key, this generates a large amount of key events, and they are buffered by the driver and given to your application as it asks for key presses.

Neither the driver nor keyboard auto-repeat feature are under control of your application. The only thing you can hope to achieve is to process key events faster than they come out of the keyboard. If you want to do this, you have to get rid of napms in your main loop and process key presses as they come, between frame repaints. There are many ways to do that but the most straightforward is to use the timeout function.

 timeout (timeToRefresh);
 ch = getch();
 if (ch == ERR) refresh();
 else processKey(ch);

You need to calculate timeToRefresh each time using a real time clock.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!