Chapter 3-3. 플레이어 이동

Date:     Updated:

카테고리:

태그:

인프런에 있는 Rookiss님의 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part2: 자료구조와 알고리즘 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click

Chapter 3. 미로 준비

📜Player.cs

플레이어의 위치 결정 및 업데이트

using System;
using System.Collections.Generic;
using System.Text;

namespace Algorithm
{
    class Player
    {
        public int PosY { get; private set; }
        public int PosX { get; private set; }

        Random _random = new Random();

        Board _board;

        public void Initialize(int posY, int posX, Board board)
        {
            PosX = posX;
            PosY = posY;

            _board = board;
        }

        const int MOVE_TICK = 100;   // 0.1 초 마다 움직이게
        int _sumTick = 0;
        public void Update(int deltaTick)
        {
            _sumTick += deltaTick;
            if (_sumTick >= MOVE_TICK)
            {
                _sumTick = 0;

                // 여기에다가 0.1초마다 실행될 로직을 넣어 준다. 
                int randValue = _random.Next(0, 4);  // 4 가지의 랜덤한 방향
                switch (randValue)
                {
                    case 0:   // 상
                        if (PosY - 1 >= 0 && _board.Tile[PosY - 1, PosX] == Board.TileType.Empty)
                            PosY = PosY - 1; 
                        break;
                    case 1:   // 하
                        if (PosY + 1 < _board.Size && _board.Tile[PosY + 1, PosX] == Board.TileType.Empty)
                            PosY = PosY + 1;
                        break;
                    case 2:   // 좌
                        if (PosX - 1 >= 0 && _board.Tile[PosY, PosX - 1] == Board.TileType.Empty)
                            PosX = PosX - 1;
                        break;
                    case 3:   // 우
                        if (PosX + 1 < _board.Size && _board.Tile[PosY, PosX + 1] == Board.TileType.Empty)
                            PosX = PosX + 1;
                        break;
                }
            }
        }
    }
}

  • 플레이어의 위치에 관한 기능을 담당한다. 👉 PosX, PosY
    • 플레이어의 위치를 결정할 땐 벽이면 갈 수 없고 벽이 아닐 때만 갈 수 있어서 미로 타일에 대한 정보가 필요하다. 👉 _board
  • Initialize
    • 인수로 들어온 값으로 PosX, PosY, _board 초기화
  • Update(int deltaTick)
    • 플레이어의 위치 PosX, PosY 를 업데이트 한다. 단, MOVE_TICK 시간이 경과될 때 마다만 실행

      • 메인 함수에서 매 프레임마다 📜Player의 이 Update(int deltaTick) 함수를 호출할 것이고 그때마다 매개 변수인 deltaTick에 프레임 간 간격 시간을 인수로 보낼 것이다. 매 프레임 때 실행될 때마다 _sumTick에 프레임 경과 시간이 더해지고 이게 MOVE_TICK 시간을 넘기면 그 때서야 실행할 것이다!
        • 예를 들어, 30 프레임마다 이 Update(int deltaTick) 함수가 실행 되고(1/30 = 0.033초 = 33 밀리세컨즈)마다 실행됨), MOVE_TICK 값이 100 이라면 (100 밀리세컨즈 = 0.1초)
          • 대략 3 ~ 4 프레임 간격으로 Update(int deltaTick) 함수가 실행될 것이다. 33 * 4 > 100
          • MOVE_TICK을 경과할 때면, 다시 _sumTick을 0 으로 초기화
    • 4 개의 방향 중 랜덤하게 선택하여 그 방향으로 갈 수 있다면 플레이어를 이동시킨다.
      • 그 방향이 갈수 있는 곳인지(벽이 아닌 곳인지), 타일 인덱스를 초과하는 곳은 아닌지 먼저 체크하고
        • 갈 수 있다면 해당 방향으로 이동.


📜Board.cs

미로에 관한 정보, 미로 렌더링

using System;
using System.Collections.Generic;
using System.Text;

namespace Algorithm
{
    class Board
    {
        const char CIRCLE = '\u25cf';

