본문 바로가기

GameDevelopmentDiary/PuzzleGame

3 Match 장르 게임 3 (7-9일차 총 9시간)

작업내용

  타일 브러시

- 기능 추가: Ctl+Click 으로 직선 그리기
- 위치 및 테스트 아이콘 추가)

  맵 저장/불러오기

-   타일 맵 저장, 다른이름으로 저장 GUI 와이어 프레임
-   타일 맵의 이름 설정 후 Json 형식으로 로컬폴더에 저장
-   불러오기

 

 

직선 그리기 코드

  점이 이동하며 그리는 직선은 타일맵 위를 지나며 좌표계에서 중심각이 45도를 넘지 않는다.

  이때 점이 X축 기준으로 한 타일의 거리만큼 이동할 때, 두 개의 타일을 지나는 경우를 탐색했다.

  (더 좋은 탐색 방법이나 빼먹은 경우의 수가 있다면 조언 부탁드립니다!)

  코드  

더보기
// BrushButtonsWidget

/// <summary>
/// 시작점에서 끝점까지 그린 직선에 걸리는 타일의 타입을 선택된 브러시 타입으로 변경.
/// </summary>
public bool DrawTilesThose(TileComponent currentTileComponent)
{
    if (selectedBrush == null) return false;

    TileMapComponent tileMapComponent = PuzzleManager.instance.tileMapComponent;
    TileComponent oldSelectedTileComponent = tileMapComponent.currentSelectedTile.GetComponent<TileComponent>();
    List<List<GameObject>> tileList = tileMapComponent.tileList;

    Vector2Int startIndexes = oldSelectedTileComponent.currentTilePosition;
    Vector2Int endIndexes = currentTileComponent.currentTilePosition;
    Vector2Int distance = new Vector2Int(
        Mathf.Abs(endIndexes.x - startIndexes.x)+1,
        Mathf.Abs(endIndexes.y - startIndexes.y)+1
        );

    // 시작점과 끝점의 선을 대각선으로 하는 사각형이 가로형인지 세로형인지 구분해 사용.
    // 탐색은 가로형에 맞춰 진행되며, Tangent 값의 범위는 0~1 사이.  
    bool isWide = distance.x >= distance.y;
    int countOfLoop = isWide ? distance.x : distance.y;
    float tangent = isWide ?
        Mathf.Floor(100.0f * distance.y / distance.x) * 0.01f :
        Mathf.Floor(100.0f * distance.x / distance.y) * 0.01f;
    float stackedTangent = 0;
    float limitTangent = 1;

    int index_H = 0;
    int index_V = 0;
    
    int dir_h = startIndexes.x > endIndexes.x ? -1 : 1;
    int dir_v = startIndexes.y > endIndexes.y ? -1 : 1;

    int startX = startIndexes.x;
    int startY = startIndexes.y;

    // 2차 배열 타일맵의 탐색이지만, 반복문은 한 번만 사용된다.
    for (int i = 0; i < countOfLoop; i++)
    {
        int indexX = startX + ((isWide ? i : index_H) * dir_h);
        int indexY = startY + ((isWide ? index_V : i) * dir_v);

        if (isWide && tangent == 1)
        {
            // 시작점과 끝점의 선분 각도가 45도 인 경우 X=Y.
            DrawTileThat(tileList[indexX][indexY].GetComponent<TileComponent>());
            index_V += 1;
        }
        else
        {
            // 일반적으로 시작점과 끝점의 선분이 하나의 타일을 지나는 경우.
            stackedTangent += tangent;
            DrawTileThat(tileList[indexX][indexY].GetComponent<TileComponent>());

            // 시작점과 끝점의 선분이 두 개 이상의 타일을 지나는 경우.
            if (Mathf.Floor(stackedTangent) == limitTangent)
            {
                if (isWide) index_V += 1;
                if (!isWide) index_H += 1;
                if (stackedTangent != limitTangent)
                {
                    DrawTileThat(tileList[indexX][indexY].GetComponent<TileComponent>());
                }
                stackedTangent = 0;
            }
        }
    }

    return true;
}

 

저장 / 불러오기

  과거 엔진의 JsonUtility 내장 함수를 사용했었는데, 애셋 스토어를 들렀다가 멋진(Free!) 플러그인을 발견했다.
  JSON .Net for Unity 플러그인이다. 덕분에 손쉬운 직렬화!

 

  그리고 파일의 저장/불러오기에 사용할 브라우저 플러그인도 발견했다! 역시 멋졌다(Free!).

  이름하야 Runtime file browser.

 

  저장, 불러오기 테스트 영상.

 

< https://youtu.be/8G-eH8P3H6M >

다음 계획
  Match 케이스 확인.

  타일 폭파.