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);
}
}
}
반응형
'Project' 카테고리의 다른 글
Abilities (0) | 2023.09.01 |
---|---|
Dungeon Raiders Proto 5 (match 3 puzzle unity) (0) | 2023.03.18 |
Dungeon Raiders Proto 3 (match 3 puzzle unity) (0) | 2023.03.17 |
Dungeon Raiders Proto 2 (match 3 puzzle unity) (0) | 2023.03.17 |
Dungeon Raiders Proto 1 (match 3 puzzle unity) (0) | 2023.03.17 |