본문 바로가기
프로그래밍

DigDog 스크립트 설명

by HyunS_PG 2020. 5. 8.
반응형

 

※목차

1. 맵 제작

2. 애니메이션

3. 플레이어 클래스

4. 광석 클래스

5. 텔레포트

6. 스테이지 진행

7. 전체 스크립트 및 게임 다운로드

 

 

 

 

1. 맵 제작                 

엑셀로 미리 만들어본 맵

스크립트)

엑셀로 좌표를 적어 이미지를 만들어 본 다음 좌표를 그대로 옮겨적어 스크립트에 적용했습니다.

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
//스테이지 1
case 1:
for (int i = (int)Screen.GAMESCREEN_START_X + 2; i < (int)Screen.GAMESCREEN_END_X - 1; i++)
{
    for (int j = (int)Screen.GAMESCREEN_START_Y + 1; j < (int)Screen.GAMESCREEN_END_Y; j++)
    {
         SetCursorPosition(i, j);
         Write("  ");
    }
}
 
for (int i = 0; i < 160; i++)
{
    concrete[i] = new Stone(0010, ConsoleColor.Black, ConsoleColor.Black);
 
    if (i < 50)
    {
        iron[i] = new Stone(0010, ConsoleColor.Black);
        gold[i] = new Stone(0010, ConsoleColor.Black);
    }
    if (i < 10)
    {
        poison[i] = new Stone(0010, ConsoleColor.Black);
    }
}
 
player = new Player((int)Screen.GAMESCREEN_START_X + 10 * 2, (int)Screen.GAMESCREEN_START_Y + 8"▼");
escape = new Escape((int)Screen.GAMESCREEN_START_X + 12 * 2, (int)Screen.GAMESCREEN_START_Y + 12);
 
