注册按键并单独发布c ++

时间:2011-07-27 16:44:11

标签: c++ keypress

我正在尝试制作pong的控制台版本。我完成了大部分工作,但遇到了烦人的问题。 使用箭头键控制播放器,但是当它们被按下时,在重复之前会有一段延迟。我正在寻找一种方法来记录何时单独按下一个键,以便它被释放,所以我可以消除这个问题。

#include <ncurses.h>

#define FX 101
#define FY 30

void clearmid();
void drawplayer(int playerpos);


int fieldx = FX;
int fieldy = FY;
char field[FY][FX];


int main(int argc, const char *argv[])
{

        initscr();
        //raw();
        noecho();
        keypad(stdscr, TRUE);

        int i, j;
        /* Clear Playing Field */
        for(i = 0; i != fieldy; i++){
                for(j = 0; j != fieldx; j++){
                        field[i][j] = '#';
                }
        }
        /* Add in Newlines so field can be printed as one string */
        for(i = 0; i != fieldy - 1; i++){
                field[i][fieldx - 1] = '\n';
        }
        field[fieldy - 1][fieldx - 1] = '\0';   // Null terminator

        int player1pos, player2pos;
        int ballx, bally, ballxv, ballyv;
        player1pos = fieldy / 2;
        player2pos = player1pos;
        ballx = (fieldx - 1) / 2;
        bally = player1pos;

        /* Ball velocity in given axis */
        ballxv = 1;
        ballyv = 1;


        int c;
        timeout(0);
        while(1){
                c = 0;
                c = getch();
                switch(c){
                        case KEY_UP:{
                                if(player1pos > 2){
                                        player1pos--;
                                }
                                break;
                        }
                        case KEY_DOWN:{
                                if(player1pos < fieldy - 3){
                                        player1pos++;
                                }
                                break;
                        }
                        case 'q':{
                                endwin();
                                return 0;
                        }
                        default:{
                                break;
                        }
                }

                clearmid();
                drawplayer(player1pos);

                if((field[bally - 1][ballx] != ' ') || (field[bally + 1][ballx] != ' ')){
                        if(ballyv == 1) ballyv = -1;
                        else ballyv = 1;
                }
                if((field[bally][ballx - 1] != ' ') || (field[bally][ballx + 1] != ' ')){
                        if(ballxv == 1) ballxv = -1;
                        else ballxv = 1;
                }
                ballx += ballxv;
                bally += ballyv;
                field[bally][ballx] = '*';

                move(0,0);
                printw("%s", field);
                refresh();
                usleep(30000);
        }
        return 0;
}

void drawplayer(int playerpos){
        field[playerpos-1][2] = '|';
        field[playerpos][2] = '|';
        field[playerpos+1][2] = '|';
}


void clearmid(){
        int i, j;
        for(i = 1; i != fieldy -1; i++){
                for(j = 1; j != fieldx - 2; j++){
                        field[i][j] = ' ';
                }
        }
}

3 个答案:

答案 0 :(得分:2)

控制台通常不会执行此类功能。我想你可以试试ncurses。否则,您将不得不转到您喜欢的操作系统的API。

答案 1 :(得分:1)

使用像ncurses这样的终端API无法获得密钥发布事件。您可以关闭键盘,就像setterm(1)那样(查看源代码),但不保证始终有效。

答案 2 :(得分:0)

这不是太容易,因为你使用的是控制台,而不是SDL。

我建议让用户输入代码段(KEY_UP等)在按下键时标记一个布尔值true。然后在渲染代码中,检查此布尔值是否为真,如果是,则相应地更新玩家位置。

通过这种方式,每个帧都会更新位置,而不仅仅是在收到用户输入时。

如果您可以检查何时释放该键,那么当您将布尔值设置为false以停止移动播放器时。

需要注意的一点是,玩家最终可能会移动太快。如果是这种情况,那么您需要将位置更新的频率限制为每秒X次或类似的次数。这也确保那些拥有快速计算机的人不会比那些速度较慢的计算机更快地移动他们的玩家。

我希望这一切都有意义,让你有一个想法来解决问题。