Decent first prototype
This commit is contained in:
267
Assets/JustSign/Scripts/JustSignController.cs
Normal file
267
Assets/JustSign/Scripts/JustSignController.cs
Normal file
@@ -0,0 +1,267 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Contains all game logic for the JustSign game
|
||||
/// </summary>
|
||||
public class JustSignController : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// All of the words that can be used in this session
|
||||
/// </summary>
|
||||
private List<Learnable> words = new List<Learnable>();
|
||||
|
||||
/// <summary>
|
||||
/// The canvas containing all components
|
||||
/// </summary>
|
||||
public Canvas canvas;
|
||||
|
||||
/// <summary>
|
||||
/// The input field where the user can type his or her answer
|
||||
/// </summary>
|
||||
public TMP_InputField answerField;
|
||||
|
||||
/// <summary>
|
||||
/// The feedback on the timing
|
||||
/// </summary>
|
||||
public TMP_Text feedBack;
|
||||
|
||||
/// <summary>
|
||||
/// The current score
|
||||
/// </summary>
|
||||
public TMP_Text scoreDisplay;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the minigame ScriptableObject
|
||||
/// </summary>
|
||||
public Minigame minigame;
|
||||
|
||||
/// <summary>
|
||||
/// The zone that the player should be hitting with his or her inputs
|
||||
/// </summary>
|
||||
public GameObject hitZone;
|
||||
|
||||
/// <summary>
|
||||
/// Symbol prefab
|
||||
/// </summary>
|
||||
public GameObject symbolPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to symbol prefab
|
||||
/// </summary>
|
||||
public Transform symbolContainer;
|
||||
|
||||
/// <summary>
|
||||
/// All of the available themes
|
||||
/// </summary>
|
||||
private ThemeList themeList;
|
||||
|
||||
/// <summary>
|
||||
/// The theme we are currently using
|
||||
/// </summary>
|
||||
private Theme currentTheme;
|
||||
|
||||
/// <summary>
|
||||
/// List of strings representing all words on the track
|
||||
/// </summary>
|
||||
private List<string> activeWords = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// List of objects representing all symbols on the track
|
||||
/// </summary>
|
||||
private List<GameObject> activeSymbols = new List<GameObject>();
|
||||
|
||||
/// <summary>
|
||||
/// The current score
|
||||
/// </summary>
|
||||
private int score;
|
||||
|
||||
/// <summary>
|
||||
/// Width and height of the symbols
|
||||
/// </summary>
|
||||
private int symbolSize = 280;
|
||||
|
||||
/// <summary>
|
||||
/// Controls movement speed of symbols (higher -> faster)
|
||||
/// </summary>
|
||||
private int moveSpeed = 200;
|
||||
|
||||
/// <summary>
|
||||
/// Starting X-coordinate of a symbol = (-1920 - symbolsize) / 2
|
||||
/// </summary>
|
||||
private int trackX = -1100;
|
||||
|
||||
/// <summary>
|
||||
/// Starting Y-coordinate of a symbol
|
||||
/// </summary>
|
||||
private int trackY = -200;
|
||||
|
||||
/// <summary>
|
||||
/// Max distance from hit zone to get perfect score
|
||||
/// </summary>
|
||||
private int perfectBoundary = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Score obtained when getting a perfect hit
|
||||
/// </summary>
|
||||
private int perfectScore = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Max distance from hit zone to get good score
|
||||
/// </summary>
|
||||
private int goodBoundary = 120;
|
||||
|
||||
/// <summary>
|
||||
/// Score obtained when getting a good hit
|
||||
/// </summary>
|
||||
private int goodScore = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Max distance from hit zone to get meh score
|
||||
/// </summary>
|
||||
private int mehBoundary = 200;
|
||||
|
||||
/// <summary>
|
||||
/// Score obtained when getting a meh hit
|
||||
/// </summary>
|
||||
private int mehScore = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Score obtained when getting a terrible hit
|
||||
/// </summary>
|
||||
private int terribleScore = -3;
|
||||
|
||||
/// <summary>
|
||||
/// Score obtained when symbol goes offscreen
|
||||
/// </summary>
|
||||
private int offscreenScore = -5;
|
||||
|
||||
/// <summary>
|
||||
/// Time at which the last symbol was spawned
|
||||
/// </summary>
|
||||
private float lastSpawn;
|
||||
|
||||
/// <summary>
|
||||
/// Determines every how many seconds a symbol should spawn (will become music-dependent later on)
|
||||
/// </summary>
|
||||
private float spawnPeriod = 3.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Start is called before the first frame update
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
scoreDisplay.text = "Score: " + score.ToString();
|
||||
currentTheme = minigame.themeList.themes[minigame.themeList.currentThemeIndex];
|
||||
words.AddRange(currentTheme.learnables);
|
||||
//currentTheme = FindThemeByName(PlayerPrefs.GetString("themeName"));
|
||||
//words = currentTheme.words;
|
||||
lastSpawn = Time.time;
|
||||
SpawnNewSymbol();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update is called once per frame
|
||||
/// </summary>
|
||||
void Update()
|
||||
{
|
||||
int matchedSymbolIndex = -1;
|
||||
for (int i = 0; i < activeWords.Count; i++) {
|
||||
if (activeWords[i].ToLower() == answerField.text.ToLower()) {
|
||||
matchedSymbolIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy the oldest symbol if the current input matches it
|
||||
if (matchedSymbolIndex >= 0) {
|
||||
int difference = Math.Abs((int) (activeSymbols[matchedSymbolIndex].transform.position.x - hitZone.transform.position.x));
|
||||
if (difference < perfectBoundary) {
|
||||
feedBack.text = "Perfect!";
|
||||
score += perfectScore;
|
||||
} else if (difference < goodBoundary) {
|
||||
feedBack.text = "Good!";
|
||||
score += goodScore;
|
||||
} else if (difference < mehBoundary) {
|
||||
feedBack.text = "Meh...";
|
||||
score += mehScore;
|
||||
} else {
|
||||
feedBack.text = "Terrible!";
|
||||
score += terribleScore;
|
||||
}
|
||||
|
||||
DestroySymbolAt(matchedSymbolIndex);
|
||||
answerField.text = "";
|
||||
}
|
||||
|
||||
// Destroy the oldest symbol if it leaves the screen
|
||||
if (activeSymbols.Count > 0) {
|
||||
if (activeSymbols[0].GetComponent<RectTransform>().localPosition.x > -trackX) {
|
||||
DestroySymbolAt(0);
|
||||
score += offscreenScore;
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn new symbol every spawn period
|
||||
float currentTime = Time.time;
|
||||
if (currentTime - lastSpawn > spawnPeriod) {
|
||||
lastSpawn = currentTime;
|
||||
SpawnNewSymbol();
|
||||
}
|
||||
|
||||
// Move all active symbols to the right
|
||||
foreach (GameObject symbol in activeSymbols) {
|
||||
RectTransform rectTransform = symbol.GetComponent<RectTransform>();
|
||||
rectTransform.localPosition = new Vector3(rectTransform.localPosition.x + Time.deltaTime * moveSpeed, trackY, 0);
|
||||
}
|
||||
|
||||
scoreDisplay.text = "Score: " + score.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroy the symbol at the given index
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the symbol to destroy</param>
|
||||
void DestroySymbolAt(int index) {
|
||||
activeWords.RemoveAt(index);
|
||||
GameObject symbol = activeSymbols[index];
|
||||
activeSymbols.RemoveAt(index);
|
||||
Destroy(symbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new symbol at the start of the track
|
||||
/// </summary>
|
||||
void SpawnNewSymbol() {
|
||||
// Pick a word that isn't in use yet
|
||||
List<int> unusedWordIndices = new List<int>();
|
||||
|
||||
for (int i = 0; i < words.Count; i++) {
|
||||
if (!activeWords.Contains(words[i].name)) {
|
||||
unusedWordIndices.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
Learnable newLearnable = words[unusedWordIndices[UnityEngine.Random.Range(0, unusedWordIndices.Count)]];
|
||||
string nextSymbol = newLearnable.name;
|
||||
|
||||
GameObject newSymbolObject = GameObject.Instantiate(symbolPrefab, symbolContainer);
|
||||
|
||||
// Dynamically load appearance
|
||||
Image image = newSymbolObject.GetComponent<Image>();
|
||||
image.sprite = newLearnable.image;
|
||||
image.rectTransform.sizeDelta = new Vector2(symbolSize, symbolSize);
|
||||
|
||||
// Place the word that the symbol represents under the image
|
||||
TMP_Text text = newSymbolObject.GetComponentInChildren<TMP_Text>();
|
||||
text.text = nextSymbol;
|
||||
text.color = Color.black;
|
||||
text.rectTransform.localPosition = new Vector3(0, -160, 0);
|
||||
|
||||
activeWords.Add(nextSymbol);
|
||||
activeSymbols.Add(newSymbolObject);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user