클래스 설계 및 함수

클래스는 전체적인 게임 플레이를 진행하고, 맵을 관리할 GameManager와 지렁이의 각 파트를 담당할 Snake, 적군을 담당할 Enermy로 이루어져있습니다.


1.GameManager

 // 전체적인 게임 플레이와 맵 관리.
public class GameManager : MonoBehaviour {

    int[,] map;
    bool isOut;
    List<snake> snake;
    List<enermy> enermy;

    // 매 틱마다 지렁이와 적군을 움직입니다.
    // 지렁이 헤드 위치에 따라 먹이를 먹거나, 게임을 종료시킵니다.
    // 지렁이를 방향으로 이동, 애니메이션 진행 후 
    // 만약 밖으로 나와있다면 적군의 경로 탐색으로 이동 좌표를 얻은다음 배열에 반영-> 애니메이션
    // 밖으로 나오는 버튼을 클릭하지 않은 상태면 목표지점에 지렁이가 밖에 있는지 확인후 위의 플로우 진행.
    public IEnumerator Tick()
    {

        yield return null;
    }
    // 맵을 랜덤하게 생성.
    public void MakeMap(ref int[,] _map)
    {

    }

    // 먹이를 먹었을 때, Snake 길이를 늘리는 함수
    public void Eat()
    {

    }

    // 버튼을 통해 지렁이의 이동방향을 변경합니다.
    // 동,남,서,북 차례로 방향 배열을 만들고, +- 1을 해준다.
    public void TurnLeftButton()
    {

    }
    public void TurnRightButton()
    {

    }

    // 지상으로 나가기 버튼 
    // 버튼을 누른동안에는 true, 아니라면 false
    public void TurnShowButton(bool isDown)
    {

    }
}


2. Snake

 // 지렁이의 각 부분을 담당하는 클래스
// 이동 좌표를 저장하고 좌표로 이동하는 애니메이션을 동작한다.
public class Snake : MonoBehaviour {
    // 이동할 좌표.
    IntVector2 currentPosition;
    // 밖으로 나왔는가
    bool isOut;


	public void SetSnakePosition(IntVector2 _current,bool _isOut)
    {

    }

    // 배정된 좌표로 이미지를 이동시킨다.
    public IEnumerator MoveSnake()
    {

        yield return null;
    }
}




3.Enermy


 // 움직이는 방해물
public class Enermy : MonoBehaviour {
    IntVector2 currentPosition;
    IntVector2 nextPosition;

    IntVector2 destination;
    int[,] findMap;

    // 목표물로부터 최단거리를 검색해 다음 이동할 타일을 반환.
    // findMap에서 주변 4방향 중 가장 작은 값이 있는곳으로 이동. (자신이 지나온곳은 100으로 변경)
    public IntVector2 FindNextTile(int[,] _mainMap,IntVector2 _destination)
    {
        return new IntVector2();
    }
    // 목표지점이 바뀌면 findMap을 새로 생성한다.(너비탐색)
    public void MakeFindMap(ref int[,] _findMap, int[,] _mainMap, IntVector2 _startPos, IntVector2 _destination)
    {

    }
    // 목표지점에 여전히 지렁이가 지상에 있는지 확인.
    public bool IsHide(int _map)
    {
        return false;
    }
    // 배정된 좌표로 이미지를 이동시킨다.
    public IEnumerator MoveEnermy()
    {

        yield return null;
    }
}




* 지적은 언제나 환영입니다.

Posted by 검은거북

고전의 고전의 고전 게임 지렁이 게임!!!  다만 지렁이 게임 자체의 로직은 단순하고 아마 검색하면 많이 나오지않을까..?싶네요. 그래서 저는 조금 룰을 추가하고, 연출을 추가해서 만들도록 하겠습니다. (별반 차이는 없을거 같지만)


1. 기획

