티스토리 뷰

안녕하세요



이번 강좌에서는 지난시간에 이어 메뉴를 선택하는 기능을 구현해보도록 하겠습니다.




[목차]


1. 키보드 입력키 선정하기


2. 선정한 키값을 정의하기


3. 키보드 이벤트 처리하기


4. 메뉴 선택기능 구현하기






[1 키보드 입력키 선정하기]



게임 내 또는, 메뉴에서 사용할 키보드의 키를 미리 정의하기 위해서는

어떤키를 선택할지 고민해야합니다.


FPS게임은 주로 이동할 때 w, a, s, d 키를 사용합니다.



이와같이 내가 개발할 콘솔게임에서 어떤 키를 사용할지 정하는것도 꽤 중요합니다.



저는 탈출게임을 목표로 진행하고있기때문에


상하좌우를 이동하기위해 w, a, s, d 키로 정하도록 하겠습니다.


기타 키값으로는 게임을 종료할 땐 q를 사용하도록 하겠습니다.






[2 선정한 키값 정의하기]



선정한 키보드 값을 그대로 사용해도 무방하지만, 알기쉽게 정의해두면 추후에 유지보수 차원에서도 훨씬 좋습니다.




#define은 전처리기 중 정의하는 매크로인데요


#define 이름

형식으로 작성하시면 됩니다.


if(UP == 0) 이라고 작성된 조건문이 있다면 결과는 참이됩니다.


컴파일시, 이름으로 사용한것들은 정의된 값으로 동일하게 적용됩니다.

예) UP + DOWN; 라고 한다면 컴파일시에 0 + 1 로 변경됩니다.


위와같이 #define으로 정의해두면 UP이라는 이름을 통해 어떤 값인지 쉽게 판별할 수 있기때문에 사용하는것도 좋습니다.




저는 위로가는 키를 0, 아래는 1, 왼쪽 오른쪽은 2, 3으로 정의하였습니다.





[3 키보드 이벤트 처리하기]




키보드이벤트란? 처음 듣는분들도 계실거라 생각합니다.

말은 생소하지만 우리들은 컴퓨터를 사용하면서 매일매일 사용하고 있습니다.


키보드가 눌렸을 때를 이벤트라고 합니다. 어떠한 행위를 하면 그게 이벤트입니다.

키보드가 눌릴때마다 이벤트가 발생하는것이죠



메모장을 실행하고 키보드를 누르면 누른 키보드에 대한 글자가 작성됩니다. 이것이 바로 키보드이벤트입니다.

키보드이벤트는 프로그램마다 다를 수 있습니다.



게임같은 종류는 키보드를 누르면 스킬을 사용하거나 이동하지만, 워드와 같이 문서작성 프로그램에서는 글자가 표시되죠.



키보드이벤트에 대해서는 간단히 설명하고 본론으로 넘어오도록 하겠습니다.




콘솔게임은 대부분 키보드로만 조작합니다(마우스 이벤트도 있지만 비효율적)

키보드가 눌렸을 때 위에서 정의한 키값을 전달해주도록 하는 함수를 하나 구현할것입니다.



키보드이벤트 관련기능도 매우 자주 사용되므로

따로 함수로 구현하도록 하겠습니다.


w(또는 대문자 W)가 입력되면 UP 이라는 값을 반환하고

a(또는 대문자 A)가 입력되면 LEFT라는 값을 반환하는 함수를 구현해보도록 하겠습니다.

(s, d 키 포함)


getch 함수는 엔터를 입력하지 않아도 키가 눌리면 바로 반환해주는 입력함수입니다.


scanf나 cin으로 입력을 받을땐 글자를 입력하고 엔터를 눌러야 입력이 되지만,

getch는 a키를 누르면 화면에 보여주지않고 바로 반환해버립니다.


29번 행에는 temp = getch() 라고 되어있습니다.

키가 입력되면 바로 temp 변수에 임시로 값을 저장하고


아래의 if문에서 입력된 값이 w, a, s, d (대문자 포함)인지 확인하는 모습입니다.

해당하는 문자가 맞으면 그에 대응하는 UP, DOWN, LEFT, RIGHT의 값을 반환하는 모습입니다.


w를 누르면 UP(0) 이 반환될것이고

d를 누르면 RIGHT(3) 이 반환될 것입니다.


테스트를 위해 22, 23번줄에 간단한 코드를 작성하였습니다.


keyControl이 키를 눌렀을 때 키값을 반환해주는 함수입니다.

그 아래에서는 반환된 키값을 출력하는 모습입니다.



d키를 누르니 3이 입력됬다고 정상적으로 나옵니다.



이제 키보드 이벤트가 발생하면 알맞는 키값을 반환할 수 있게되었으니 

중요기능들이 거의 구현되어가고있습니다.






[4 메뉴 선택기능 구현하기]



게임시작

게임정보

종료


이 세가지 메뉴를 이전 강좌에서 출력해보았습니다.


하지만 보이기만할뿐 움직이지도, 선택할수도 없는데요.



