Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
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
Archives
Today
Total
관리 메뉴

시작은 0부터

21. 레이싱게임 - 2차원 배열로 장애물 낙하 구현 본문

C# 학습일지

21. 레이싱게임 - 2차원 배열로 장애물 낙하 구현

0base 2022. 7. 28. 00:03

  1차원배열에 장애물이 낙하할 x값을 랜덤하게 넣어 동일한 Y값에 일렬로 낙하하는 것은 구현했었다. 그런데 장애물이 한줄로만 떨어지는 것이 아닌 동시다발적으로 계속해서 떨어지는 것은 구현하지 못했었다. 그래서 지뢰찾기를 다 끝내고 이전에 제대로 끝내지 못했던 지렁이게임과 레이싱게임을 다시 손봤다.

 

지렁이게임은 비교적 순조롭게 수정했다. 간혹 2P의 캐릭터 꼬리가 증가되지 않는 현상이 있었는데 코드를 잘 들여다보니 2P가 아닌 1P의 증가로 되어있어 그러한 오류가 생겼었고, 꼬리끼리 부딪혀도 죽도록 만들었는데 상대방의 꼬리에 부딪히지도 않았는데 죽었다는 판정이 떠서 왜 그런가 했더니 충돌판정을 딜레이 안에 넣지 않아서 프레임이 갱신되기도 전에 충돌판정이 되어 랜더로 이미지를 출력했을 때는 부딪히지 않았지만 프로그램상으로는 부딪혔다고 판정이 되어있어서 그러한 오류가 생겼던 것이었다.

 

지렁이게임의 미구현부분은 미미한 문제였지만 레이싱게임은 어려웠다. 2차원 배열에 대한 개념이 제대로 잡혀있지 않아서 인지 일렬로 떨어지는 것은 초기에 떨어질 때 x값만 랜덤값을 주고 이후에는 Update마다 y++를 하여 따로 y값을 주지 않더라도 그냥 알아서 떨어지도록 만들었다. 그리고 y가 맨아래에 도달하면 다시 위치를 0으로 돌림으로써 한줄만 반복해서 사용했는데 동시에 여러줄이 떨어진다는게 감이 안왔다. 동기의 도움을 받아 2차원배열로 맵의 좌표를 만들고 각 좌표에 값을 넣어 그 값에 따라 장애물, 빈공간 등을 구분하는 방법을 참고하여 만들었다. 그리고 떨어지는 것을 구현하기 위해서는 y값을 증가시켜야해서 y+1값에 y값을 넣어 한칸씩 아래로 떨어지도록 만들었다.

 

장애물 낙하 코드

public void Update() //적 위치 변경
        {
            for (int y = mapY; y > -1; y--)
            {
                for (int x = 0; x < mapX; x++)
                {
                    if (y + 1 < mapY - 1)
                    {
                        map[y + 1, x] = map[y, x];
                    }
                }
            }

            for(int x = 0; x < mapX; x++) //첫째 줄 값을 다 0으로
            {
                map[0, x] = 0;
            }

        }

아래쪽 값은 위의 값을 받기 때문에 따로 값을 넣지 않아도 되는 구조인데 그 생각을 못하고 1차원배열로 했을 때처럼 마지막에 도달하면 지워줘야된다는 강박때문에 처음에는 맵을 그리고 Y값이 맵의 맨 아래 위치에 도달하면 값을 0, 공백으로 만들어 지우는 구조를 짰더니 이전 위치값을 지우지 않아 일렬로 떨어지고 멈추는 현상이 발생했었다. 그리고 좌표를 받는 조건을 인덱스로 받아야하는데 배열을 비교함으로써 배열 인덱스가 아닌 배열 값을 비교하는 치명적인 실수를 저질렀다.

처음에는 그 조건문을 잘못쓴걸 인지하지 못하고 y증감식 아래에 Y열 0번째 x값이 0이 아닐경우 y,x 값을 0으로 바꾼다는 코드를 짰더니 위에서는 오른쪽에서 부터 블록이 날라오면서 아래로 떨어지는 기괴한 현상이 발생했다. 결국 위 코드로 수정하여 레이싱게임은 최종완료했다.

 

▼ 맨 위 줄에서 랜덤한 x값에 장애물을 생성하는 코드

public void EnemyInstance() //맨 위에서 적 랜덤 생성
        {
            checkFirstLine = false;
            for (int x = 0; x < mapX; x++) { if (map[0, x] != 0) { checkFirstLine = true; break; } }

            if (checkFirstLine == false)
            {
                int enemyCount = rd.Next(0, 5);
                int[] enemyXList = new int[enemyCount];
                for (int i = 0; i < enemyCount; i++)
                {
                    enemyXList[i] = rd.Next(0, mapX);
                    if (xList.Contains(enemyXList[i]) == true) //중복제거
                    { i--; continue; }

                    xList.Add(enemyXList[i]);
                }

                for (int i = 0; i < xList.Count; i++)
                {
                    map[0, xList[i]] = 1;
                }
                xList.Clear();
            }
        }

랜덤한 x값에 랜덤한 수 만큼 생성하는 것은 List를 활용하는 것이 간편했다. 배열은 배열 내에서 중복값을 제거하는 기능이 따로 없고 코드로 구현을 해야했지만, List는 Contains( ) 기능으로 리스트 내에 해당 값이 포함되어있는지를 판단하여 중복을 간편하게 방지할 수 있는 기능이 있어 랜덤값을 넣어줄 때는 List를 사용했다.

 

▼ 아이템 드랍 구현

        public void ItemInstance()
        {
            int time = GameLoop.GetFrameCount();
            if (time == 10)
            {
                int starPoint = 0;
                while (true)
                {
                    starPoint = rd.Next(0, mapX);
                    if (map[0, starPoint] == 0) { break; }
                }
                map[0, starPoint] = 2;
            }
        }

충돌시 점수가 올라가는 아이템 생성 코드. 아이템은 장애물처럼 계속해서 떨어지지 않고 일정한 텀을 두고 떨어지도록 구현하기 위해 프레임을 갱신하는 딜레이가 한번 돌때마다 증가하는 변수를 만들어 그 변수가 특정 값을 만족했을 때 실행되는 방식으로 텀을 주었다. 그리고 장애물과 같은 x열에 배치되면 안되기 때문에 while문으로 해당 좌표에 장애물이 없을 때까지 반복해서 랜덤값을 주는 방법을 사용했다.