C++ 分别注册按键和释放键c++;

C++ 分别注册按键和释放键c++;,c++,keypress,C++,Keypress,我正在尝试制作pong的控制台版本。我已经完成了大部分工作,但遇到了一个恼人的问题。 玩家可以通过箭头键进行控制,但当按下箭头键时,在重复之前会有一个延迟。我正在寻找一种方法,以注册时,一个键被单独按下时,它被释放,所以我可以消除这个问题 #include <ncurses.h> #define FX 101 #define FY 30 void clearmid(); void drawplayer(int playerpos); int fieldx = FX; int

我正在尝试制作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] = ' ';
                }
        }
}
#包括
#定义FX101
#定义30财年
void clearmid();
虚空抽球员(智力球员);
int fieldx=FX;
int fieldy=FY;
字符字段[FY][FX];
int main(int argc,const char*argv[]
{
initscr();
//原始();
noecho();
键盘(stdscr,真);
int i,j;
/*公平竞争环境*/
for(i=0;i!=fieldy;i++){
对于(j=0;j!=fieldx;j++){
字段[i][j]=“#”;
}
}
/*添加换行符,以便字段可以作为一个字符串打印*/
for(i=0;i!=fieldy-1;i++){
字段[i][fieldx-1]='\n';
}
字段[fieldy-1][fieldx-1]='\0';//空终止符
int player1pos,player2pos;
int ballx、bally、ballxv、ballyv;
player1pos=fieldy/2;
player2pos=player1pos;
ballx=(fieldx-1)/2;
贝利=玩家1人;
/*给定轴上的球速度*/
ballxv=1;
ballyv=1;
INTC;
超时(0);
而(1){
c=0;
c=getch();
开关(c){
案例编号:{
如果(播放机1 POS>2){
玩家1人--;
}
打破
}
案例键向下:{
如果(玩家1个玩家
控制台通常不执行此类功能。我想你可以试试ncurses。否则,您将不得不转到您最喜欢的操作系统API。

这并不容易,因为您使用的是控制台,而不是SDL之类的东西

我建议在按下键时,让代码的用户输入部分(
KEY\u UP
等)标记为布尔值
true
。然后在渲染代码中,检查此布尔值是否为真,如果为真,则相应地更新播放器位置

这样,位置会在每一帧更新,而不仅仅是在接收到用户输入时更新

如果您可以检查何时释放关键点,也就是将布尔值设置为false以停止移动播放器

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


我希望这一切都是有意义的,并为您提供了一个解决方案。

不可能使用像ncurses这样的终端API获取密钥发布事件。你可以像setterm(1)那样关闭键盘重复功能(查看源代码),但这并不保证总是有效。

由于“帧速率”是由usleep(3000)延迟控制的,因此速度不会成为问题;是的,我想完全按照你的建议去做,但我需要知道什么时候释放钥匙才能做到这一点。