맵 타일 16*16 (벽 타일을 고려하여 18*18)

  1.  맵은 먹이, 고정 방해물과 움직이는 방해물로 이루어져있다.
  2.  먹이는 하나를 먹으면 새로 하나가 랜덤한 곳에 배치된다.
  3.  방해물은 최초 배치된 갯수가 유지되며, 움직이는 방해물은 지렁이가 2칸 이동할때 1칸 이동한다.
  4.  지렁이는 직선으로만 이동하고, 오른쪽 왼쪽 버튼을 통해 직각으로 방향전환을 할 수 있다.
    1.  지렁이는 항상 중앙에서 위로 출발하며 시작한다.
  5.  지렁이는 평소 땅 속에 있다가 버튼을 통해 지상으로 나온다. 지상으로 나오면 먹이를 먹을 수 있지만, 움직이는 방해물이 쫒아온다.
  6.  움직이는 방해물은 지렁이가 땅속에 있는 동안에는 추적하거나 공격하지 못한다. (지나가도 죽지않는다.
  7.  고정 방해물은 지렁이가 땅속에 있어도 부딪히면 죽는다.
  8.  지렁이는 최초 길이가 2이고, 먹이를 먹으면 길이가 1 늘어나며, 방해물에 닿거나 자신의 몸에 닿으면 게임이 종료된다.
  9.  지렁이의 몸체 길이가 16 이상이면 새 스테이지로 넘어간다.
  10. 스테이지에 따라 게임속도와 장애물 갯수가 늘어난다.(최대 2배속 ,장애물 20개)



2. 플로우

유저

  1.  맵은 랜덤하게  생성한다. ( 먹이는 1개, 방해물은 고정 방해물 8~12개, 움직이는 방해물은 1개)
    • 하나의 맵 배열에 이동가능은 0 , 먹이는 1, 방해물은 2, 움직이는 방해물은 3으로 생성.
    • 먹이나 지상의 방해물은 지하의 지렁이와 겹칠 수 있다. bit 단위로 맵을 관리.
      • 이동가능 - 0 , 먹이 - 1 , 방해물 -2, 움직이는 방해물 -4, 지렁이 -8, 지상지렁이 -16
      • 겹칠때는 &, | 연산을 통해 해당 bit만 더하고 뺀다.
  2. 지렁이는 특정 방향으로 매초마다 움직인다. 
  3. 유저가 좌, 우 버튼 클릭시 지렁이는 해당 방향의 직각으로 이동하고, 지상 버튼 클릭하는 동안에는 지상으로 나와서 이동한다. 
    • 1) 지렁이는 좌표 리스트로 이루어진다. 리스트의 맨 뒤가 꼬리, 맨 앞이 머리이다. 
      • 이동시에는  리스트의 맨 앞의 좌표(꼬리)를 제거하고, 맨 뒤에 다음 이동할 좌표를 추가한다. 
      • 이동시에는 리스트의 맨 뒤(꼬리)부터 맨 앞(머리)까지 자신보다 뒤에있는 좌표를 배정하고, 이동 애니메이션을 실행한다. 
      • 새로 추가되는 머리는 리스트의 마지막 좌표에 현재 향하고 있는 방향을 더한다. (동서남북 중 하나)
      • 일정 시간마다 다음 칸으로 이동을 진행한다. (코루틴)
        • 몸통과 머리, 꼬리 좌표를 배정하고 난뒤 각 오브젝트는 다음 이동 좌표로 이동한다. ( 러프 이동)
        • 이동하는 애니메이션을 위해 지렁이의 몸체는 각각 오브젝트로 사용.
      • 먹이를 먹으면 길이를 1늘리며, 리스트 맨 뒤에 기존의 꼬리와 동일한 오브젝트를 추가한다.
      • 이동은 180도로 할 수 없어야하므로, 플래그를 두어 좌 우 버튼은 매 틱 한 번만 클릭이 되도록한다.
    • 2) 지렁이를 큐를 이용해 만든다. 
      • 꼬리가 제거되고, 머리가 추가되는 식으로 한다면, 큐가 맞지만, 각 몸통이 다음 타일로 이동하는 애니메이션을 진행하려면 큐는 맞지않아 보임.
  4.  먹이를 먹으면 길이가 1씩 늘고, 길이가 총 16이 되면 다음 스테이지로 이동하고, 자신의 몸이나 방해물에 닿으면 종료된다.
    1. 먹이를 먹을때 종료 판단. 이동시 배열의 값에따라 종료 판단.
