255 lines
7.9 KiB
C#
255 lines
7.9 KiB
C#
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
using BoardState = System.Collections.Generic.List<System.Collections.Generic.List<TileInfo>>;
|
|||
|
using TileList = System.Collections.Generic.List<TileInfo>;
|
|||
|
|
|||
|
using UnityEngine.UI;
|
|||
|
using TMPro;
|
|||
|
|
|||
|
public class GameBoardRender : MonoBehaviour {
|
|||
|
// Auto assign so that I can copy stuff around like a shmuk - Texel
|
|||
|
private GameBoard board;
|
|||
|
|
|||
|
public TMPro.TextMeshPro ScoreText;
|
|||
|
public TMPro.TextMeshPro ComboText;
|
|||
|
|
|||
|
[Header("Positioning")]
|
|||
|
public Transform basePoint;
|
|||
|
public float width, height;
|
|||
|
|
|||
|
[Header("Extra")]
|
|||
|
public TileRender place1;
|
|||
|
public TileRender place2;
|
|||
|
public TileRender place3, place4; // Next tile display
|
|||
|
|
|||
|
// Dramatically slow falls in combo mode
|
|||
|
public float tileSpeed => board.Combo > 0 ? 15 : 20;
|
|||
|
|
|||
|
GameObject tilePrefab => GameBoardInstance.instance.tilePrefab;
|
|||
|
|
|||
|
void Start() {
|
|||
|
// Auto-assign off same object - Texel
|
|||
|
board = GetComponent<GameBoard>();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
float comboTime = 0f;
|
|||
|
float comboDuration = 3f;
|
|||
|
public void SetComboLevel(int num) {
|
|||
|
if (!ComboText) return;
|
|||
|
if (num == 0) return;
|
|||
|
|
|||
|
comboTime = Time.time;
|
|||
|
if (num == 1)
|
|||
|
ComboText.text = "NICE";
|
|||
|
else
|
|||
|
ComboText.text = string.Format("{0}x COMBO", num);
|
|||
|
}
|
|||
|
|
|||
|
public void SetScoreValue(int value) {
|
|||
|
if (ScoreText) ScoreText.text = string.Format("{0:D6}", value);
|
|||
|
}
|
|||
|
|
|||
|
Transform corner;
|
|||
|
private void Awake() {
|
|||
|
var pos = basePoint.position;
|
|||
|
var rowOffset = basePoint.right * width;
|
|||
|
var columnOffset = basePoint.up * height;
|
|||
|
pos += rowOffset * 0.5f + columnOffset * 0.5f;
|
|||
|
for (var i = 0; i < GameBoard.COLUMN; ++i) {
|
|||
|
var t = new GameObject("column" + i.ToString()).transform;
|
|||
|
t.SetParent(basePoint);
|
|||
|
t.position = pos + rowOffset * i;
|
|||
|
t.localRotation = Quaternion.identity;
|
|||
|
t.localScale = Vector3.one;
|
|||
|
}
|
|||
|
|
|||
|
corner = new GameObject("corner").transform;
|
|||
|
corner.SetParent(basePoint.GetChild(0));
|
|||
|
corner.localPosition = Vector3.zero;
|
|||
|
corner.localRotation = Quaternion.identity;
|
|||
|
corner.localScale = Vector3.one;
|
|||
|
corner.SetParent(transform, true);
|
|||
|
|
|||
|
place1 = Instantiate(GameBoardInstance.instance.tilePrefab, corner).GetComponent<TileRender>();
|
|||
|
place2 = Instantiate(GameBoardInstance.instance.tilePrefab, corner).GetComponent<TileRender>();
|
|||
|
|
|||
|
place3 = Instantiate(GameBoardInstance.instance.tilePrefab, corner).GetComponent<TileRender>();
|
|||
|
place4 = Instantiate(GameBoardInstance.instance.tilePrefab, corner).GetComponent<TileRender>();
|
|||
|
|
|||
|
place1.transform.localPosition = Vector3.zero;
|
|||
|
place2.transform.localPosition = Vector3.zero;
|
|||
|
place3.transform.localPosition = Vector3.zero;
|
|||
|
place4.transform.localPosition = Vector3.zero;
|
|||
|
}
|
|||
|
|
|||
|
public void Render(BoardState state) {
|
|||
|
if (Time.time + comboDuration > comboTime) {
|
|||
|
if (ComboText) ComboText.text = "";
|
|||
|
}
|
|||
|
|
|||
|
// render
|
|||
|
for (var i = 0; i < state.Count; ++i) {
|
|||
|
var root = basePoint.GetChild(i);
|
|||
|
var t = state[i];
|
|||
|
RebuildStack(root, t);
|
|||
|
DrawStack(root, t);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Spawn a fading 'ghost' of a tile as an activator for the cool effect
|
|||
|
public void Ghost(TileInfo tile, (int x, int y) ghostPos) {
|
|||
|
//var tileGo = Instantiate<GameObject>(tilePrefab,corner);
|
|||
|
var tileGo = Instantiate(tilePrefab, corner);
|
|||
|
var tr = tileGo.GetComponent<TileRender>();
|
|||
|
tr.renderer.sortingOrder = 3; // Draw infront of the others!
|
|||
|
tileGo.transform.localPosition = new Vector3(ghostPos.x * width, ghostPos.y * height);
|
|||
|
//Debug.Log("Ghosting", tr.gameObject);
|
|||
|
//Debug.Break();
|
|||
|
StartCoroutine(HandleGhost(tr,tile.color));
|
|||
|
}
|
|||
|
|
|||
|
public void Crumble(TileInfo tile, (int x, int y) crumblePos) {
|
|||
|
// Copypastecopypastecopypast - Texel
|
|||
|
var tileGo = Instantiate(tilePrefab, corner);
|
|||
|
var tr = tileGo.GetComponent<TileRender>();
|
|||
|
tr.renderer.sortingOrder = 3; // Draw infront of the others!
|
|||
|
tileGo.transform.localPosition = new Vector3(crumblePos.x * width, crumblePos.y * height);
|
|||
|
|
|||
|
StartCoroutine(HandleCrumble(tr, tile.color, tile.kind));
|
|||
|
}
|
|||
|
|
|||
|
// Float up and fade out
|
|||
|
IEnumerator HandleGhost(TileRender tr, TileColor color) {
|
|||
|
float opacity = 1f;
|
|||
|
while (opacity > 0f) {
|
|||
|
opacity -= Time.deltaTime;
|
|||
|
// Move up about one unit over a second?
|
|||
|
tr.transform.localPosition += new Vector3(0, Time.deltaTime, 0);
|
|||
|
|
|||
|
tr.SetDisplay(color, TileKind.Activator);
|
|||
|
tr.renderer.color = new Color(1, 1, 1, opacity);
|
|||
|
yield return null;
|
|||
|
}
|
|||
|
Destroy(tr.gameObject);
|
|||
|
}
|
|||
|
|
|||
|
// Fall down and fade out
|
|||
|
IEnumerator HandleCrumble(TileRender tr, TileColor color, TileKind kind) {
|
|||
|
float opacity = 2f;
|
|||
|
float sideVel = Random.value - 0.5f;
|
|||
|
float fallSpeed = 0.9f + (Random.value * 0.3f);
|
|||
|
|
|||
|
while (opacity > 0f) {
|
|||
|
opacity -= Time.deltaTime;
|
|||
|
tr.transform.localPosition += new Vector3(sideVel * Time.deltaTime, fallSpeed * -Time.deltaTime, 0);
|
|||
|
|
|||
|
tr.SetDisplay(color, kind);
|
|||
|
tr.renderer.color = new Color(1, 1, 1, opacity);
|
|||
|
yield return null;
|
|||
|
}
|
|||
|
Destroy(tr.gameObject);
|
|||
|
}
|
|||
|
|
|||
|
public void RenderPlacement(TileInfo left, TileInfo right, (int x, int y) leftPosition, (int x, int y) rightPosition){
|
|||
|
place1.transform.localPosition = new Vector3(leftPosition.x * width, leftPosition.y * height);
|
|||
|
place2.transform.localPosition = new Vector3(rightPosition.x * width, rightPosition.y * height);
|
|||
|
|
|||
|
place3.transform.localPosition = new Vector3(board.nextRootX * width, board.nextRootY * height);
|
|||
|
place4.transform.localPosition = new Vector3(board.nextRootX * width, (board.nextRootY - 1f) * height);
|
|||
|
|
|||
|
var np = board.nextPair;
|
|||
|
place3.SetDisplay(np.left.color, np.left.kind);
|
|||
|
place4.SetDisplay(np.right.color, np.right.kind);
|
|||
|
|
|||
|
place1.SetDisplay(left, left.color, left.kind);
|
|||
|
place2.SetDisplay(right, right.color, right.kind);
|
|||
|
}
|
|||
|
|
|||
|
void RebuildStack(Transform root, TileList tiles){
|
|||
|
var spawnOffset = 0f;
|
|||
|
var maxHeight = height * (GameBoard.ROW + 1);
|
|||
|
|
|||
|
for(var i = 0; i < tiles.Count; ++i){
|
|||
|
var tile = tiles[i];
|
|||
|
var tilestate = tile.kind;
|
|||
|
var tileinstance = 0;
|
|||
|
|
|||
|
var ttransform = i < root.childCount ? root.GetChild(i) : null;
|
|||
|
var trender = ttransform != null ? ttransform.GetComponent<TileRender>() : null;
|
|||
|
|
|||
|
// new tiles, place them at the top
|
|||
|
if (ttransform == null){
|
|||
|
var t = Instantiate(tilePrefab, root).transform;
|
|||
|
t.localPosition = new Vector3(0f, Mathf.Max(maxHeight, spawnOffset));
|
|||
|
t.localRotation = Quaternion.identity;
|
|||
|
t.localScale = Vector3.one;
|
|||
|
|
|||
|
t.GetComponent<TileRender>().id = tileinstance;
|
|||
|
|
|||
|
spawnOffset = t.localPosition.y + height;
|
|||
|
}
|
|||
|
// not in sync, stop destroying
|
|||
|
else if (tileinstance != trender.id){
|
|||
|
ttransform.parent = null;
|
|||
|
Destroy(ttransform.gameObject);
|
|||
|
i--;
|
|||
|
}
|
|||
|
// in sync, continue
|
|||
|
else {
|
|||
|
spawnOffset = ttransform.localPosition.y + height;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// any excess tiles are removed
|
|||
|
while(tiles.Count < root.childCount){
|
|||
|
var child = root.GetChild(root.childCount - 1);
|
|||
|
child.parent = null;
|
|||
|
Destroy(child.gameObject);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
private static Dictionary<TileColor, Color> colorConversion = new Dictionary<TileColor, Color>(){
|
|||
|
{ TileColor.Blue, Color.blue },
|
|||
|
{ TileColor.Green, Color.green },
|
|||
|
{ TileColor.Red, Color.red },
|
|||
|
{ TileColor.Yellow, Color.yellow}
|
|||
|
};
|
|||
|
|
|||
|
void DrawStack(Transform root, TileList tiles){
|
|||
|
var dest = 0f;
|
|||
|
var speed = Time.deltaTime * tileSpeed;
|
|||
|
|
|||
|
for(var i = 0; i < tiles.Count; ++i){
|
|||
|
var tile = tiles[i];
|
|||
|
var tilekind = tile.kind;
|
|||
|
var tilecolor = tile.color;
|
|||
|
var ttransform = root.GetChild(i);
|
|||
|
var trender = ttransform.GetComponent<TileRender>();
|
|||
|
|
|||
|
if (tilekind != TileKind.Air){
|
|||
|
// pos
|
|||
|
var pos = ttransform.localPosition.y;
|
|||
|
ttransform.localPosition = new Vector3(0f, Mathf.MoveTowards(pos, dest, speed));
|
|||
|
dest += height;
|
|||
|
|
|||
|
// color
|
|||
|
ttransform.gameObject.SetActive(true);
|
|||
|
trender.SetDisplay(tile, tilecolor, tilekind);
|
|||
|
|
|||
|
// counter
|
|||
|
trender.SetCounter(tilekind == TileKind.Trash ? tile.counter.ToString() : "");
|
|||
|
} else {
|
|||
|
ttransform.gameObject.SetActive(false);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|