for (int i = 0; i < 7; i++)
{
    concrete[i] = new Stone((int)Screen.GAMESCREEN_START_X + (7 + i) * 2, (int)Screen.GAMESCREEN_START_Y + 7, (int)eStone.concrete_HP, 0, ConsoleColor.White, ConsoleColor.White);
    concrete[i + 7= new Stone((int)Screen.GAMESCREEN_START_X + (7 + i) * 2, (int)Screen.GAMESCREEN_START_Y + 13, (int)eStone.concrete_HP, 0, ConsoleColor.White, ConsoleColor.White);
    concrete[i + 14= new Stone((int)Screen.GAMESCREEN_START_X + 7 * 2, (int)Screen.GAMESCREEN_START_Y + 7 + i, (int)eStone.concrete_HP, 0, ConsoleColor.White, ConsoleColor.White); 
    concrete[i + 21= new Stone((int)Screen.GAMESCREEN_START_X + 13 * 2, (int)Screen.GAMESCREEN_START_Y + 7 + i, (int)eStone.concrete_HP, 0, ConsoleColor.White, ConsoleColor.White);
}
 
iron[0= new Stone((int)Screen.GAMESCREEN_START_X + 9 * 2, (int)Screen.GAMESCREEN_START_Y + 9, (int)eStone.iron_HP, (int)eStone.iron_Chance, ConsoleColor.DarkGray);
iron[1= new Stone((int)Screen.GAMESCREEN_START_X + 10 * 2, (int)Screen.GAMESCREEN_START_Y + 9, (int)eStone.iron_HP, (int)eStone.iron_Chance, ConsoleColor.DarkGray);

(생략)
iron[10= new Stone((int)Screen.GAMESCREEN_START_X + 12 * 2, (int)Screen.GAMESCREEN_START_Y + 11, (int)eStone.iron_HP, (int)eStone.iron_Chance, ConsoleColor.DarkGray);
iron[11= new Stone((int)Screen.GAMESCREEN_START_X + 10 * 2, (int)Screen.GAMESCREEN_START_Y + 12, (int)eStone.iron_HP, (int)eStone.iron_Chance, ConsoleColor.DarkGray);
 
poison[0= new Stone((int)Screen.GAMESCREEN_START_X + 10 * 2, (int)Screen.GAMESCREEN_START_Y + 10, (int)eStone.poison_HP, 0, ConsoleColor.Green);
poison[1= new Stone((int)Screen.GAMESCREEN_START_X + 10 * 2, (int)Screen.GAMESCREEN_START_Y + 11, (int)eStone.poison_HP, 0, ConsoleColor.Green);
                    
posion_MaxCount = 2;    //없애야하는 오염물질 수
posion_Count = 0;       //스테이지 넘어갈 때 0으로 리셋
break;
cs

 

 

 

 

2. 애니메이션                 

곡괭이 애니메이션

스크립트)

곡괭이 업그레이드시 색 변화를 주기 위해서 ConsoleColor만 받아온 다음 애니메이션은 Sleep()을 사용하여 만들었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//곡괭이질 애니메이션
static void Pick_Ani(ConsoleColor pick_color)
{
    SetCursorPosition((int)Screen.GAMESCREEN_END_X + 3, (int)Screen.GAMESCREEN_END_Y - 9);
    Write("          ");
(생략)
    SetCursorPosition((int)Screen.GAMESCREEN_END_X + 3, (int)Screen.GAMESCREEN_END_Y - 4);
    Write("          ");
 
    ForegroundColor = pick_color;
    SetCursorPosition((int)Screen.GAMESCREEN_END_X + 13, (int)Screen.GAMESCREEN_END_Y - 6);
    Write("■■");
(생략)
    ForegroundColor = ConsoleColor.DarkRed;
    SetCursorPosition((int)Screen.GAMESCREEN_END_X + 11, (int)Screen.GAMESCREEN_END_Y - 2);
    Write("■");
(생략)
 
    System.Threading.Thread.Sleep(40);
 
    SetCursorPosition((int)Screen.GAMESCREEN_END_X + 11, (int)Screen.GAMESCREEN_END_Y - 6);
    Write("          ");
(생략)
}
cs

 

 

 

 

 

 

3. 플레이어 클래스                 

스크립트)

1) 플레이어의 좌표(int x,y)와 플레이어가 지나간 흔적을 지우기 위한 좌표(int preX, preY) 변수 선언

2) 정면에 있는 광석을 타겟팅하기 위해 변수(forwarxX,Y) 선언

3) 플레이어의 이미지에 따라 이동 및 회전하기 위해 shape 사용

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
    //플레이어 클래스
    class Player
    {
        public int x, y;                      //플레이어 위치
        public int preX, preY;                //플레이어 이전 위치(흔적 지우기 위함)
        public int forwardX, forwardY;        //플레이어 정면(타겟팅) 
        public int preForwardX, preForwardY;  //타겟팅 이전 위치
        public string shape;                  //플레이어 이미지
        public int Attack { get; set; }       //곡괭이에 따른 플레이어 공격력
        public int Money { get; set; }        //소지한 골드
 
        //플레이어 클래스 초기화
        public Player(int x, int y, string shape)
        {
            this.x = x;         //처음 시작 위치
            this.y = y;
            this.shape = shape; //처음 플레이어 이미지
 
            //방향에 따른 플레이어 이미지
            switch (shape)
            {
                case "▲":
                    forwardX = x;
                    forwardY = y - 1;
                    break;
                case "▼":
                    forwardX = x;
                    forwardY = y + 1;
                    break;
                case "◀":
                    forwardX = x - 2;
                    forwardY = y;
                    break;
                case "▶":
                    forwardX = x + 1;
                    forwardY = y;
                    break;
            }
 
            preForwardX = forwardX;
            preForwardY = forwardY;
 
            Money = 0;
        }
 
        //플레이어 공격
        public void Attacking(Stone[] concrete, Stone[] iron, Stone[] gold, Stone[] poison)
        {
            for (int i = 0; i < concrete.Length; i++)
            {
                if (forwardX % 2 == 1)  //광석 오른쪽에 있을 때는 타겟팅 위치가 같을 수 없으므로 x좌표를 -1한다.
                    forwardX--;
                if ((concrete[i].X == forwardX) && (concrete[i].Y == forwardY)) //광석 위치와 타켓팅 위치가 같을 때
                    concrete[i].DecreaseHP(Attack);
            }
(생략)
        }
 
        //텔레포트 스킬
        public void Teleport(Stone[] concrete, Stone[] iron, Stone[] gold, Stone[] poison) {...}
    }
cs

 

 

 

 

 

4. 광석 클래스                 

광석 애니메이션

스크립트)

1) string[] shaping으로 광석의 각 이미지 저장

2) IEnumerator GetEnumerator()으로 광석의 체력에 따른 이미지를 가져옴(일반상태, 체력이 절반일 때, 부서질 때)

3) Random() 함수를 이용하여 Chance 확률로 보석이 떨어짐

