(CGP) 6장. 두더지 잡기 게임

 

 

[ 두더지 잡기 게임의 학습 목표 ]

 

각 개체의 속성을 정의하고 프로그래밍할 수 있다.

전체 제작 로드맵을 보면서 단계별로 게임의 모듈을 완성할 수 있다.

단계별로 제작한 소스를 이용하여 전체 프로그램을 완성할 수 있다.

 

헉4유튜브 동영상 강의 주소

(1) http://youtu.be/o4l_cOpYYOU

(2) http://youtu.be/25xfgTZ3X-g

(3) http://youtu.be/YLA-zPX9B3A

(4) http://youtu.be/c9-MnRmLdMY

 

 

 

 


01 기획

 

■ 스토리

 

구멍에서 튀어나오는 두더지를 제한 시간 안에 목표 수만큼 잡아라.

 

■ 게임 방식

 

두더지가 나오는 구멍은 9개로 구성되며 숫자 키 패드의 위치와 동일하다. 숫자 키패드를 누르는 순간 대기하던 망치가 출현한 두더지를 타격하는 게임이다.

 

■ 제한 사항

 

스테이지마다 제한 시간과 목표한 두더지 수가 정해져 있으며 이것을 달성해야 다음 스테이지로 넘어갈 수 있다. 각 스테이지 난이도는 두더지가 출현하고 있는 시간과 망치의 동작 속도에 의해 결정된다.

 

■ 기획 화면

 

[그림 6-1] 게임 기획 화면

 

 


02 실행 화면

  

[그림 6-2] 게임 시작 화면

 

[그림 6-3] 스테이지 소개 화면

 

[그림 6-4] 게임 진행 화면

 

[그림 6-5] 망치 동작 화면

 

[그림 6-6] 미션 성공 화면

 

[그림 6-7] 미션 실패 화면

 

[그림 6-8] 결과 화면

 

 

 


03 게임 제작 로드맵

 

두더지 잡기 게임은 앞서 제작한 게임보다 훨씬 더 쉽게 구현할 수 있다. 왜냐하면 앞서 제작한 게임은 기본적으로 이동이 있었지만 이 게임은 고정된 위치에서 두더지가 나타나고 사라지기를 반복하는 것 외에는 다른 것이 없기 때문이다.

이 게임은 아래의 로드맵만으로 전체 게임을 직접 제작해 본 후에 단계별로 제작과정을 살펴본다면 본인의 실력 향상에 더욱 많은 도움이 될 것이다.

 

[STEP 01]

 

[STEP 02]

 

 

[STEP 03]

 

[STEP 04]

 

[STEP 05]

[그림 6-9] 제작 로드맵

 

 


04 단계별 프로그래밍

 

 

 

STEP 01

 

[그림 6-10] 1단계 제작 로드맵

 

■ 망치

 

- 속성 

 

이 게임에서 주인공 캐릭터는 바로 망치이다.

망치가 일반적인 주인공 캐릭터와 다른 점이 있다면 생명이라는 속성이 없다는 점과 9개의 고정된 위치로 이동할 뿐 그 외의 이동은 할 수 없다는 점이다. 이와 같은 차이점을 간단히 정리하면 [표 6-1]과 같다.

 

 

구분

속성

일반적인 주인공 캐릭터

① 생명력 또는 생명

② 이동 속도 또는 이동 거리와 이동 시간 간격

③ 이동 좌표

④ 이전 이동 시각

망치

① 망치 상태( 대기 상태, 타격 상태 )

② 타격 상태가 시작된 시각

③ 타격 상태의 대기 시간

④ 좌표 배열에 접근하기 위한 인덱스

⑤ 대기 좌표

 

