TIL

[멋쟁이사자처럼 부트캠프 TIL 회고] 유니티 게임개발 3기 47일차 TICTACTOE제작3

HYttt 2025. 2. 5. 17:40

TICTACTOE 제작

블록의 색상 변경

  • 같은 모양 3개가 완성된 줄에 색상표시하기
  • 블록의 색상을 변경하는 함수는 Block 클래스에 있음
  • BlockController GameManager로부터 플레이어 타입과 완성된 줄의 인덱스 튜플 배열을 받아 O 승리 이면 파란색, X 승리 이면 빨간색으로 변경
using System;
using UnityEngine;

[RequireComponent(typeof(SpriteRenderer))]
public class Block : MonoBehaviour
{
    [SerializeField] private Sprite oSprite;
    [SerializeField] private Sprite xSprite;
    [SerializeField] private SpriteRenderer markerSpriteRenderer;

    public enum MarkerType{None, O, X}
    
    public delegate void OnBlockClicked(int index);
    
    private OnBlockClicked _onBlockClicked;
    private int _blockIndex;
    private SpriteRenderer _spriteRenderer;
    private Color _defaultColor;
    private void Awake()
    {
        _spriteRenderer = GetComponent<SpriteRenderer>();
        _defaultColor = _spriteRenderer.color;
    }

    /// <summary>
    /// 블럭의 색상을 변경하는 함수
    /// </summary>
    /// <param name="color">색상</param>
    public void SetColor(Color color)
    {
        _spriteRenderer.color = color;
    }

    public void InitMarker(int blockIndex, OnBlockClicked onBlockClicked)
    {
        _blockIndex = blockIndex;
        SetMarker(MarkerType.None);
        this._onBlockClicked = onBlockClicked;
        SetColor(_defaultColor);
    }
   
    public void SetMarker(MarkerType markerType)
    {
        // 생략
    }

    private void OnMouseUpAsButton()
    {
        _onBlockClicked?.Invoke(_blockIndex);
    }
}
using UnityEngine;

public class BlockController : MonoBehaviour
{
    [SerializeField] private Block[] blocks;

    public delegate void OnBlockClickedDelegate(int row, int col);
    public OnBlockClickedDelegate onBlockClickedDelegate;
    public void InitBlocks()
    {
        for (int i = 0; i < blocks.Length; i++)
        {
            blocks[i].InitMarker(i, blockIndex =>
            {
                var clickedRow = blockIndex / 3;
                var clickedCol = blockIndex % 3;
                
                onBlockClickedDelegate?.Invoke(clickedRow, clickedCol);
            });
        }
    }
    
    public void PlaceMarker(Block.MarkerType markerType, int row, int col)
    {
        // row, col를 index로 변환
        var markerIndex = row * 3 + col;
        
        // Block에게 마커 표시
        blocks[markerIndex].SetMarker(markerType);
    }
    
    
    
    public void SetBlockColor(GameManager.PlayerType playerType, (int row, int col)[] blockPositions)
    {
        if(playerType == GameManager.PlayerType.None) return;

        foreach (var blockPosition in blockPositions)
        {
            var blockIndex = blockPosition.row * 3 + blockPosition.col;
            Color markerColor;
            if(playerType == GameManager.PlayerType.PlayerA)
                markerColor = new Color32(0, 166, 255, 255);
            else if (playerType == GameManager.PlayerType.PlayerB)
            {
                markerColor = new Color32(255, 0, 94, 255);
            }
            else
            {
                markerColor = Color.black;
            }
            blocks[blockIndex].SetColor(markerColor);
        }
    }
}

 

플레이어의 턴을 표시하는 UI

  • 현재 차례의 플레이어의 마커가 더 밝게 표시되도록 구현
  • Canvas Group의 Alpha값을 조절
  • 게임이 종료되면 게임종료 버튼 표시
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameUIController : MonoBehaviour
{
    [SerializeField] private CanvasGroup canvasGroupA;
    [SerializeField] private CanvasGroup canvasGroupB;
    [SerializeField] private Button gameOverButton;
    
    public enum GameUIMode
    {
        Init,
        TurnA,
        TurnB,
        GameOver
    }

    private const float DisableAlpha = 0.5f;
    private const float EnableAlpha = 1f;
    
    public void SetGameUIMode(GameUIMode mode)
    {
        switch (mode)
        {
            case GameUIMode.Init:
                canvasGroupA.gameObject.SetActive(true);
                canvasGroupB.gameObject.SetActive(true);
                gameOverButton.gameObject.SetActive(false);
                
                canvasGroupA.alpha = DisableAlpha;
                canvasGroupB.alpha = DisableAlpha;
                break;
            case GameUIMode.TurnA:
                canvasGroupA.gameObject.SetActive(true);
                canvasGroupB.gameObject.SetActive(true);
                gameOverButton.gameObject.SetActive(false);
                
                canvasGroupA.alpha = EnableAlpha;
                canvasGroupB.alpha = DisableAlpha;
                break;
            case GameUIMode.TurnB:
                canvasGroupA.gameObject.SetActive(true);
                canvasGroupB.gameObject.SetActive(true);
                gameOverButton.gameObject.SetActive(false);
                
                canvasGroupA.alpha = DisableAlpha;
                canvasGroupB.alpha = EnableAlpha;
                break;
            case GameUIMode.GameOver:
                canvasGroupA.gameObject.SetActive(false);
                canvasGroupB.gameObject.SetActive(false);
                gameOverButton.gameObject.SetActive(true);
                break;
        }
    }

    public void OnClickGameOverButton()
    {
        // TODO : 구현해야 함..
    }
}

 

Main Scene 분리

  • Main Scene 과 Game Scene을 분리
  • 플레이 버튼 클릭시 GameScene 로드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class MainPanelController : MonoBehaviour
{
    public void OnClickSinglePlayButton()
    {
        SceneManager.LoadScene("GameScene");
    }

    public void OnClickDualPlayButton()
    {
        SceneManager.LoadScene("GameScene");
    }

    public void OnClickSettingsButton()
    {
        
    }
}