4) DecreaseHP(int playerAttack) 함수로 플레이어 공격에 따른 광석의 체력 계산

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
//광석 클래스
class Stone
{
    public int X { get; set; }      //광석 X좌표
    public int Y { get; set; }      //광석 Y좌표
    public int Max_HP { get; set; } //광석 최대체력
    public int HP { get; set; }     //광석 체력
    public int Chance { get; set; } //보석이 나올 확률
    public int Worth { get; set; }  //보석 값
    public ConsoleColor Color { get; set; } //광석 색깔
    (생략)
    public string[] shaping = { "■""▦""▒""__""  ""◈" };   //광석 애니메이션 이미지와 보석 이미지
    (생략)
 
    //광석 클래스 초기화
    public Stone(int x, int y, int max_HP, int chance, ConsoleColor color) {...}
    
    //광석을 부수면 지정한 확률로 보석이 생김
    public void RandomGem()
    {
        Random rand = new Random();
 
        if (rand.Next(100+ 1 <= Chance) //(Chance)% 확률로 보석이 생김
        {
            SetCursorPosition(X, Y);
            ForegroundColor = Color;
            Write("◈");
            gainGem = true;          //보석이 떨어졌을 때 획득이 가능해짐
        }
    }
 
    //광석의 체력에 따라 이미지 변경
    public IEnumerator GetEnumerator()
    {
        if (!isDead)
        {
            ForegroundColor = Color;
 
            //광석 체력이 절반으로 됐을 때 이미지
            if (HP <= Max_HP / 2 && HP > 0)
               yield return shaping[1];
 
            //광석 체력이 0이하로 됐을 때 이미지
            else if (HP <= 0)
            {
                yield return shaping[2];
                System.Threading.Thread.Sleep(200);
                ForegroundColor = Color;
                yield return shaping[3];
                System.Threading.Thread.Sleep(200);
                yield return shaping[4];
                isDead = true;
                death = 1;
                RandomGem();
            }
            //광석 기본 이미지
            else
                yield return shaping[0];
            //BackgroundColor = ConsoleColor.Black;     //콘크리트 배경있는 버전용
        }
    }
 
    //플레이어가 광석 타격시 체력 감소
    public void DecreaseHP(int playerAttack)
    {
        HP -= playerAttack;
    }
    (생략)
}
cs

 

 

 

 

 

5. 텔레포트                 

텔레포트의 최대거리를 3으로 설정한 상태이기 때문에 3칸 앞에 하얀 벽이 있어서 처음에는 2칸만 이동, 그 다음 텔레포트시에는 빈 공간이어서 3칸 이동

스크립트)

1) 모든 벽과 광석의 좌표 정보를 받아오는 이유는 텔레포트시 플레이어와 겹치는 경우를 계산하기 위함입니다.

2) 앞에 장애물이 있을 경우 최대한 먼 빈 공간으로 이동하기 위해 distance 변수와 --를 사용

3) 플레이어가 바라보는 방향으로 텔레포트하기 위해 if(shape == "") 사용

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
//텔레포트 스킬
public void Teleport(Stone[] concrete, Stone[] iron, Stone[] gold, Stone[] poison)
{
   int distance = 3;   //텔레포트 최대 거리
   int preDistance;
 
   while (true)
   {
      preDistance = distance;
 
      if (shape == "▲")       //플레이어 이미지(방향)에 따라 순간이동
      {
         y -= distance;
 
         forwardX = x;
         forwardY = y - 1;
      }
      if (shape == "▼")       //플레이어 이미지(방향)에 따라 순간이동
      {
         y += distance;
 
         forwardX = x;
         forwardY = y + 1;
      }
      if (shape == "◀")       //플레이어 이미지(방향)에 따라 순간이동
      {
         x -= 2 * distance;
                    
         forwardX = x - 1;
         forwardY = y;
      }
      if (shape == "▶")       //플레이어 이미지(방향)에 따라 순간이동
      {
         x += 2 * distance;
 
         forwardX = x + 2;
         forwardY = y;
      }
 
      //텔레포트시 플레이어가 게임 화면 밖으로 나가지 않게 하기 위한 조건
      if ((x <= (int)Screen.GAMESCREEN_START_X) || (x >= (int)Screen.GAMESCREEN_END_X) || (y <= (int)Screen.GAMESCREEN_START_Y) || (y >= (int)Screen.GAMESCREEN_END_Y))
         distance--;
 
      //텔레포트시 플레이어가 광석하고 겹치지 않게 하기 위한 조건
      for (int i = 0; i < concrete.Length; i++)
      {
         if (!concrete[i].isDead && (x == concrete[i].X) && (y == concrete[i].Y))
            distance--;
      }
      (생략)
      for (int i = 0; i < poison.Length; i++)
      {
         if (!poison[i].isDead && (x == poison[i].X) && (y == poison[i].Y))
             distance--;
      }
 
      //순간이동 가능할 때 or 앞에 공간이 더이상 없을 때
      if ((preDistance == distance) || (distance <= 0))
         break;
      //순간이동 불가능할 때
      else
      {
         x = preX;
         y = preY;
         forwardX = preForwardX;
         forwardY = preForwardY;
 
         continue;
      }
   }
}
 
static void Action(ref Player player, Stone[] concrete, Stone[] iron, Stone[] gold, Stone[] poison, ref bool quit, Pick pick, ref int pick_num, ref bool toggle, ref bool teleport_on, ref bool effect)
{
   (생략)
   //행동
   ConsoleKey key = ReadKey(true).Key;
   switch (key)
   {
      (생략)
      //텔레포트 사용
      case ConsoleKey.Z:
         if (teleport_on && (player.Money >= 3))
         {
//텔레포트 사용시 이펙트
             if (effect)
             {
                 BackgroundColor = ConsoleColor.Red;
                 SetCursorPosition(player.x, player.y);
                 Write(player.shape);
                 System.Threading.Thread.Sleep(30);
                 BackgroundColor = ConsoleColor.Blue;
                 SetCursorPosition(player.x, player.y);
                 Write(player.shape);
                 System.Threading.Thread.Sleep(30);
                 BackgroundColor = ConsoleColor.Green;
                 SetCursorPosition(player.x, player.y);
                 Write(player.shape);
                 System.Threading.Thread.Sleep(30);
                 BackgroundColor = ConsoleColor.Black;
                 SetCursorPosition(player.x, player.y);
                 Write(player.shape);
                 effect = false;
            }
 
            player.Money -= 3;  //텔레포트 사용시 소모하는 골드
 
            player.Teleport(concrete, iron, gold, poison);  //텔레포트시 충돌 처리
            effect = true;
       }
   }
}
cs

 

 

 

 

 

6. 스테이지 진행                 

오염물질 모두 제거시 탈출구 생성

 

스크립트)

1) 스테이지별 정해진 개수(posion_MaxCount)의 오염물질 제거시 지정된 좌표의 탈출구가 생성(escape.Print())

2) 플레이어가 탈출구 위로 올라갔을 때 (if문) int자료형인 stage++하여 다음 스테이지로 이동

3) bool자료형인 clear_stage는 다음 스테이지갈 때 초기화를 위한 변수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//스테이지 설정
if (clear_stage)
{
    money = player.Money;
    Stage(stage, ref player, concrete, iron, gold, poison, ref escape, ref posion_MaxCount, ref posion_Count, ref teleport_on);
    player.Money = money;
    clear_stage = false;
}
 
//클리어했을 경우
if (posion_Count == posion_MaxCount)
{
    //탈출구 위치 생김
    escape.Print();
 
    if ((player.x == escape.X) && (player.y == escape.Y))
    {
        clear_stage = true;
        stage++;    //다음 스테이지
    }
}
cs

 

 

 

 

 

7. 전체 스크립트 및 게임 다운로드                 

 

전체 스크립트 : https://nemesis32.tistory.com/107

 

DigDog 스크립트

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..

nemesis32.tistory.com

게임 다운로드 : www.drive.google.com/open?id=1Iyn-1fyk5wpCQAv5bKMAnBidrICVXCVU

 

DigDoc.zip

 

drive.google.com

 

 

 

반응형