        public TileType[,] Tile { get; private set; }  // 맵의 타일들을 담을 배열
        public int Size { get; private set; }

        Player _player;

        public enum TileType
        {
            Empty,   // 갈 수 있는 타일
            Wall,    // 갈 수 없는 타일
        }

        public void Initialize(int size, Player player)
        {
            if (size % 2 == 0)
                return;

            _player = player;

            Tile = new TileType[size, size];
            Size = size;

            // GenerateByBinaryTree();
            GenerateBySideWinder();
        }

        public void Render()
        {
            ConsoleColor prevColor = Console.ForegroundColor;

            for (int y = 0; y < Size; y++)
            {
                for (int x = 0; x < Size; x++)
                {
                    // 플레이어 좌표 갖고 와서, 그 좌표랑 현재 y, x 가 일치하면 플레이어 전용 색상인 파란색으로 표시
                    if (y == _player.PosY && x == _player.PosX)
                        Console.ForegroundColor = ConsoleColor.Blue;
                    else
                        Console.ForegroundColor = GetTileColor(Tile[y, x]);

                    Console.Write(CIRCLE);  
                }
                Console.WriteLine(); 
            }
        }


        void GenerateBySideWinder()
        {
             // ...
        }

        void GenerateByBinaryTree()
        {
             // ...
        }

        ConsoleColor GetTileColor(TileType type)
        {
            // ...
        }
    }
}

  • 미로 렌더링시 플레이어의 위치를 알아야 하므로 Player _player 📜Player 멤버 선언이 필요하다.
  • 미로 렌더링시 미로의 모든 타일을 검사할 때, 해당 타일이 플레이어의 현재 위치와 일치하다면 파란색으로 그려준다.


📜Prdogram.cs

메인 함수. 본격 플레이. 무한 루프로 1️⃣ 입력 2️⃣ 로직 3️⃣ 렌더링 한다.

using System;

namespace Algorithm
{
    class Program
    {
        static void Main(string[] args)
        {
            Board board = new Board();

            Player player = new Player();
            
            board.Initialize(25, player);  // 플레이어보다 먼저 이니셜라이징이 이루어져야 함
            player.Initialize(1, 1, board);

            Console.CursorVisible = false;

            const int WAIT_TICK = 1000 / 30; // 1000밀리세컨즈/30 = 1초/30 = 1/30초 = 33밀리세컨즈 쯤 = 30 프레임 환경에서 1 프레임당 걸리는 시간

            int lastTick = 0;
            while (true)
            {
                #region 프레임 관리
                int currentTick = System.Environment.TickCount;  // 밀리 세컨즈로 나타낸 현재시간.  1초 = 1000 밀리세컨즈
                if (currentTick - lastTick < WAIT_TICK) // 만약 경과한 시간이 1/30초보다 작다면 아래 모든 부분을 실행하지 않고 다시 위로
                    continue;
                int deltaTick = currentTick - lastTick; // 1프레임 지날 때마다 업데이트
                lastTick = currentTick;  // 마지막 측정 시간 업뎃
                #endregion

                // 1.입력

                // 2.로직
                player.Update(deltaTick);

                // 3.렌더링
                Console.SetCursorPosition(0, 0);
                board.Render();
            }
        }
    }
}

board.Initialize(25, player);
player.Initialize(1, 1, board);

📢 미로의 초기화가 플레이어 초기화보다 먼저 이루어져야 한다!! 📜Player 에서 플레이어의 위치를 업뎃 할 때 📜Board 의 미로 배열의 타일를 가져와 벽인지 벽이 아닌지 따져야 하기 때문이다. 이 순서를 뒤바꾼 바람에 계속 런타임 에러가 났는데 이유를 찾느라 애먹었다. 😡

image

4 개의 방향 중 랜덤하게 한 방향을 선택해서 갈 수 있다면 가기 때문에 굉장히.. 바보 같이.. 갔던 길 다시 되돌아가고.. 그러는 모습을 볼 수 있다.



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

댓글남기기