TouhouLS/Assets/RealCode/GameBoardRender.cs

364 lines
11 KiB
C#
Raw Permalink Normal View History

2020-08-22 05:29:00 +00:00
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;
2020-08-22 05:41:26 +00:00
public TextMeshPro NickNameText;
2020-08-22 05:29:00 +00:00
[Header("Positioning")]
public Transform basePoint;
public float width, height;
[Header("Extra")]
public TileRender place1;
public TileRender place2;
public TileRender place1a, place2a; // Ghost tile display
2020-08-22 05:29:00 +00:00
public TileRender place3, place4; // Next tile display
public SimpleAnimationLoop[] characterAnimations;
2020-08-22 10:15:14 +00:00
private float soonestChangeTime = 0f;
public void SetAnimation() {
var index = 0;
if (GameTransition.Instance.state == GameState.InGame){
// default idle
if (GameBoardInstance.instance.readyActive){
index = 0;
}
// regular Texel way
else if (GameBoardInstance.instance.gameActive){
if (Time.time < soonestChangeTime) return;
switch(board.desiredAnimation) {
case GameBoard.AnimationName.Happy:
case GameBoard.AnimationName.Sad:
soonestChangeTime = Time.time + 5f;
break;
}
index = (int)board.desiredAnimation;
}
// win or loss
else if (GameBoardInstance.instance.gameSetActive){
index = board.delayState == GameBoard.DelayState.Loss ? 2 : 1;
}
}
2020-08-23 00:31:57 +00:00
// lobby edge case
else if (GameTransition.Instance.state == GameState.Lobby){
index = 0;
}
// lol no nothing
else return;
// can't disable it?
var selected = characterAnimations[index];
foreach(var a in characterAnimations){
if (a != selected)
a.gameObject.SetActive(false);
}
selected.gameObject.SetActive(true);
selected.Update();
2020-08-22 10:15:14 +00:00
}
2020-08-22 05:29:00 +00:00
// 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>();
place1a = Instantiate(GameBoardInstance.instance.tilePrefab, corner).GetComponent<TileRender>();
place2a = Instantiate(GameBoardInstance.instance.tilePrefab, corner).GetComponent<TileRender>();
2020-08-22 05:29:00 +00:00
place3 = Instantiate(GameBoardInstance.instance.tilePrefab, corner).GetComponent<TileRender>();
place4 = Instantiate(GameBoardInstance.instance.tilePrefab, corner).GetComponent<TileRender>();
place1a.transform.localPosition = Vector3.zero;
place2a.transform.localPosition = Vector3.zero;
2020-08-22 05:29:00 +00:00
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];
DrawStack(root, t);
}
}
public void RebuildStack(BoardState state){
for (var i = 0; i < state.Count; ++i) {
var root = basePoint.GetChild(i);
var t = state[i];
RebuildStack(root, t);
}
}
2020-08-22 05:41:26 +00:00
public void RenderName(){
if (NetworkManager.inRoom && board.authorityID != -1){
var player = NetworkManager.net.CurrentRoom.GetPlayer(board.authorityID);
NickNameText.text = player.NickName;
} else {
NickNameText.text = string.Empty;
2020-08-22 05:41:26 +00:00
}
}
2020-08-22 05:29:00 +00:00
// 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 ClearPlacement(){
place1.ClearDisplay();
place2.ClearDisplay();
place1a.ClearDisplay();
place2a.ClearDisplay();
place3.ClearDisplay();
place4.ClearDisplay();
}
2020-08-22 05:29:00 +00:00
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);
int min = Mathf.Min(leftPosition.x, rightPosition.x), max = Mathf.Max(rightPosition.x, leftPosition.x);
if (min >= 0 && max < GameBoard.COLUMN) {
int leftHeight = board.board[leftPosition.x].Count;
int rightHeight = board.board[rightPosition.x].Count;
switch(board.playerRotation) {
case 3:
leftHeight += 1;
break;
case 1:
rightHeight += 1;
break;
}
place1a.transform.localPosition = new Vector3(leftPosition.x * width, leftHeight * height);
place2a.transform.localPosition = new Vector3(rightPosition.x * width, rightHeight * height);
place1a.SetDisplay(left.color, left.kind);
place2a.SetDisplay(right.color, right.kind);
var fade = new Color(1, 1, 1, board.delayState.Equals(GameBoard.DelayState.None) ? 0.5f : 0.0f);
place1a.renderer.color = fade;
place2a.renderer.color = fade;
} else {
place1a.ClearDisplay();
place2a.ClearDisplay();
}
2020-08-22 05:29:00 +00:00
}
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);
}
}
}
}