움직이는 방해물
  1.  평소에는 배정된 타일에 가만히 있다가 지렁이가 밖으로 나오면 지렁이의 1/2 속도로 쫒아온다.
    1. 지렁이가 밖으로 나온는 버튼을 유저가 클릭하면 지렁이의 머리가 있는 타일을 움직이는 방해물에게 전달한다.
      • 전달된 경로를 향해 최단경로 탐색을 진행한 후 다음 타일을 저장 후, 이동한다.
      • 최단 경로 탐색 알고리즘은 무엇을?
        • A* 알고리즘 - 휴리스틱이 의미없다
        • 다익스트라
        • 플로이드
        • 너비 탐색 - 경로간 가중치도 없으니 너비탐색으로 하겠습니다.
          • 목표지점부터 시작지점까지 너비 탐색을 하여  칸마다 +1을 하여 별도의 맵에 저장한다. (시작에 도착하면 종료)
          • 시작지점에서는 저장된 맵을 보고 4방향 (자신이 지나온곳을 제외한) 중 가장 작은 값으로 이동한다. 





* 지적은 언제나 환영입니다.

Posted by 검은거북

Flood 영역을 탐색하는 로직은 아래와 같습니다.


1. SearchFlood

 
public void SearchFlood(ref int[,] _tileArray, ref bool[,] _tileSelect, int _searchTile)
    {
        IntVector2[] checkPosition =
        {
            new IntVector2(1,0),
            new IntVector2(0,1),
            new IntVector2(-1,0),
            new IntVector2(0,-1)
        };
        bool[,] visitArray = new bool[HEIGHT,WIDTH];
        IntVector2 tile = new IntVector2(0,0);

        Queue<intvector2> tileQueue = new Queue<intvector2>();
        tileQueue.Enqueue(tile);
        visitArray[tile.y, tile.x] = true;

        while (tileQueue.Count > 0)
        {
            tile = tileQueue.Dequeue();

            // 큐에서 꺼낼 때 타일을 변경한다.
            _tileArray[tile.y, tile.x] = _searchTile;
            _tileSelect[tile.y, tile.x] = true;

            for (int i = 0; i < 4; i++)
            {
                IntVector2 checkTile = new IntVector2(tile.x + checkPosition[i].x, tile.y + checkPosition[i].y);

                // 예외처리 위치가 벗어났는지, 이미 접근했던 곳인지
                if (checkTile.x<0 || checkTile.y <0 || checkTile.x>=WIDTH || checkTile.y>=HEIGHT || visitArray[checkTile.y,checkTile.x] == true)
                {
                    continue;
                }
                // 접근했다는 표식을 남긴다.
                visitArray[checkTile.y, checkTile.x] = true;

                // 선택영역이거나 클릭된 타일이면 큐에 넣는다.
                if(_tileSelect[checkTile.y,checkTile.x] == true)
                {
                    tileQueue.Enqueue(checkTile);
                }else if(_tileArray[checkTile.y, checkTile.x] == _searchTile)
                {
                    tileQueue.Enqueue(checkTile);
                }
            }

        }
    }

 최초 (0,0)의 타일을 큐에 넣고, 큐에서 하나씩 꺼내어 4방향으로 탐색하여, 선택영역이거나 클릭된 타일과 동일한 타일이면 큐에 넣습니다. 큐에 더 이상 타일이 없을 때까지 반복하여 4방향 탐색을 진행합니다.( 너비탐색이죠.)

 만약 2번째 방식 (테두리를 별도로 저장)으로 하려면 선택 영역이거나 클릭된 타일을 큐에 넣는 곳에서 그 외일때 tile 위치를 테두리 큐에 별도로 저장하면 되겠네요.


 * 위의 함수는 최초 생성 후에 최초 선택영역을 지을때도 사용가능합니다. (0,0)타일을 매개변수로 넘기면 되니까요. 


* 아래는 오브젝트와 연출이 추가된 버전입니다.





* 지적은 언제나 환영입니다.

Posted by 검은거북

블로그 이미지
프로그래밍 공부 요약 및 공부하며 발생한 궁금증과 해결과정을 포스팅합니다.
검은거북

공지사항

Yesterday
Today
Total

달력

 « |  » 2025.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

최근에 올라온 글

최근에 달린 댓글

글 보관함