Dungeon Raiders Proto 4 (match 3 puzzle unity)

Project 2023. 3. 17. 18:07
반응형

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.U2D;
using TMPro;

public class Cell : MonoBehaviour
{
    public enum eBlockType { 
        coin = 0, enemy, potion, shield, sword
    }

    public GameObject focusGo;
    public GameObject focusGo2;
    public SpriteRenderer sr;
    public eBlockType blockType;
    public TMP_Text txtHp;

    private int hp;

    public int Hp {
        get {
            return this.hp;
        }
        set {
            this.hp = value;
            Debug.LogFormat("-----> {0},{1} , hp: {2}", this.row, this.col, this.hp);
            this.txtHp.text = this.hp.ToString();
        }
    }

    public bool isSelected = false;
    public int row;
    public int col;

    public void Init(int row, int col, eBlockType blockType) {
        this.row = row;
        this.col = col;
        this.blockType = blockType;
        if (this.blockType == eBlockType.enemy) this.Hp = 5;
        else this.Hp = 1;
        this.txtHp.gameObject.SetActive(this.blockType == eBlockType.enemy);

        var iconName = blockType.ToString();
        Debug.LogFormat("iconName: {0}", iconName);
        var sp1 = Game.instance.atlas.GetSprite(iconName);
        this.sr.sprite = sp1;
        var sp2 = Game.instance.atlas.GetSprite(iconName + "_focus");
        this.focusGo2.GetComponent<SpriteRenderer>().sprite = sp2;
        this.focusGo2.SetActive(false);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System;
using DG.Tweening;
using UnityEngine.UI;
using UnityEngine.U2D;

public class Game : MonoBehaviour
{
    public GameObject cellPrefab;
    public int maxRow;
    public int maxCol;
    public LineRenderer line;
    private Cell[,] cells;
    public RectTransform fontTrans;
    public SpriteAtlas atlas;

    public static Game instance;
    private void Awake()
    {
        Game.instance = this;
    }

    void Start()
    {
        this.cells = new Cell[this.maxRow, this.maxCol];

        for (int i = 0; i < maxRow; i++)
        {
            for (int j = 0; j < maxCol; j++)
            {
                var pos = new Vector2(j, -i);
                var go = Instantiate(this.cellPrefab, pos, Quaternion.identity);
                go.name = string.Format("({0},{1})", i, j);
                var cell = go.GetComponent<Cell>();
                this.cells[i, j] = cell;
                var rand = UnityEngine.Random.Range(0, 5);
                cell.Init(i, j, (Cell.eBlockType)rand);
            }
        }
    }


    private bool isDown = false;
    private List<Cell> list = new List<Cell>();
    private Cell currentCell;
    private Cell.eBlockType selectedBlockType;
    private int damage = 0;

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            this.isDown = true;
        }
        else if (Input.GetMouseButtonUp(0))
        {
            this.isDown = false;
            this.currentCell.focusGo.SetActive(false);
            this.currentCell.focusGo2.SetActive(false);
            this.currentCell = null;
            

            //3개 이상이면 블록 제거 
            if (list.Count >= 3)
            {
                //제거 
                foreach (var cell in this.list)
                {
                    if (this.cells[cell.row, cell.col].blockType == Cell.eBlockType.enemy)
                    {
                        this.cells[cell.row, cell.col].focusGo2.SetActive(false);

                        Debug.LogFormat("this.damage: {0}", this.damage);

                        this.cells[cell.row, cell.col].Hp -= this.damage;

                        if (this.cells[cell.row, cell.col].Hp <= 0) {
                            this.cells[cell.row, cell.col] = null;
                        }
                    }
                    else {
                        this.cells[cell.row, cell.col].Hp = 0;
                        this.cells[cell.row, cell.col] = null;
                    }
                }

                foreach (var cell in this.list) {
                    if (cell.Hp <= 0) {
                        cell.gameObject.SetActive(false);
                    }
                }
                    

                //라인렌더러 초기화
                this.line.positionCount = 0;

                //폰트 비활성화 
                this.fontTrans.gameObject.SetActive(false);

                this.StartCoroutine(this.CoDecreaseRow( ()=> {

                    Debug.Log("이동완료");

                    this.PrintCells();

                    //빈공간 찾아 새로운 블록 만들기 
                    float offset = 3f;
                    for (int i = 0; i < maxRow; i++) {
                        for (int j = 0; j < maxCol; j++)
                        {
                            var c = this.cells[i, j];
                            if (c == null)
                            {
                                //새로운 블록 생성 위치 
                                var x = j;
                                var y = -1 * i;
                                var tpos = new Vector3(x, y, 0);
                                var go = Instantiate(this.cellPrefab, new Vector3(x, y + offset, 0), Quaternion.identity);
                                go.name = string.Format("({0},{1})", i, j);
                                var cell = go.GetComponent<Cell>();
                                var rand = UnityEngine.Random.Range(0, 5);
                                cell.Init(i, j, (Cell.eBlockType)rand);
                                this.cells[i, j] = cell;

                                //tween 
                                go.transform.DOMoveY(tpos.y, 0.2f).SetEase(Ease.Linear);
                            }
                        }
                    }

                    this.PrintCells();

                }));

            }
            else
            {
                Debug.Log("연결된 블록 갯수 부족");
                foreach (var cell in this.list)
                    cell.focusGo2.SetActive(false);

                //라인렌더러 초기화
                this.line.positionCount = 0;

                //폰트 비활성화 
                this.fontTrans.gameObject.SetActive(false);

            }
            this.list.Clear();

            this.damage = 0;

        }

        if (this.isDown) {
            var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            var hit = Physics2D.Raycast(ray.origin, ray.direction);
            Cell prevCell = null;

            if (hit.collider != null) {
                var cell = hit.collider.GetComponent<Cell>();

                if (this.currentCell != cell) {

                    if (this.currentCell != null) {
                        prevCell = this.currentCell;
                        prevCell.focusGo.SetActive(false);
                    }

                    this.currentCell = cell;

                    if (!list.Contains(this.currentCell))
                    {
                        //처음 블록 선택 
                        if (this.list.Count == 0)
                        {
                            
                            list.Add(this.currentCell);
                            this.currentCell.focusGo.SetActive(true);
                            this.currentCell.focusGo2.SetActive(true);

                            //처음 블록 타입 저장 
                            this.selectedBlockType = this.currentCell.blockType;

                            Debug.LogFormat("start : {0}", this.selectedBlockType);

                        }
                        else {
                            //마지막 선택된 셀과 인접해 있는가?
                            var dis = Vector3.Distance(list[list.Count - 1].transform.position, this.currentCell.transform.position);

                            //Debug.Log(dis);

                            this.currentCell.focusGo.SetActive(true);

                            if (dis > 1.42f)
                            {
                                Debug.Log("인접해 있지 않음");
                                
                            }
                            else {

                                Debug.LogFormat("{0}, {1}", this.selectedBlockType, this.currentCell.blockType);

                                //인접해 있음 
                                //블록 타입 확인 
                                if (this.selectedBlockType == Cell.eBlockType.sword || this.selectedBlockType == Cell.eBlockType.enemy)
                                {

                                    //처음 선택한 블록 타입이 적이거나 칼이면 
                                    //적 또는 칼만 선택 가능 

                                    if (this.currentCell.blockType == Cell.eBlockType.sword || this.currentCell.blockType == Cell.eBlockType.enemy)
                                    {
                                        this.list.Add(this.currentCell);
                                        this.currentCell.focusGo.SetActive(true);
                                        this.currentCell.focusGo2.SetActive(true);

                                        //라인 렌더러 
                                        this.UpdateLine();

                                        //폰트 위치 
                                        this.UpdateFontPosition();
                                    }
                                }
                                else {
                                    //그게 아니라면 같은것만 선택 가능 
                                    if (this.currentCell.blockType == this.selectedBlockType)
                                    {
                                        this.list.Add(this.currentCell);
                                        this.currentCell.focusGo.SetActive(true);
                                        this.currentCell.focusGo2.SetActive(true);

                                        //라인 렌더러 
                                        this.UpdateLine();

                                        //폰트 위치 
                                        this.UpdateFontPosition();
                                    }
                                    else {
                                        Debug.Log("다른 블록 타입 입니다.");
                                    }
                                }

                                
                            }
                        }

                        //폰트 활성화 
                        this.fontTrans.gameObject.SetActive(true);

                        //폰트 포지션 
                        this.UpdateFontPosition();

                    }
                    else
                    {
                        Debug.Log("이미 선택된 cell");
                        var idx = list.IndexOf(this.currentCell);
                        for (int i = idx + 1; i < list.Count; i++) {
                            list[i].focusGo.SetActive(false);
                            list[i].focusGo2.SetActive(false);
                        }
                        list.RemoveRange(idx + 1, list.Count - 1 - idx);
                        this.currentCell.focusGo.SetActive(true);

                        //라인 렌더러 
                        this.UpdateLine();

                        //폰트 활성화 
                        this.fontTrans.gameObject.SetActive(true);

                        //폰트 위치 
                        this.UpdateFontPosition();
                    }
                }
            }
        }

    }

    private void UpdateFontPosition() {
        var pos = this.currentCell.transform.position;
        pos.z = 0;
        float offsetY = 120;
        Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(Camera.main, pos);
        screenPoint.y += offsetY;
        this.fontTrans.position = screenPoint;
        var txtCnt = this.fontTrans.GetComponent<Text>();

        //처음 선택한 블록이 칼또는 적이라면 
        //리스트에 있는 블록들중 칼이 몇개 인가를 표시 
        if (this.selectedBlockType == Cell.eBlockType.enemy || this.selectedBlockType == Cell.eBlockType.sword)
        {
            var swords = this.list.Where(x => x.blockType == Cell.eBlockType.sword).Count();
            this.damage = swords + 1;
            txtCnt.text = string.Format("{0}", damage);
            
        }
        else 
        {
            txtCnt.text = string.Format("{0}", this.list.Count);
        }
        
    }


    private void PrintCells()
    {
        //빈공간 찾기 
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        for (int i = 0; i < maxRow; i++)
        {
            for (int j = 0; j < maxCol; j++)
            {
                var c = this.cells[i, j];
                if (c == null)
                {
                    sb.Append(string.Format("<color=yellow>{0},{1}</color> ", i, j));
                }
                else
                {
                    sb.Append("cell ");
                }
            }
            sb.AppendLine();
        }

        Debug.Log(sb.ToString());
    }

