TouhouLS/Assets/RealCode/GameBoardRender.cs

263 lines
8.2 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;
public TextMeshPro NickNameText;
[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);
}
}
public void RenderName(){
if (NetworkManager.inRoom && board.authorityID != -1){
var player = NetworkManager.net.CurrentRoom.GetPlayer(board.authorityID);
NickNameText.text = player.NickName;
}
}
// 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);
}
}
}
}