1010 만들기 [켠김에 완성까지]

 


GameManagerEditor.cs 소스입니다


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

[CustomEditor(typeof(GameManager))]
public class GameManagerEditor : Editor
{
GameManager GM;

void OnEnable()
{
GM = target as GameManager;
GM.EditorRepaint += Repaint;
}

void OnDisable()
{
GM.EditorRepaint -= Repaint;
}

public override void OnInspectorGUI()
{
base.OnInspectorGUI();
GUILayout.Space(20);

EditorGUILayout.LabelField("Array");
for (int i = 9; i >= 0; i--)
{
GUILayout.BeginHorizontal();
for (int j = 0; j < 10; j++)
GM.Array[j, i] = EditorGUILayout.IntField(GM.Array[j, i], GUILayout.Width(30));
GUILayout.EndHorizontal();
}
}
}








CellScript.cs 소스입니다



using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class CellScript : MonoBehaviour
{
public int colorIndex;
public Vector3[] ShapePos;
GameManager GM;
Vector3 BlockPos, pos;

void Start()
{

BlockPos = transform.parent.position;
GM = GameObject.FindWithTag("GameManager").GetComponent<GameManager>();

ShapePos = new Vector3[transform.childCount];
for (int i = 0; i < transform.childCount; i++)
ShapePos[i] = transform.GetChild(i).localPosition;
}

IEnumerator FollowMouse() 
{
while (true) 
{
yield return null;
transform.position = Vector3.Lerp(transform.position, pos + new Vector3(0, 1, 0), Time.deltaTime * 30);
}
}


void OnMouseDown() 
{
transform.DOScale(1, 0.2f);
StartCoroutine("FollowMouse");
}

void OnMouseDrag()
{
pos = Camera.main.ScreenToWorldPoint(Input.mousePosition) + new Vector3(0, 0, 10);
}

void OnMouseUp()
{
StopCoroutine("FollowMouse");
transform.DOScale(0.6f, 0.2f);
transform.DOMove(BlockPos, 0.2f);

Vector3 lastPos = pos + new Vector3(0, 1, 0);
lastPos.x = Mathf.RoundToInt(lastPos.x);
lastPos.y = Mathf.RoundToInt(lastPos.y);

GM.BlockInput(this ,colorIndex, lastPos, ShapePos);
}

public void ForceDestroy() 
{
DOTween.KillAll();
Destroy(gameObject);
}
}









GameManager.cs 소스입니다



using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class GameManager : MonoBehaviour
{
const int SIZE = 10;
public Color[] ShapeColors;
public GameObject[] Cells;
public int[,] Array = new int[SIZE, SIZE];
public GameObject[] Shapes;
public Transform[] BlockPos;
public TextMesh ScoreTextMesh;
public event System.Action EditorRepaint = () => { };
int score;


void Start()
{
StartCoroutine(SpawnBlocks());
}

IEnumerator SpawnBlocks()
{
for (int i = 0; i < BlockPos.Length; i++)
{
yield return new WaitForSeconds(0.08f);
Transform CurShape = Instantiate(Shapes[Random.Range(0, Shapes.Length)],
//Transform CurShape = Instantiate(Shapes[0],
//Transform CurShape = Instantiate(Shapes[8],
BlockPos[i].position + new Vector3(10, 0, 0), Quaternion.identity).transform;
CurShape.SetParent(BlockPos[i]);
CurShape.DOMove(BlockPos[i].position, 0.4f);
}
yield return null;
if (!AvailCheck()) Die();
}


GameObject GetCell(int x, int y)
{
return Cells[y * SIZE + x];
}

bool InRange(int x, int y)
{
if (x < 0 || y < 0 || x >= SIZE || y >= SIZE) return false;
return true;
}

bool Possible(int x, int y)
{
if (Array[x, y] != 0) return false;
return true;
}


public void BlockInput(CellScript cellScript, int colorIndex, Vector3 lastPos, Vector3[] ShapePos)
{
for (int i = 0; i < ShapePos.Length; i++)
{
Vector3 SumPos = ShapePos[i] + lastPos;
if (!InRange((int)SumPos.x, (int)SumPos.y)) return;
if (!Possible((int)SumPos.x, (int)SumPos.y)) return;
}

for (int i = 0; i < ShapePos.Length; i++)
{
Vector3 SumPos = ShapePos[i] + lastPos;
Array[(int)SumPos.x, (int)SumPos.y] = colorIndex;
GetCell((int)SumPos.x, (int)SumPos.y).GetComponent<SpriteRenderer>().color = ShapeColors[colorIndex];
}

cellScript.ForceDestroy();
LineLogic(ShapePos.Length);
Invoke("EndTurn", 0.07f);
EditorRepaint();
}

void LineLogic(int shapePosLength)
{
// 가로세로
int oneLine = 0;
for (int i = 0; i < SIZE; i++)
{
int horizontalCount = 0;
int verticalCount = 0;
for (int j = 0; j < SIZE; j++) 
if (Array[j, i] != 0) ++horizontalCount;
if (Array[i, j] != 0) ++verticalCount;
}

if (horizontalCount == 10)
{
++oneLine;
for (int j = 0; j < SIZE; j++) Array[j, i] = -1;
}
if (verticalCount == 10)
{
++oneLine;
for (int j = 0; j < SIZE; j++) Array[i, j] = -1;
}
}

// 파괴
for (int i = 0; i < SIZE; i++)
for (int j = 0; j < SIZE; j++)
if (Array[i, j] == -1)
{
Array[i, j] = 0;
GameObject CurCell = GetCell(i, j);
var doScale = CurCell.transform.DOScale(Vector3.zero, 0.2f);
doScale.OnComplete(() =>
{
CurCell.GetComponent<SpriteRenderer>().color = ShapeColors[0];
CurCell.transform.localScale = new Vector3(0.28f, 0.28f, 1);
});
}

// 점수
score += oneLine * 10 + shapePosLength;
}


bool Putable(Vector3[] ShapePos) 
{
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
int count = 0;
for (int k = 0; k < ShapePos.Length; k++)
{
Vector3 CurShapePos = ShapePos[k] + new Vector3(i, j, 0);
if (!InRange((int)CurShapePos.x, (int)CurShapePos.y)) break;
if (!Possible((int)CurShapePos.x, (int)CurShapePos.y)) break;
++count;
}
if (count == ShapePos.Length) return true;
}
}
return false;
}


bool AvailCheck() 
{
int count = 0;
for (int i = 0; i < BlockPos.Length; i++)
{
if (BlockPos[i].childCount != 0)
{
count++;
if (Putable(BlockPos[i].GetComponentInChildren<CellScript>().ShapePos)) return true; // 가능한 블럭
}
}
return count == 0;
}


void EndTurn() 
{
ScoreTextMesh.text = score.ToString();

if (!AvailCheck()) { Die(); return; }

int count = 0;
for (int i = 0; i < BlockPos.Length; i++)
if (BlockPos[i].childCount != 0) ++count;

if (count == 0) StartCoroutine(SpawnBlocks());
}


void Die() 
{
print("죽음");
}
}