[표 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

#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]의 예

 

 


STEP 02

 

 

[그림 6-13] 2단계 제작 로드맵

 

 

■ 두더지 구조 설계 및 설정

 

- 속성 

 

두더지는 정해진 위치에서만 출현을 할 뿐 다른 이동은 하지 않으며 게임이 종료될 때까지  소멸되지 않는다. 두더지의 단순한 출현 동작에도 불구하고 게임을 재미있게 하는 요소는 두더지가 나와 있는 시간과 들어가 있는 시간이 다양하기 때문이다.

이와 같은 사항을 간단히 정리하면 아래의 [표 6-3]과 같으며 구조체는 [소스 6-3]과 같이 정의한다.

 

 

① 두더지 상태

② 두더지가 들어갔을 때 대기 시간

③ 두더지가 나왔을 때 대기 시간

 이전 동작 시각

 

[표 6-3] 두더지 속성

 

 

typedef enum _DUDAGI_STATE { SETUP, UP, DOWN } DUDAGI_STATE;

 

typedef struct _DUDAGI

{       

        DUDAGI_STATE nState;     // Note: 두더지 상태 

        clock_t   StayTime;           // Note: 들어갔을 때 대기 시간

        clock_t  OutPutTime;        // Note: 나왔을 때 대기 시간

        clock_t  OldTime;           // Note: 이전 시각          

} DUDAGI;

 

[소스 6-3] 두더지 속성을 구조체 정의

 

[표 6-3]의 두더지 상태에 대해 자세히 살펴보자.

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

두더지는 자신의 동작을 업그레이드하기 위해서 매번 아래의 [표 6-4]와 같은 상태를 가진다.

 

 

상태

설명

설정 상태(SETUP)

두더지의 속성을 다시 설정하는 상태

나온 상태(UP)

두더지가 출력되는 상태

들어간 상태(DOWN)

두더지가 출력되지 않는 상태

 

[표 6-4] 두더지 상태

 

첫째, 설정 상태는 두더지를 새로이 출현시키기 위해 값을 초기화하는 상태를 말한다. 즉 두더지의 다음 상태인 UP상태일 때 대기 시간과 DOWN 상태일 때의 대기 시간을 설정한다. 그리고 현재 상태에서 다음 상태와의 시간 차이를 계산하기 위해서 현재의 시각을 두더지 속성인 OldTime에 저장한다.

 

둘째, 나온 상태는 두더지를 화면에 출력한 상태를 말하며 이 상태가 되면 매번 현재의 시각과 두더지의 이전 상태 시각과 비교하여 다음 상태인 들어간 상태를 설정한다.

 

셋째, 들어간 상태는 현재 시각과 이전 상태 시각을 비교하여 들어간 상태를 유지한다.

 

여기까지 두더지 상태와 전이에 대해서 살펴보았고 이에 대한 상태 변환 순서는 [그림 6-14]와 같다.

 

[그림 6-14] 두더지 상태 변환 순서

 

위의 [그림 6-14]를 보면 SETUP은 UP과 DOWN 상태를 다시 설정하기 위한 상태라는 것을 알 수 있다. 또한 SETUP은 설정에만 관여하며 UP과 DOWN은 두더지 동작에 관여한다. 그리고 UP에서 DOWN으로, DOWN에서 SETUP 상태로 바뀌는 것은 일정한 시간 간격에 의해 바뀌게 된다.

 

[실습 예제 6-2]

 

[소스 6-3]의 두더지 속성 구조체를 이용하여 임의의 위치에 2개의 두더지가 [그림 6-15]와 같이 임의의 시간 간격으로 나오고 들어가는 프로그램을 작성해 보자.

 

[그림 6-15] 두더지 출력 화면

 

 

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

#include <stdio.h>

#include <conio.h>

#include <windows.h>

#include <time.h>

#include "Screen.h"

 

typedef enum _DUDAGI_STATE { SETUP, UP, DOWN } DUDAGI_STATE;

 

typedef struct _DUDAGI

{       

        DUDAGI_STATE nState;      // Note: 두더지 상태 

        clock_t   StayTime;           // Note: 들어갔을 때 대기 시간

        clock_t    OutPutTime;        // Note: 나왔을 때 대기 시간

        clock_t    OldTime;           // Note: 이전 시각          

} DUDAGI;

 

typedef struct _XY

{

        int nX, nY;

} XY;

 

XY     g_Point[2] = {{ 10, 10 }, { 20, 10 } };

DUDAGI g_Dudagi[2];

 

void Init()

{

     int i;

 

     // Note: 데이터 초기화

     for( i = 0 ; i < 2 ; i++ )

        g_Dudagi[i].nState = SETUP; 

}

 

void Update()

{

     int i;

     clock_t CurTime = clock();

 

     for( i = 0; i < 2 ; i++ )

     {

        switch( g_Dudagi[i].nState )

        {

        case SETUP:               

                   g_Dudagi[i].nState = UP;

                   g_Dudagi[i].OldTime = CurTime;

                   g_Dudagi[i].OutPutTime = rand() % 2000 + 50;

                   g_Dudagi[i].StayTime = rand() % 1000 + 30;

                   break;

        case UP :

                   if( (CurTime  - g_Dudagi[i].OldTime) > g_Dudagi[i].OutPutTime )

                   {

                        g_Dudagi[i].OldTime = CurTime ;

                        g_Dudagi[i].nState = DOWN;

                    }

                    break;

        case DOWN :

                    if( (CurTime  - g_Dudagi[i].OldTime) > g_Dudagi[i].StayTime )

                    {

                         g_Dudagi[i].OldTime = CurTime ;

                         g_Dudagi[i].nState = SETUP;

                     }

                     break;

        }               

     }

}

 

void Render()

{

     int i;

 

     ScreenClear();

 

     for( i = 0 ; i< 2 ; i++ )

     {

        if( g_Dudagi[i].nState == UP )

        {

            ScreenPrint( g_Point[i].nX, g_Point[i].nY, "●" );

        }               

 

        ScreenPrint( g_Point[i].nX, g_Point[i].nY + 1,  "♨" );                     

      }  

      ScreenFlipping();

}

 

void Release()

{

}

 

int main(void)

{

    int nKey;

 

    ScreenInit();

    Init();        // 초기화

 

    while( 1 )

    {

        if( _kbhit() )

        {

            nKey = _getch();

            if( nKey == 'q' )

               break;             

         }

 

           Update();    // 데이터 갱신

           Render();    // 화면 출력   

    }

     

    Release();   // 해제

    ScreenRelease();

    return 0;

}

 

[소스 6-4] 두더지 출현 소스

 

45행과 46행은 두더지가 나와 있는 시간과 들어가 있는 시간을 임의로 생성하여 설정하는 부분이다. 45행을 예로 보면 rand() % 2000은 0에서부터 1999까지의 값을 얻을 수 있다.

이때 구해진 값 중에서 0은 시간값으로 사용할 수 없으므로 최소 50 이상의 값을 가지게 하기 위해서 rand() % 2000 + 50 으로 하고 있다. 그래서 현재 g_Dudagi[i].OutPutTime 값은 최소 50에서부터 최대 2049까지의 값을 가지게 된다.

 

49행과 56행은 UP상태에서 DOWN상태로 전이하기 위한 부분과 DOWN에서 SETUP으로 전이하기 위한 경과 시간을 측정하는 부분이다.

 

 


STEP 03

 

[그림 6-16] 3단계 제작 로드맵

 

 

■ 충돌 체크

 

- 망치와 두더지 충돌

 

두더지 게임에서 충돌 체크는 상당히 간단하다. 일단 좌표 이동에 대한 개념이 없으므로 범위를 이용한 충돌 체크가 필요 없다.

그렇다면 망치와 두더지가 충돌하는 경우는 어떤 경우인가? 그것은 서로 같은 좌표 인덱스를 사용하고 망치는 타격 상태, 두더지는 출력 상태일 때이다.

여기에서 망치가 타격 상태라는 것은 망치 속성 nIsAttack 변수가 1일 때이며, 두더지가 출력되어 있다는 것은 상태 변수인 nState 값이 UP일 때이다.

 

[실습 예제 6-3]

 

두더지 상태와 망치 상태를 [그림 6-17]에서부터 [그림 6-20]와 같이 화면으로부터 상태에 해당하는 입력을 받아 설정하고 충돌 체크 결과를 출력하는 프로그램을 작성해 보자.

이 프로그램은 앞서 살펴본 게임 프레임워크를 적용할 필요가 없다.

 

[그림 6-17] 비충돌 상태

 

[그림 6-18] 충돌 상태

 

[그림 6-19] 비충돌 상태

 

[그림 6-20] 비충돌 상태

 

 

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

#include <stdio.h>

#include <conio.h>

#include <time.h>

#include <stdlib.h>

 

typedef enum _DUDAGI_STATE { SETUP, UP, DOWN } DUDAGI_STATE;

 

typedef struct _MANGCHI

{

    int    nIsAttack;         // 망치 상태

    clock_t  StartTime;        // 타격 상태가 시작된 시각

    clock_t  DelayTime;       // 타격 상태의 지연 시각

    int    nIndex;            // 좌표 배열에 접근하기 위한 인덱스

    int    nStayX, nStayY;    // 대기 상태일 때 좌표     

} MANGCHI;

 

typedef struct _DUDAGI

{       

        DUDAGI_STATE nState;   // Note: 두더지 상태   

        clock_t   StayTime;        // Note: 들어갔을 때 대기 시간

        clock_t  OutPutTime;     // Note: 나왔을 때 대기 시간

        clock_t  OldTime;        // Note: 이전 시각            

} DUDAGI;

 

MANGCHI  g_Mangchi;

DUDAGI  g_Dudagi;

 

int main( void)

{

    int nKey;

        

    while( 1 )

    {

        system( "cls" );

        printf( "두더지 상태를 설정하세요! ( 1: UP 2: DOWN ) : " );

        scanf( "%d", &nKey );

        

        g_Dudagi.nState = nKey;

        printf( "망치 상태를 설정하세요! ( 0: 대기 1:타격 ) : " );   

        scanf( "%d", &nKey );

                

        g_Mangchi.nIsAttack =  nKey;

                

        if( g_Dudagi.nState == UP && g_Mangchi.nIsAttack )

        {

            printf( "충돌" );

        }else{

            printf( "비충돌" );

        }

        _getch();

     }

     return 0;

}

 

[소스 6-5] 두더지와 망치 충돌 체크

 

 


 STEP 04

 

[그림 6-21] 4단계 제작 로드맵

 

■ 게임 스테이지 정보

 

두더지 잡기 게임에서 스테이지를 구성하기 위한 정보를 살펴보면 다음과 같다.

 

첫째, 스테이지마다 잡아야 하는 두더지의 목표 개수가 있어야 한다.

 

둘째, 제한 시간이 있어야 한다.

위의 첫째 요소와 둘째 요소는 모든 게임에 공통적으로 들어가는 요소이다.

 

셋째, 두더지가 나와 있는 대기 시간과 들어가 있는 대기 시간을 설정할 수 있어야 한다.

첫 스테이지에서는 여러 마리의 두더지가 나와 있는 시간을 길게 설정해 주는데 여기서 길게 설정한다는 것은 임의의 값의 생성 범위를 크게 해주는 것을 의미한다.

그리고 스테이지가 진행됨에 따라 두더지가 나와 있는 시간을 짧게 설정하여 스테이지의 변화를 주면 스테이지에 따른 긴장감을 높일 수 있다.

 

이제까지 살펴본 두더지 잡기 게임의 스테이지 정보는 [표 6-5]와 같으며 [소스 6-6]의 구조체로 정의한다.

 

 

① 스테이지마다 잡아야 하는 목표 개수

② 스테이지 제한 시간

③ 두더지가 UP 상태로 대기하는 최대 시간

④ 두더지가 DOWN 상태로 대기하는 최대 시간

 

[표 6-5] 스테이지 정보

 

 

typedef struct _STAGE_INFO

{

     int       nCatchDudagi;

     clock_t   LimitTime;         

     clock_t   UpLimitTime;

     clock_t   DownLimitTime;

} STAGE_INFO;

 

[소스 6-6] 스테이지 정보 정의

 

■ 게임 진행 제어

 

두더지 잡기 게임의 진행 상태도 다음과 같이 일곱 가지 상태로 나눌 수 있으며 앞서 제작한 슛 골인 게임과 동일하다.

또한 게임의 전체 흐름도인 [그림 6-22]는 앞서 제작한 슛 골인 게임과 같은 흐름을 가지고 있다.

 

 

상태

설명

초기 상태(INIT)

게임 변수의 초기화 및 사운드 초기화, 스테이지별 데이터 설정

준비상태(READY)

스테이지 정보 출력

게임 진행 상태(RUNNING)

게임 진행 및 중지 상태로 전이

중지 상태(STOP)

미션 성공과 실패를 판단

미션 성공 상태(SUCCESS)

미션 성공 화면을 출력 및 다음 스테이지로 진행

미션 실패 상태(FAILED)

미션 실패 화면을 출력한 후에 종료와 재시작 여부를 묻고 종료 또는 재시작함

결과 출력 및 종료 상태 (RESULT)

게임 결과 출력 및 종료

 

[표 6-6] 게임 진행 상태

 

 

typedef enum _GAME_STATE { INIT, READY, RUNNING, STOP, SUCCEESS, FAILED,  RESULT } GAME_STATE;

 

[소스 6-7] enum형

 

[그림 6-22] 전체 흐름도

 

위의 전체 흐름도를 다시 한번 더 설명하면 데이터 갱신 상태에서 s 키와 f 키가 입력되면 STOP 상태로 강제적으로 전이된다. STOP 상태에서 입력된 키가 s이면 SUCCESS로 게임 상태 변수를 설정하고 f이면 FAILED로 게임 상태 변수를 설정하여 다음 상태로 전이한다. 이때 키 입력은 스테이지마다 설정된 제한 시간 안에 입력되어야 한다.

마지막 RESULT 상태에서 게임의 다시 시작 질문에, y이면 현재의 스테이지를 다시 시작하지만 그렇지 않으면 결과를 출력하고 종료한다.

 

[실습 예제 6-4]

 

[그림 6-21]과 같은 전체 흐름이 진행될 수 있도록 프로그래밍해 보자. 미션의 성공과 실패는 s 키와 f 키로 대신 설정할 수 있도록 하고 제한 시간을 스테이지마다 다르게 두어 3 스테이지까지 진행이 되도록 프로그래밍해 보자.

참고로 [실습 예제 6-4]는 5장 슛 골인 게임의 [실습 예제 5-8]과 동일함으로 [실습 예제 6-4]를 자체 제작해 본 후에 [실습 예제 5-8]을 참고적으로 살펴보기 바란다.

 

여기까지 두더지 잡기 게임을 구성하는 부분을 구현해 보았으며 전체적인 구조 또한 예제를 통해 제작해 보았다. 이를 기반으로 두더지 잡기 게임 전체를 제작해 보자.

 

좋은하루강의가 도움이 되셨습니까? 손가락 꾸욱 눌러주는 센스 ~~ 

[출처] https://nowcampus.tistory.com/entry/6%EC%9E%A5?category=655340

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
108 [Xamarin] Xamarin.Forms. Android 실행/ 디버깅시에 에뮬리이터 배포오류 Why am I getting this error in Xamarin.Forms using Visual Studio? file 졸리운_곰 2021.12.01 22
107 [Xamarin] Visual Studio 2019 를 설치하고 Xmarin.forms 빌드시 에러 : I am just download and start Visual Studio (Xamarin Project). But there is an ERROR NU1101. file 졸리운_곰 2021.12.01 53
106 [게임개발] How to Create Smarter NPCs in Games file 졸리운_곰 2021.08.31 23
105 (CGP)16장. 탱크 게임 file 졸리운_곰 2021.06.28 802
104 (CGP) 15장. 탱크 맵툴 만들기 file 졸리운_곰 2021.06.28 225
103 (CGP) 14장 Sogo 게임 file 졸리운_곰 2021.06.28 21
102 (CGP)13장. 패턴 뷰어 file 졸리운_곰 2021.06.28 19
101 (CGP) 12장 Snake 게임 file 졸리운_곰 2021.06.28 23
100 (CGP) 11장 Snake 게임 툴 만들기 file 졸리운_곰 2021.06.28 50
99 (CGP) 10장. 하트담기 게임 file 졸리운_곰 2021.06.28 25
98 (CGP) 9장. 하트 툴 만들기 file 졸리운_곰 2021.06.28 22
97 (CGP) 8장. 벽돌깨기 게임 file 졸리운_곰 2021.06.28 48
96 (CGP)7장. 짝 맞추기 게임 file 졸리운_곰 2021.06.28 130
» (CGP) 6장. 두더지 잡기 게임 file 졸리운_곰 2021.06.28 113
94 (CGP) 5장. 슛골인 게임 file 졸리운_곰 2021.06.27 151
93 (CGP) 4장. 사운드 file 졸리운_곰 2021.06.27 77
92 (CGP) 3장. 게임의 기본 구조 file 졸리운_곰 2021.06.27 126
91 (CGP) 2장. 함수 file 졸리운_곰 2021.06.27 36
90 (CGP) 1장. C언어 file 졸리운_곰 2021.06.27 60
89 (CGP) 0장. C를 이용한 게임프로그래밍 강좌를 시작하기 전에 file 졸리운_곰 2021.06.27 173
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED