|
구분 | 속성 |
일반적인 주인공 캐릭터 | ① 생명력 또는 생명 ② 이동 속도 또는 이동 거리와 이동 시간 간격 ③ 이동 좌표 ④ 이전 이동 시각 |
망치 | ① 망치 상태( 대기 상태, 타격 상태 ) ② 타격 상태가 시작된 시각 ③ 타격 상태의 대기 시간 ④ 좌표 배열에 접근하기 위한 인덱스 ⑤ 대기 좌표 |
[표 6-1] 속성 비교
위의 [표 6-1]에서 소개한 망치의 속성에 대해 살펴보자.
첫째, 망치 상태가 있다.
망치 상태는 타격 상태와 대기 상태로 나눌 수 있다.
타격 상태는 현재 망치가 9개의 두더지 구멍으로 이동한 상태를 말하며 대기 상태는 타격을 하기 위한 준비 상태를 말한다.
이 상태값에 따라 충돌과 망치의 다음 동작이 결정된다.
둘재, 타격 상태가 시작된 시각이 있다.
이 속성은 시간 간격을 조사하기 위한 속성으로 대기 상태에서 타격 상태가 될 때의 시간을 의미한다.
이 시각을 기준으로 타격 상태를 일정 시간동안 유지하게 된다.
셋째, 타격 상태의 대기 시간이 있다.
만약 키 입력에 따라 아무 제약 없이 타격 동작을 반복하게 한다면 키 입력 속도에 따라 망치의 타격 속도가 결정되므로 게임성이
떨어지게 된다. 그래서 타격 상태일 때 약간의 대기시간을 두어 키 입력에 따라 즉시 반응하지 못하게 하여야 한다.
그리고 대기 시간은 항상 둘째 속성인 타격 상태가 시작된 시각을 기준으로 현재 시각까지를 조사하여 다음 상태를 결정하게 된다.
넷째, 좌표 배열에 접근하기 위한 인덱스가 있다.
망치와 두더지는 같은 좌표를 사용하므로 9개의 좌표를 공유할 수 있다.
이때 9개의 좌표는 같은 데이터형을 사용하므로 간단히 9개의 배열로 선언하면 되고, 각 배열에 접근하기 위해 인덱스가 필요하다.
다섯째, 대기 좌표가 있다.
대기 좌표는 망치가 준비하는 좌표이므로 화면의 임의의 고정 위치가 된다.
여기까지 소개한 망치의 다섯 가지 속성을 구조체로 정리하면 [소스 6-1]과 같다.
typedef struct _MANGCHI { int nIsAttack; // 망치 상태 clock_t StartTime; // 타격 상태가 시작된 시각 clock_t DelayTime; // 타격 상태의 대기 시간 int nIndex; // 좌표 배열에 접근하기 위한 인덱스 int nStayX, nStayY; // 대기 상태일 때 좌표 } MANGCHI; |
[소스 6-1] 망치 속성 정의
이동 및 키보드 처리
망치는 대기 상태에서 타격 상태로 바뀔 때 이동된다. 대기 상태에서 타격 상태로 바뀐다는 것은 망치의 상태를 바꾸는 것도
의미하지만 좌표가 변한다는 의미도 있다. 그래서 망치에 대기 상태일 때의 좌표와 타격했을 때의 좌표가 있는 것이다.
두 좌표는 고정 좌표를 사용하며 망치가 타격 상태일 때는 미리 설정한 9개의 고정 좌표로부터 현재 좌표를 설정한다.
그러기 위해서는 9개의 배열에 배열 인덱스로 접근하여 좌표값을 읽어 와야 한다.
특히 망치로 타격할 때 입력키가 1에서부터 9까지를 이용하므로 이것을 9개의 배열 인덱스(0~8)로 변환하여 사용하면 키 입력값으로
좌표 배열의 값을 쉽게 읽어 올 수 있다. 또한 망치를 타격한 다음 망치가 원래의 자리로 바로 돌아오면 재빨리 쓸 수 있으므로 게임의
재미 요소를 떨어뜨릴 수 있다. 그래서 망치가 타격 상태에서 대기 상태로 돌아오는데 약간의 대기 시간을 주는데 위의 MANGCHI 구
조체 변수인 StartTime과 DelayTime이 그 역할을 한다.
[실습 예제 6-1]
[소스 6-1]에 정의한 망치 속성을 정의하고 키 입력(1~9 숫자)에 따라 망치가 [그림 6-11]의 대기 상태에서 [그림 6-12]와 같이
타격 상태가 되도록 프로그래밍해 보자.
그리고 망치가 타격 상태가 되었을 때 대기 시간을 적용하여 일정 시간 머물도록 프로그래밍하자.
[그림 6-11] 대기 상태의 망치
[그림 6-12] 타격 상태의 망치
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | #include <stdio.h> #include <conio.h> #include <string.h> #include <windows.h> #include <time.h> #include "Screen.h"
typedef struct _MANGCHI { int nIsAttack; // 망치 상태 clock_t StartTime; // 타격 상태가 시작된 시각 clock_t DelayTime; // 타격 상태의 대기 시간 int nIndex; // 좌표 배열에 접근하기 위한 인덱스 int nStayX, nStayY; // 대기 상태일 때 좌표 } MANGCHI;
typedef struct _XY { int nX, nY; } XY;
XY g_Point[9] = { { 10, 15 }, { 20, 15 }, { 30, 15 }, { 10, 10 }, { 20, 10 }, { 30, 10 }, { 10, 5 }, { 20, 5 }, { 30, 5 } };
MANGCHI g_Mangchi;
void Mangchi( int x, int y ) { ScreenPrint( x-4, y-1, "☆┏━┓" ); ScreenPrint( x-4, y, "⊂┃꽝┃〓〓⊂⊃"); ScreenPrint( x-4, y+1, "☆┗━┛" ); }
void MangchiReady( int x, int y ) { ScreenPrint( x-4, y-2, " ∩" ); ScreenPrint( x-4, y-1, " ┏━┓" ); ScreenPrint( x-4, y, " ┃ ┃"); ScreenPrint( x-4, y+1, " ┗━┛" ); ScreenPrint( x-4, y+2, " ∥" ); ScreenPrint( x-4, y+3, " ∥" ); ScreenPrint( x-4, y+4, " ∩" ); ScreenPrint( x-4, y+5, " ∪" ); }
void Init() { // Note: 망치 셋업 g_Mangchi.nIsAttack = 0; g_Mangchi.nIndex = 0; g_Mangchi.nStayX = 40; g_Mangchi.nStayY = 10; g_Mangchi.StartTime = 0; g_Mangchi.DelayTime = 300; }
void Update() { clock_t CurTime = clock();
if( g_Mangchi.nIsAttack == 1 ) { if( ( CurTime - g_Mangchi.StartTime) > g_Mangchi.DelayTime ) { g_Mangchi.nIsAttack = 0; } } }
void Render() { ScreenClear();
if( g_Mangchi.nIsAttack ) Mangchi( g_Point[g_Mangchi.nIndex].nX, g_Point[g_Mangchi.nIndex].nY ); else MangchiReady( g_Mangchi.nStayX, g_Mangchi.nStayY );
ScreenFlipping(); }
void Release() {
}
int main(void) { int nKey;
ScreenInit(); Init(); // 초기화
while( 1 ) { if( _kbhit() ) { nKey = _getch(); if( nKey == 'q' ) break;
if( g_Mangchi.nIsAttack == 0 ) { if( nKey >= '1' && nKey <= '9' ) { g_Mangchi.nIndex = nKey - '1'; g_Mangchi.StartTime = clock(); g_Mangchi.nIsAttack = 1; } } }
Update(); // 데이터 갱신 Render(); // 화면 출력 }
Release(); // 해제 ScreenRelease(); return 0; } |
[소스 6-2] 망치 소스
22행부터 24행은 망치와 두더지가 공통적으로 사용하는 좌표이다.
이 좌표는 공용으로 사용하는 좌표이므로 전역 변수로 선언되어 있다.
망치가 대기 상태에서 타격 상태로 바뀌는 순간은 104행과 같이 현재의 망치 상태가 대기 상태이고 1에서부터 9까지의 키 입력이
들어 왔을 때이다.
이때가 타격 상태로 전이하는 때이므로 109행을 보면 현재의 시각을 g_Mangchi.StartTime에 저장하고 있다.
이제 이 시각에서부터 시작해서 망치의 대기 시간을 비교하여 망치가 타격 상태에서 대기 상태로 돌아가기 위한 시간 차이를
계산하게 된다.
이에 대한 부분은 65행과 67행에 나와 있다.
여기서 타격은 키패드의 숫자 1에서부터 9까지를 이용하므로 1에서부터 9까지의 아스키코드 값을 배열의 인덱스인 0에서부터 8까지
변환해야 하는데 이 부분은 108행과 같이 계산하면 된다.
인덱스 = 키 - ‘1’ |
[식 6-1] 인덱스로 변환 식
아래의 [표 6-2]는 대기 상태에서 키 입력이 들어 왔을 때에 [식 6-1]을 적용한 결과를 나타낸다.
키 입력 상태 | 아스키 상태 |
‘1’ - ‘1’ = 0 ‘2’ - ‘1’ = 1 ‘3’ - ‘1’ = 2 ‘4’ - ‘1’ = 3 ‘5’ - ‘1’ = 4 ‘6’ - ‘1’ = 5 ‘7’ - ‘1’ = 6 ‘8’ - ‘1’ = 7 ‘9’ - ‘1’ = 8 | 49 - 49 = 0 50 - 49 = 1 51 - 49 = 2 52 - 49 = 3 53 - 49 = 4 54 - 49 = 5 55 - 49 = 6 56 - 49 = 7 57 - 49 = 8 |
[표 6-2] [식 6-1]의 예