오늘의 4챕터에서 선택할 수 있는 기능을 구현해보도록 하겠습니다.






이동뿐만아니라 선택을 위한 키를 정의합니다. (9행)

15행의 메뉴출력 함수의 반환형을 void -> int로 변경해줍니다.

keyControl 함수 내에 스페이스바 입력에 대한 부분도 추가해줍니다. (37~39)







아래에서는 menuDraw 부분의 반환형을 선언한 부분과 일치하게 int형으로 변경해줍니다.


57~58, 65~93행은 새로 추가된 소스코드입니다.


65행의 무한 반복은 키보드입력을 무한정 받고 기다리고 하는 부분입니다.

계속 가만히있는게 아니라 스페이스바(위의 SUBMIT 코드)가 입력되면 return 하여 루프와 함수를 빠져나갑니다.


66행의 int n 은 키보드의 키코드를 임시로 저장하는 변수입니다.

키코드를 저장하였으면 67행의 switch 문에서 해당하는 키코드의 동작을 실행하죠


만약 입력된 키가 UP이면 y를 감소시키고

DOWN이면 y를 증가시킵니다.


if문도 있는데 이는 범위를 벗어나지 못하게하는 부분입니다.


게임시작

게임정보

종료


이 세가지 메뉴만 있는데 w키를 눌렀다고 위로 계속 올라가버리면 안되기때문에 범위를 조건문으로 지정하였습니다.


x축은 가만히 있으면 되고 y축으로 위, 아래로만 이동하면 되기때문에 y값을 증감하는 모습입니다.



y위치가 12부터 시작하고 있습니다.


12에는 게임시작

13에는 게임정보

14에는  종료


이렇게 되어있습니다.


12~14까지만 이동하면 되므로 이것이 조건문으로 제한해둔 이유입니다.

조건문에서 조건이 참이 되면 실제 이동(출력)하는 부분이 있습니다.


DOWN일 상태를 가정하여 설명하겠습니다.



1. 키보드 s키가 눌린다.


2. keyControl 함수에서 DOWN값을 반환


3. 67행의 switch문에서 DOWN에 해당하는 case로 이동


4. y가 14보다 작은가? 조건 체크


5. 작으면 gotoxy()로 현재 좌표위치로 이동 (아직 가만히있는 상태)


6. 출력되어있던 ">" 문자를 공백으로 덮어씌움(지우기)


7. gotoxy로 새로 이동할 위치로 이동(82행)


8. ">" 문자 출력 




위의 과정이 길고 복잡해보일 수 있습니다.


하지만 천천히 과정을 생각해보시고 코드로 작성해서 살펴보신다면 큰 어려움은 없을겁니다.









위 사진은 실제  출력 과정입니다.


키보드가 입력되면 먼저 좌표값을 변경하는것이 아니라

우선 원래있던 위치로 이동하여 > 문자를 지워버립니다.

지운 후에 이동하여 새로 > 문자를 출력하는 방식이죠.




<실행결과>




처음에는 어려우실 수 있지만 이해하신다면 다음 강좌를 진행하셔도 좋습니다.

이후로도 출력에는 위와같은 방식을 사용하기때문에 숙지하셔야합니다.




감사합니다.






댓글
  • 프로필사진 Thanks for you while (1)
    {
    int num = KeyControl();
    switch (num)
    {
    case UP: {
    if (y > 12)
    {
    gotoxy(x - 2, y);
    printf(" ");
    gotoxy(x - 2, --y);
    printf(">");

    }
    break;
    }

    case DOWN: {
    if (y < 14)
    {
    gotoxy(x - 2, y);
    printf(" ");
    gotoxy(x - 2, ++y);
    printf(">");

    }
    break;
    }

    case SUBMIT: {
    return y - 12;
    }
    }
    }
    /
    작성자님의 메뉴 선택코드를 받아 적어서 실행시켜 봤는데 방향 키를 눌러도 화살표의 위치가 바뀌지 않고, 계속 제자리에 있습니다.
    제가 무엇을 잘 못 했을까요? Keycontrol 함수는 문제가 없다 판단했습니다.. 도움을 주시면 되게 감사할 것 같습니다 ㅠㅠ
    2018.08.08 12:34
  • 프로필사진 BlogIcon 이근둥 키값(num)과 상수 UP, DOWN을 한번 출력해보시겠어요?

    KeyControl 함수에서 문제가 없다고 하면 switch문에서 UP 또는 DOWN의 값과 키값이 일치하지 않아서 그냥 지나치는것같습니다!
    2018.08.08 20:21 신고
  • 프로필사진 Thanks for you 문제 해결완료헀습니다!
    int num = KeyControl();
    switch (num)
    여기서 문제가 생겼는데 switch(num)으로 코드가 이동하면 num에 0값으로 자동 초기화되서 계속 w버튼이 인식되는 것 처럼 작동되었던 것이라 단순히 define에 숫자들을 1씩 올려주어 해결했습니다. 그런데 왜 0으로 자동초기화가 되는 것일까요..?
    2018.08.15 00:14
  • 프로필사진 BlogIcon 이근둥 w키를 누르지 않아도 0 (UP) 값으로 초기화되어있었다는 말씀이시죠..?!

    코드상으로는 0으로 초기화하는 부분이 없으니까 KeyControl에서 잘못된 값이 반환되었을 확률이 높습니다
    2018.08.15 15:45 신고
  • 프로필사진 Thanks for you 따로 소스파일 만들어서 확인해본 결과
    int num = keycontrl(); 이 부분에서 0값이 들어가는 것 같더군요.. 제 생각(뇌피셜)에는 keycontrol함수에 문제가 있다기 보다는 함수가 무사히 종료됐다고 반환 값이 0으로 날라가는 것이 아닐까 싶습니다..
    2018.08.15 21:25
  • 프로필사진 BlogIcon 이근둥 메인함수의 경우에만 함수 종료 시 암시적으로 0이 반환되는걸로 알고있습니다!

    Visual Studio에서 디버깅모드를 사용하면 변수값을 확실히 확인할 수 있는데 다음에 저도 한번 확인해봐야겠네요 ㅜㅜ
    2018.08.16 12:24 신고
  • 프로필사진 저도 지금 윗분과 똑같은 문제가 발생하는데 코드가 혹시 잘못된거 아닌가요 2018.08.10 14:48
  • 프로필사진 BlogIcon 이근둥 테스트 후 캡쳐했기 때문에 문제는 없을겁니다.

    키 입력값이 switch문의 case에 일치하는 값이 없어서 반응이 없을 수도 있습니다.
    한번 printf로 입력된 키값을 출력해보시고 switch문을 작성해보세요!
    2018.08.13 20:45 신고
  • 프로필사진 1234 저도 윗분들하고 똑같은 문제가 생기는데 디파인에 0이 아니라 1부터 지정하니까 문제가 없어지네요 2019.03.22 05:00
  • 프로필사진 BlogIcon 이근둥 컴파일 및 테스트 후 캡쳐한 사진인데 다시 한 번 확인해봐야겠네요.. 불편을 드려 죄송합니다 ㅜㅜ 2019.03.22 08:27 신고
  • 프로필사진 Ever int mainDraw() 함수에서 이미 x와 y는 정수가 지정되어 있는데 이 함수 내부의 while 문에서 y의 값을 왜 비교할 수 있는 것인가요? 아직 초보라 이해가 안 돼서요... ㅠㅠㅠ 2020.02.20 01:44
  • 프로필사진 BlogIcon 이근둥 mainDraw 함수 내에 선언된 변수이기 때문에 mainDraw 함수 안에 있는 코드라면 모두 접근할 수 있습니다.

    int fn ()
    {
    int a = 10;
    while (1) {
    printf("%d\n", a);
    }
    }

    위의 fn 함수 내에 선언된 a 변수는 fn 함수 내라면 어디서든 접근할 수 있습니다.
    스코프 범위에 대해 한 번 알아보시는것도 좋을 것 같습니다 :)
    2020.02.20 10:15 신고
  • 프로필사진 kathon while 문에서 키 입력은 유효 하지만 화살표는 딱 한번만 움직입니다(keyControl() 함수에서 리턴 앞에
    gotoxy(1, 1);
    printf("%c", temp);
    을 추가한 후 실행하면, 화살표는 딱 한번만 움직이지만, (1,1)좌표에서는 계속 바뀐 키보드의 값이 출력됩니다
    무엇이 문제일까요 ㅠㅠ
    2020.09.02 09:38
  • 프로필사진 BlogIcon kathon
    case UP: {
    if (y > 12) {
    gotoxy(x - 2, y);
    printf(" ");
    gotoxy(x - 2, y - 1);
    printf(">");
    }
    break;
    }
    문장을
    case UP: {
    if (y > 12) {
    gotoxy(x - 2, y);
    printf(" ");
    gotoxy(x - 2, --y);
    printf(">");
    }
    break;
    }
    가독성이 편하여 --y 를 y-1 로 바꾸었는데 작성자님 코드로 바꾸니까 정상적으로 작동하네요 이유를 알 수 있을까요?
    혹시 전위 증감 연산자 와 후위 증감 연산자의 차이인가요?
    2020.09.02 09:43
  • 프로필사진 BTJ 위, 아래 입력 잘 안되시는 분들께서는 아래 소스코드로 대체해서 해보시길 바랍니다
    ------------------------------------------------------
    case UP:
    gotoxy(x -2, y);
    printf(" ");

    y = y - 1;
    if (y < 12)
    {
    y = 12;
    } else {/**/}
    gotoxy(x - 2, y);
    printf(">");
    break;

    case DOWN:
    gotoxy(x - 2, y);
    printf(" ");

    y = y + 1;
    if (y > 14)
    {
    y = 14;
    } else {/**/ }
    gotoxy(x - 2, y);
    printf(">");
    break;
    2020.09.29 11:58
  • 프로필사진 clvkdh wasd키가 아니라 방향키로는 못하나요? 2022.03.16 20:00
댓글쓰기 폼