다중키 입력이 가능한 GetAsyncKeyState
C언어 / C++에서 입력키의 정보를 알아오기 위해 _getch()를 종종 사용하고는 합니다. 하지만 _getch() 함수는 마지막에 누른 키 하나만을 입력받습니다. 그렇기에 좌,우,상,하 키를 동시에 입력받지 못하여 "대각선 이동" 모션을 할수가 없습니다. 게임을 개발하기 위해서는 _getch()함수보다는 GetAsyncKeyState()함수를 사용하도록 합시다. GetAsyncKeyState()함수는 입력을 멀티로 받을 수 있습니다. →키와 ↑키를 동시에 누른다면 오른쪽 위의 대각선 방향으로 이동을 할 수 있게됩니다.
GetAsyncKeyState 사용법
SHORT GetAsyncKeyState(int vKey)
함수의 형태는 위와 같습니다. 인자값으로는 키보드의 키 (ex : VK_LEFT) 같은 키값이 오며 리턴값으로는 Short를 반환합니다. 정확히는 Short보다는 비트값이라고 보는것이 맞습니다.
GetAsyncKeyState의 반환값
반환값 | 설명 |
0(0x0000) | 이전에 누른 적이 없고 호출 시점에서 안눌린 상태 |
0x8000 | 이전에 누른 적이 없고 호출 시점에서 눌린 상태 |
0x8001 | 이전에 누른 적이 있고 호출 시점에서 눌린 상태 |
1(0x0001) | 이전에 누른 적이 있고 호출 시점에서 안눌린 상태 |
GetAsyncKeyState는 키의 상태에 따라 위와 같이 반환값이 비트형태로 리턴됩니다. 그렇기에 이 반환값을 활용하기 위해서는 아래와 같이 비트연산자를 활용해야합니다.
if(GetAsyncKeyState(VK_LEFT) & 0x8000) -> 지금 키가 눌림
if(GetAsyncKeyState(VK_LEFT) & 0x0001) -> 이전과 지금 사이에 키가 눌림
if(GetAsyncKeyState(VK_LEFT)) -> 둘다 가능
게임 개발을 위해서라면 if(GetAsyncKeyState(VK_LEFT)) 이 형태로 사용하는것을 가장 추천드립니다.
GetAsyncKeyState와 GetKeyState의 차이점
GetAsyncKeyState()함수는 비동기로 처리합니다. 즉, 호출된 시점에서 키 상태를 조사하여, 메시지 큐를 거치지 않고 바로 리턴해주므로 키 입력을 바로 처리해 줄 수 있습니다. 반대로 GetKeyState()함수는 호출된 시점에서 메시지 큐를 거치게 되며, 메시지 발생 후의 상태를 리턴하게 되며 키보드 메시지 처리 루틴내에서 사용할 수 있습니다.
대부분의 게임은 현재 눌린키값이 무엇인지가 중요하고 이전에 눌린 키의 값은 중요하지 않습니다. GetKeyState()함수를 사용할 시 메시지 큐에 처리되지 않은 키값이 남아있다면 키가 눌렸다고 인식이 되므로 GetAsyncKeyState함수를 사용하는것이 불필요한 오류를 예방할 수 있습니다.
GetAsyncKeyState 함수를 활용하여 캐릭터 이동시키기
#include<stdio.h>
#include<windows.h>
void gotoxy(int x, int y) {
COORD Pos = { x - 1, y - 1 };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);
}
void main() {
int x = 1;
int y = 1;
gotoxy(x, y);
while (1) {
if (GetAsyncKeyState(VK_LEFT) & 0x8000) { //왼쪽
x--;
}
if (GetAsyncKeyState(VK_RIGHT) & 0x8000) { //오른쪽
x++;
}
if (GetAsyncKeyState(VK_UP) & 0x8000) { //위
y--;
}
if (GetAsyncKeyState(VK_DOWN) & 0x8000) { //아래
y++;
}
system("cls");
gotoxy(x, y);
printf("♥");
}
}
간단하게 위, 아래, 오른쪽, 왼쪽의 키값을 받아 좌표를 움직이는 예제를 만들어 보았습니다. 캐릭터를 이동시키고 싶다면 입력키별로 좌표값을 조정하여 캐릭터를 이동시키시면 됩니다.
가상 키 코드
값 | 가상키 코드 | 설명 |
0x01 | VK_LBUTTON | 마우스 왼쪽 버튼 |
0x02 | VK_RBUTTON | 마우스 오른쪽 버튼 |
0x03 | VK_CANCEL | Ctrl + Break |
0x04 | VK_MBUTTON | 마우스 가운데 버튼 |
0x05 | VK_XBUTTON1 | X1 마우스 버튼 |
0x06 | VK_XBUTTON2 | X2 마우스 버튼 |
0x07 | - | <정의되지 않음> |
0x08 | VK_BACK | Backspace |
0x09 | VK_TAB | Tab |
0x0A-0x0B | - | <예약됨> |
0x0C | VK_CLEAR | Clear 키 |
0x0D | VK_RETURN | Enter |
0x0E-0x0F | - | <정의되지 않음> |
0x10 | VK_SHIFT | Shift |
0x11 | VK_CONTROL | Ctrl |
0x12 | VK_MENU | Alt |
0x13 | VK_PAUSE | Pause |
0x14 | VK_CAPITAL | Caps Lock |
0x15 | VK_KANA / VK_HANGUL | IME 가나 모드 / 한글 모드 |
0x16 | - | <정의되지 않음> |
0x17 | VK_JUNJA | IME 전자모드 |
0x18 | VK_FINAL | IME 최종모드 |
0x19 | VK_HANJA / VK_KANJI | IME 한자모드 |
0x1A | - | <정의되지 않음> |
0x1B | VK_ESCAPE | Esc |
0x1C | VK_CONVERT | IME 변환 |
0x1D | VK_NONCONVERT | IME 변환 안함 |
0x1E | VK_ACCEPT | IME 승인 |
0x1F | VK_MODECHANGE | IME 모드 변경 요청 |
0x20 | VK_SPACE | Space Bar |
0x21 | VK_PRIOR | Page Up |
0x22 | VK_NEXT | Page Down |
0x23 | VK_END | End |
0x24 | VK_HOME | Home |
0x25 | VK_LEFT | ← |
0x26 | VK_UP | ↑ |
0x27 | VK_RIGHT | → |
0x28 | VK_DOWN | ↓ |
0x29 | VK_SELECT | Select |
0x2A | VK_PRINT | Print Screen |
0x2B | VK_EXECUTE | Execute |
0x2C | VK_SNAPSHOT | Print Screen |
0x2D | VK_INSERT | Insert |
0x2E | VK_DELETE | Delete |
0x2F | VK_HELP | Help |
0x30 | - | 0 |
0x31 | - | 1 |
0x32 | - | 2 |
0x33 | - | 3 |
0x34 | - | 4 |
0x35 | - | 5 |
0x36 | - | 6 |
0x37 | - | 7 |
0x38 | - | 8 |
0x39 | - | 9 |
0X3A-0X40 | - | <정의되지 않음> |
0x41 | - | A |
0x42 | - | B |
0x43 | - | C |
0x44 | - | D |
0x45 | - | E |
0x46 | - | F |
0x47 | - | G |
0x48 | - | H |
0x49 | - | I |
0x4A | - | J |
0x4B | - | K |
0x4C | - | L |
0x4D | - | M |
0x4E | - | N |
0x4F | - | O |
0x50 | - | P |
0x51 | - | Q |
0x52 | - | R |
0x53 | - | S |
0x54 | - | T |
0x55 | - | U |
0x56 | - | V |
0x57 | - | W |
0x58 | - | X |
0x59 | - | Y |
0x5A | - | Z |
0x5B | VK_LWIN | 왼쪽 윈도우 키 |
0x5C | VK_RWIN | 오른쪽 윈도우 키 |
0x5D | VK_APPS | 어플리케이션 키 |
0x5E | - | <예약됨> |
0x5F | VK_SLEEP | Computer Sleep키 |
0x60 | VK_NUMPAD0 | 숫자 키패드0 |
0x61 | VK_NUMPAD1 | 숫자 키패드1 |
0x62 | VK_NUMPAD2 | 숫자 키패드2 |
0x63 | VK_NUMPAD3 | 숫자 키패드3 |
0x64 | VK_NUMPAD4 | 숫자 키패드4 |
0x65 | VK_NUMPAD5 | 숫자 키패드5 |
0x66 | VK_NUMPAD6 | 숫자 키패드6 |
0x67 | VK_NUMPAD7 | 숫자 키패드7 |
0x68 | VK_NUMPAD8 | 숫자 키패드8 |
0x69 | VK_NUMPAD9 | 숫자 키패드9 |
0x6A | VK_MULTPLY | 숫자 키패드* |
0x6B | VK_ADD | 숫자 키패드+ |
0x6C | VK_SEPARATOR | Separator키 |
0x6D | VK_SUBTRACT | 숫자 키패드- |
0x6E | VK_DECIMAL | 숫자 키패드. |
0x6F | VK_DIVDE | 숫자 키패드/ |
0x70 | VK_F1 | F1 |
0x71 | VK_F2 | F2 |
0x72 | VK_F3 | F3 |
0x73 | VK_F4 | F4 |
0x74 | VK_F5 | F5 |
0x75 | VK_F6 | F6 |
0x76 | VK_F7 | F7 |
0x77 | VK_F8 | F8 |
0x78 | VK_F9 | F9 |
0x79 | VK_F10 | F10 |
0x7A | VK_F11 | F11 |
0x7B | VK_F12 | F12 |
0x7C | VK_F13 | F13 |
0x7D | VK_F14 | F14 |
0x7E | VK_F15 | F15 |
0x7F | VK_F16 | F16 |
0x80 | VK_F17 | F17 |
0x81 | VK_F18 | F18 |
0x82 | VK_F19 | F19 |
0x83 | VK_F20 | F20 |
0x84 | VK_F21 | F21 |
0x85 | VK_F22 | F22 |
0x86 | VK_F23 | F23 |
0x87 | VK_F24 | F24 |
0x88-0x8F | - | NumLock |
0x90 | VK_NUMLOCK | ScrollLock |
0x91 | VK_SCROLL | OEM키 |
0x92-0x96 | - | <할당되지 않음> |
0xA0 | VK_LSHIFT | 왼쪽 Shift |
0xA1 | VK_RSHIFT | 오른쪽 Shift |
0xA2 | VK_LCONTROL | 왼쪽 Ctrl |
0xA3 | VK_RCONTROL | 오른쪽 Ctrl |
0xA4 | VK_LMENU | 왼쪽 Alt |
0xA5 | VK_RMENU | 오른쪽 Alt |
0xA6-0xFE | - | <이하생략> |
'Language > C , C++ , C#' 카테고리의 다른 글
[C언어/C++] 인라인(inline) 함수 사용법 & 예제 (0) | 2021.02.22 |
---|---|
[C언어/C++] 화면 깜빡임 없애기 (더블 버퍼링) (0) | 2021.02.21 |
[C언어/C++] 화면의 커서 안보이게 숨기기 (+커서 두께 조절) (0) | 2021.02.20 |
[C언어/C++] 원하는 좌표로 커서 이동하기 (SetConsoleCursorPosition) (0) | 2021.02.20 |