253 lines
7.5 KiB
C#
253 lines
7.5 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
public class StreamController : MonoBehaviour {
|
|
|
|
// May be a flatUI arrow or pixel art arrow.
|
|
// Pixel art is used in gameplay streams.
|
|
// FlatUI arrows are used in cutaway scene streams.
|
|
[SerializeField] public GameObject arrowPrefab;
|
|
[SerializeField] public AudioClip hitClip;
|
|
[SerializeField] public AudioClip missClip;
|
|
[SerializeField] public AudioClip winClip;
|
|
[SerializeField] public AudioClip loseClip;
|
|
|
|
[SerializeField] public GameObject arrowGroup;
|
|
|
|
[SerializeField] public AudioSource audioSource;
|
|
|
|
[SerializeField] public List<ArrowController> arrows;
|
|
|
|
[SerializeField] public float resetDelay = 0.5f;
|
|
|
|
[SerializeField] public bool debug = false;
|
|
[SerializeField] public int debugLength = 5;
|
|
[SerializeField] public float debugTimeLimit = 30f;
|
|
|
|
[SerializeField] Button continueButton;
|
|
|
|
StreamInfo info;
|
|
|
|
bool isTicking = false;
|
|
bool isOver = false;
|
|
int passed = 0;
|
|
|
|
[SerializeField] TextMeshProUGUI clearCountTMPro;
|
|
[SerializeField] TextMeshProUGUI timeTMPro;
|
|
[SerializeField] TextMeshProUGUI summaryTMPro;
|
|
[SerializeField] public int numWon = 0;
|
|
|
|
float startTimestamp = 0.0f;
|
|
float freezeTimestamp = 0.0f;
|
|
|
|
public class StreamInfo {
|
|
public int numArrows { get; set; }
|
|
public float timeLimit { get; set; }
|
|
public float startDelay { get; set; }
|
|
public float endDelay { get; set; }
|
|
// Whether or not to auto-close the Stream after winning or losing.
|
|
// Infinite scenes are for special enjoyment events.
|
|
public bool infinite { get; set; }
|
|
// In sudden death, missing one arrow fails the event even if
|
|
// the timer is still running.
|
|
public bool suddenDeath { get; set; }
|
|
public Sprite beforeBG { get; set; } = null;
|
|
public Sprite winBG { get; set; } = null;
|
|
public Sprite loseBG { get; set; } = null;
|
|
public AudioClip beforeClip { get; set; } = null;
|
|
public AudioClip winClip { get; set; } = null;
|
|
public AudioClip loseClip { get; set; } = null;
|
|
}
|
|
|
|
public void Init(StreamInfo info, bool wait = true) {
|
|
this.info = info;
|
|
passed = 0;
|
|
// Calculate int[] keys
|
|
for (int i = 0; i < info.numArrows; i++) {
|
|
ArrowController arrow = Instantiate(arrowPrefab).GetComponent<ArrowController>();
|
|
arrow.key = Random.Range(0, 4);
|
|
arrow.Init();
|
|
arrow.transform.position = arrowGroup.transform.position;
|
|
arrow.transform.SetParent(arrowGroup.transform);
|
|
arrow.transform.localScale = new Vector3(1, 1, 1);
|
|
arrows.Add(arrow);
|
|
}
|
|
if (wait) {
|
|
Invoke("StartTimer", info.startDelay);
|
|
}
|
|
}
|
|
|
|
public void Start() {
|
|
if (debug) {
|
|
Init(new StreamInfo {
|
|
numArrows = debugLength,
|
|
timeLimit = debugTimeLimit,
|
|
startDelay = 1.0f,
|
|
endDelay = 1.0f,
|
|
infinite = true,
|
|
suddenDeath = false
|
|
});
|
|
}
|
|
|
|
audioSource = GameObject.FindWithTag("SFX").GetComponent<AudioSource>();
|
|
continueButton.gameObject.SetActive(false);
|
|
}
|
|
|
|
public void MakeGlow(int arrowIndex) {
|
|
// TODO: implement (make the arrow at ArrowIndex glow)
|
|
// use the shader thing
|
|
}
|
|
|
|
void StartTimer() {
|
|
startTimestamp = Time.time;
|
|
isTicking = true;
|
|
MakeGlow(0);
|
|
}
|
|
|
|
void Reset() {
|
|
Debug.Log("Reset");
|
|
if (isOver)
|
|
return;
|
|
foreach (ArrowController arrow in arrows) {
|
|
Destroy(arrow.gameObject);
|
|
}
|
|
arrows.Clear();
|
|
Init(this.info, false);
|
|
isTicking = true;
|
|
MakeGlow(0);
|
|
}
|
|
|
|
char GetRank() {
|
|
float winRate = numWon * info.numArrows * (1 + resetDelay);
|
|
if (winRate > info.timeLimit * 3)
|
|
return 'S';
|
|
if (winRate > info.timeLimit * 2.5)
|
|
return 'A';
|
|
if (winRate > info.timeLimit * 2)
|
|
return 'B';
|
|
if (winRate > info.timeLimit * 1.5)
|
|
return 'C';
|
|
if (winRate > info.timeLimit * 1)
|
|
return 'D';
|
|
return 'F';
|
|
}
|
|
|
|
int GetScore(char rank) {
|
|
return numWon * 30;
|
|
/*
|
|
switch (rank) {
|
|
case 'S':
|
|
return 300;
|
|
case 'A':
|
|
return 250;
|
|
case 'B':
|
|
return 200;
|
|
case 'C':
|
|
return 150;
|
|
case 'D':
|
|
return 100;
|
|
default:
|
|
return 0;
|
|
}
|
|
*/
|
|
}
|
|
|
|
public void GoBack() {
|
|
GameData.GLOBAL.IncrementTime();
|
|
SceneManager.LoadScene("Manager");
|
|
}
|
|
|
|
void AllowContinue() {
|
|
continueButton.gameObject.SetActive(true);
|
|
}
|
|
|
|
void TimesUp() {
|
|
Debug.Log("Time's Up!");
|
|
isOver = true;
|
|
char rank = GetRank();
|
|
int score = GetScore(rank);
|
|
summaryTMPro.SetText("Time's Up!\nRank: " + rank.ToString() + "\nPay: $" + score.ToString());
|
|
GameData.GLOBAL.money += score;
|
|
GameData.GLOBAL.workedToday = true;
|
|
Invoke("AllowContinue", 1.0f);
|
|
}
|
|
|
|
void TryHit(int key) {
|
|
if (isOver)
|
|
return;
|
|
if (passed < info.numArrows) {
|
|
if (arrows[passed].key == key) {
|
|
// You hit the right arrow, move to the next one
|
|
audioSource.PlayOneShot(hitClip);
|
|
arrows[passed].Succeed();
|
|
passed += 1;
|
|
} else {
|
|
arrows[passed].Fail();
|
|
if (!info.suddenDeath) {
|
|
audioSource.PlayOneShot(missClip);
|
|
isTicking = false;
|
|
Invoke("Reset", resetDelay);
|
|
} else {
|
|
// TODO: do a lose thing
|
|
audioSource.PlayOneShot(loseClip);
|
|
}
|
|
}
|
|
if (passed == info.numArrows) {
|
|
// TODO: do a win thing
|
|
audioSource.PlayOneShot(winClip);
|
|
numWon += 1;
|
|
isTicking = false;
|
|
Invoke("Reset", resetDelay);
|
|
} else {
|
|
MakeGlow(passed);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update() {
|
|
if (isOver)
|
|
return;
|
|
// Process key presses if the delay is over
|
|
if (isTicking) {
|
|
if (Input.GetKeyDown(KeyCode.LeftArrow)) {
|
|
Debug.Log("Left");
|
|
TryHit(0);
|
|
}
|
|
if (Input.GetKeyDown(KeyCode.DownArrow)) {
|
|
Debug.Log("Down");
|
|
TryHit(1);
|
|
}
|
|
if (Input.GetKeyDown(KeyCode.UpArrow)) {
|
|
Debug.Log("Up");
|
|
TryHit(2);
|
|
}
|
|
if (Input.GetKeyDown(KeyCode.RightArrow)) {
|
|
Debug.Log("Right");
|
|
TryHit(3);
|
|
}
|
|
}
|
|
clearCountTMPro.SetText(numWon.ToString());
|
|
}
|
|
|
|
void FixedUpdate() {
|
|
float time;
|
|
if (isTicking) {
|
|
time = info.timeLimit - (Time.time - startTimestamp);
|
|
if (time <= 0f) {
|
|
isTicking = false;
|
|
time = 0f;
|
|
TimesUp();
|
|
}
|
|
freezeTimestamp = time;
|
|
} else {
|
|
time = freezeTimestamp;
|
|
}
|
|
timeTMPro.SetText(time.ToString("#0.00"));
|
|
}
|
|
}
|