워리어 콤보 모작 개발일지

워리어콤보 모작 개발일지 - 02 [3 Match Puzzle - Board][연습]

다모아 2023. 9. 13. 18:20

참고

https://ninezmk2.blogspot.com/2019/11/board.html

 

2. 플레이 보드(Board) 만들기

유니티 3매치 퍼즐 게임 개발 과정을 공유하는 블로그입니다.

ninezmk2.blogspot.com


StageController ---------> Stage ----------> Board

이런 식으로 정보를 받아온다

 

ComposeStage 함수로 StageController에서 Prefab과 Transform 정보가져온걸 Stage로  -> Board로 정보를 보낸다.

 

Board의 CalcInitX, CalcInitY --> 나는 Col 값과 Row 값을 7로 했는데 그럼 원점을 기준으로 -3, -3이 Cell/Block은 (0, 0)의 위치이다.

ClacInitX,Y 는 -m_nCol/2.0f + offset 값을 해줌으로써 Cell과 Block의 원점값을 구한다.

 

Cell의 InstantiateCellObj는 인스턴스화 하고 그 인스턴스화한 애들의 parent의 transform도 다 containerObj로 바꾼다.

그리고 CellBehaviour에 컴포넌트를 보관시킨다.

 

StageBuilder는 BuildStage를 받아와서 Basic과 Empty를 row와 col 별로 구성해주는 역할을 하고있다.


Stage

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//게임판의 크기를 저장할 Stage다.
public class Stage
{
    private Board m_Board;
    public int maxRow { get { return this.m_Board.maxRow; } }
    public int maxCol { get { return this.m_Board.maxCol; } }
    public Board board { get { return m_Board; } }

    private StageBuilder stageBuilder;

    public Block[,] blocks { get { return this.m_Board.blocks; } }
    public Cell[,] cells { get { return this.m_Board.cells; } }

    public Stage(StageBuilder stageBuilder, int nRow, int nCol)
    {
        this.stageBuilder = stageBuilder;

        this.m_Board = new Board(nRow, nCol);
    }

    //StageController에서 넘김 받은 cell, block, container 정보들 Board로 넘겨주기
    internal void ComposeStage(GameObject cellPrefab, GameObject blockPrefab, Transform container)
    {
        this.m_Board.ComposeStage(cellPrefab, blockPrefab, container);
    }

    public void PrintAll()
    {
        System.Text.StringBuilder strCells = new System.Text.StringBuilder();
        System.Text.StringBuilder strBlocks = new System.Text.StringBuilder();

        for (int nRow = this.maxRow -1; nRow >=0; nRow--)
        {
            for (int nCol = 0; nCol < maxCol; nCol++)
            {
                strCells.Append($"{cells[nRow, nCol].type}, ");
                strBlocks.Append($"{blocks[nRow, nCol].type}, ");
            }
            strCells.Append("\n");
            strBlocks.Append("\n");
        }
        Debug.Log(strCells.ToString());
        Debug.Log(strBlocks.ToString());
    }
}

 

Cell

using System.Collections;
using System.Collections.Generic;
using UnityEditor.U2D.Aseprite;
using UnityEngine;

//보드의 배경을 구성한다, 변하지 않는 데이터라 DataManager의 역할이랑 비슷하다고 본다
public class Cell
{
    protected CellType m_CellType;
    public CellType type
    {
        get { return m_CellType; }
        set { m_CellType = value; }
    }

    protected CellBehaviour m_CellBehaviour;
    public CellBehaviour cellBehaviour
    {
        get { return m_CellBehaviour; }
        set
        {
            m_CellBehaviour = value;
            m_CellBehaviour.SetCell(this);
        }
    }
    public Cell(CellType cellType)
    {
        this.m_CellType = cellType;
    }

    //Cell오브젝트 인스턴스화하기
    public Cell InstantiateCellObj(GameObject cellPrefab, Transform containerObj)
    {
        GameObject newObj = GameObject.Instantiate(cellPrefab, new Vector3(0, 0, 0), Quaternion.identity);

        newObj.transform.parent = containerObj;

        this.cellBehaviour = newObj.transform.GetComponent<CellBehaviour>();

        return this;
    }

    //위치지정
    public void Move(float x, float y)
    {
        this.cellBehaviour.transform.position = new Vector3(x, y);
    }
}

 

Board

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//보드를 구성하는 데이터 저장소임.
public class Board
{
    private int m_nRow; //열
    private int m_nCol; //행

    public int maxRow { get { return m_nRow; } }
    public int maxCol { get { return m_nCol; } }

    //2중 배열의 Cell 생성 --> 보드구성
    private Cell[,] m_Cells;
    public Cell[,] cells { get { return m_Cells; } }

    //2중 배열의 Block 생성 --> 보드구성
    private Block[,] m_Blocks;
    public Block[,] blocks { get { return m_Blocks; } }

    private Transform m_Container;
    private GameObject m_CellPrefab;
    private GameObject m_BlockPrefab;
    //생성자
    public Board(int nRow, int nCol)
    {
        this.m_nRow = nRow;
        this.m_nCol = nCol;

        this.m_Cells = new Cell[nRow, nCol];
        this.m_Blocks = new Block[nRow, nCol];
    }

    //Stage에서 넘김받은 정보들 보드에 저장해두기 및 위치 
    internal void ComposeStage(GameObject cellPrefab, GameObject blockPrefab, Transform container)
    {
        this.m_BlockPrefab = blockPrefab;
        this.m_CellPrefab = cellPrefab;
        this.m_Container = container;

        float initX = CalcInitX(0.5f);
        float initY = CalcInitY(0.5f);
        for (int nRow = 0; nRow < m_nRow; nRow++)
        {
            for (int nCol = 0; nCol < m_nCol; nCol++)
            {
                Cell cell = m_Cells[nRow, nCol]?.InstantiateCellObj(cellPrefab, container);
                cell?.Move(initX + nCol, initY + nRow);
            }
        }
    }

    public float CalcInitX(float offset)
    {
        return -m_nCol / 2.0f + offset;
    }

    public float CalcInitY(float offset)
    {
        return -m_nRow / 2.0f + offset;
    }
}

 

StageController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//현재 스테이지를 총괄하는 역할
public class StageController : MonoBehaviour
{
    //초기화 여부 상태 true or false
    private bool m_blnit;
    private Stage m_Stage;

    [SerializeField]
    private Transform m_Container;
    [SerializeField]
    private GameObject m_CellPrefab;
    [SerializeField]
    private GameObject m_BlockPrefab;

    void Start()
    {
        this.InitStage();    
    }

    //초기화스테이지
    void InitStage()
    {
        // m_blnit가 true라면 반환해라
        if (m_blnit)
            return;

        this.m_blnit = true;

        BuildStage();

        this.m_Stage.PrintAll();
    }

    //스테이지 빌드
    private void BuildStage()
    {
        //스테이지 row, col 보내줘서 스테이지 구성하기
        this.m_Stage = StageBuilder.BuildStage(nStage: 0, row: 7, col: 7);
        //Cell[프리팹], Block[프리팹], Container[위치] 가져와서 Stage로 넘겨주기
        this.m_Stage.ComposeStage(this.m_CellPrefab, this.m_BlockPrefab, this.m_Container);
    }
}

 

CellBehaviour

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CellBehaviour : MonoBehaviour
{
    Cell m_Cell;
    SpriteRenderer m_SpriteRenderer;

    private void Start()
    {
        this.m_SpriteRenderer = GetComponent<SpriteRenderer>();

        this.UpdateView(false);
    }

    //받아온 cell 저장해두기
    public void SetCell(Cell cell)
    {
        this.m_Cell = cell;
    }

    //EMPTY라면 sprite를 null로 바꾸라는 함수
    public void UpdateView(bool bValueChanged)
    {
        if (this.m_Cell.type == CellType.EMPTY)
        {
            this.m_SpriteRenderer.sprite = null;
        }
    }
}

 

StageBuilder

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StageBuilder
{
    private int m_nStage;

    public StageBuilder(int nStage)
    {
        this.m_nStage = nStage;
    }

    public Stage ComposeStage(int row, int col)
    {
        Stage stage = new Stage(this, row, col);

        //Cell, Block 초기 값 생성
        for (int nRow = 0; nRow < row; nRow++)
        {
            for (int nCol = 0; nCol < col; nCol++)
            {
                stage.blocks[nRow, nCol] = SpawnBlockForStage(nRow, nCol);
                stage.cells[nRow, nCol] = SpawnCellForStage(nRow, nCol);
            }
        }

        return stage;
    }

    private Block SpawnBlockForStage(int nRow, int nCol)
    {
        return new Block(BlockType.BASIC);
    }

    private Cell SpawnCellForStage(int nRow, int nCol)
    {
        return new Cell(nRow == nCol ? CellType.EMPTY : CellType.BASIC);
    }

    public static Stage BuildStage(int nStage, int row, int col)
    {
        StageBuilder stageBuilder = new StageBuilder(0);
        Stage stage = stageBuilder.ComposeStage(row, col);

        return stage;
    }
}