    private IEnumerator CoDecreaseRow(System.Action callback) {
        
        while (true)
        {
            var set = this.CalcMoveActionBlocks();
            if (set.Count == 0)
            {
                callback();
                break;
            }
            foreach (var x in set)
            {
                //Debug.LogFormat("{0},{1} -> {2},{3}", x.Item1, x.Item2, x.Item1 + 1, x.Item2);
                var cell = this.cells[x.Item1, x.Item2];
                this.cells[x.Item1, x.Item2] = null;
                this.cells[x.Item1 + 1, x.Item2] = cell;
                this.cells[x.Item1 + 1, x.Item2].row = x.Item1 + 1;
                this.cells[x.Item1 + 1, x.Item2].gameObject.name = string.Format("({0},{1})", this.cells[x.Item1 + 1, x.Item2].row, this.cells[x.Item1 + 1, x.Item2].col);

                cell.transform.DOMoveY(cell.transform.position.y - 1, 0.1f).SetEase(Ease.Linear);
                
            }
            yield return new WaitForSeconds(0.1f);
        }

        yield return null;
        
    }

    private HashSet<Tuple<int, int>> CalcMoveActionBlocks() {
        HashSet<Tuple<int, int>> set = new HashSet<Tuple<int, int>>();
        for (int i = this.maxRow - 1; i >= 0; i--)
        {
            for (int j = 0; j < this.maxCol; j++)
            {
                var cell = this.cells[i, j];
                if (cell == null)
                {
                    //Debug.LogErrorFormat("{0},{1}", i, j);
                    for (int row = i; row >= 0; row--)
                    {
                        if (this.cells[row, j] != null)
                        {
                            //Debug.LogFormat("---------->{0},{1}", row, j);
                            set.Add(new Tuple<int, int>(row, j));
                            break;
                        }
                    }
                }
            }
        }
        return set;
    }

    private void UpdateLine() {
        this.line.positionCount = this.list.Count;
        for (int i = 0; i < this.list.Count; i++)
        {
            var pos = this.list[i].transform.position;
            pos.z = 0;
            this.line.SetPosition(i, pos);
        }
    }
}
반응형
: