2011-07-27 5 views
2

콘솔 버전의 pong을 만들려고합니다. 나는 대부분의 일을 끝내었지만 성가신 문제에 부딪쳤다. 플레이어는 화살표 키로 제어되지만, 길게 누르면 반복되기 전에 지연됩니다. 키를 놓을 때 키를 누를 때 등록 방법을 찾고 있으므로이 문제를 없앨 수 있습니다.키 누름을 별도로 등록하십시오. C++

#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] = ' '; 
       } 
     } 
} 

답변

2

콘솔은 일반적으로 이러한 기능을 수행하지 않습니다. 너는 ncurses를 시도 할 수 있었다. 그렇지 않으면 좋아하는 운영 체제의 API로 이동해야합니다.

+1

그의 코드는 이미 ncurses를 사용합니다. –

0

SDL과 같이 콘솔을 사용하고 있기 때문에 너무 쉽지 않습니다.

키를 누를 때 코드 (KEY_UP 등)의 사용자 입력 섹션에 부울을 표시하는 것이 좋습니다 (true). 그런 다음 렌더링 코드에서이 부울이 참인지 확인한 다음 적절하면 플레이어 위치를 업데이트하십시오.

이렇게하면 사용자 입력이 수신 될 때가 아니라 모든 프레임마다 위치가 업데이트됩니다.

키를 놓을 때 확인할 수있는 경우, 부울을 false로 설정하여 플레이어 이동을 중지 할 때입니다.

조심해야 할 것은 플레이어가 너무 빨리 움직이는 것입니다. 이 경우 위치가 초당 X 회 또는 비슷한 수로 업데이트되는 빈도를 제한해야합니다. 또한 빠른 컴퓨터를 사용하는 플레이어가 느린 컴퓨터를 사용하는 플레이어보다 빠르게 플레이어를 이동시키지 않도록합니다.

이 모든 것이 의미가 있고 효과가 있다고 생각합니다.

+0

"프레임 속도"가 usleep (3000)으로 지연하여 제어되기 때문에 속도가 문제가되지 않습니다. 그리고 네, 당신이 제안한 것과 똑같이하기를 원하지만, 그렇게하기 위해 키가 공개 될 때를 알 수 있어야합니다. – wheybags

1

ncurses와 같은 터미널 API로 키 릴리스 이벤트를받을 가능성은 없습니다. setterm (1)이하는 것처럼 키보드 반복을 끌 수 있습니다 (소스보기). 그러나 항상 작동하는 것은 아닙니다.

관련 문제