Skip to content

Instantly share code, notes, and snippets.

@cucumbur
Created July 24, 2016 22:22
Show Gist options
  • Save cucumbur/5db80e61f84225c99b38cd06355d149b to your computer and use it in GitHub Desktop.
Save cucumbur/5db80e61f84225c99b38cd06355d149b to your computer and use it in GitHub Desktop.
Turn Management code from WIP game
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityStandardAssets.Utility;
public class TurnManager : Singleton<TurnManager> {
// Singleton enforcer
protected TurnManager() {}
// Inspector-assigned components
[SerializeField]
private GameObject turnMenu;
[SerializeField]
private GameObject base_spinner;
// State
public enum StateTurn {None, ChooseAction, Spinning, ChooseMovement, Moving, ChooseItem};
public StateTurn state;
// Turn information
private GameObject _player;
private enum ActionChoice {None, Move, Inventory, Map, Info};
private ActionChoice _actionChoice;
// For Move turn action
private int moveNumber;
private int hasSpun;
private GameObject moveTarget;
void Awake() {
state = StateTurn.None;
moveTarget = null;
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public IEnumerator NewTurn(GameObject currentPlayer) {
_player = currentPlayer;
yield return StartCoroutine(Turn());
}
IEnumerator Turn() {
// Make sure data from previous turns is reset
_player.GetComponent<Player>().usedItem = false;
hasSpun = 0;
moveNumber = 0;
moveTarget = null;
_actionChoice = ActionChoice.None;
// Turn Phases
// 1. Set currentplayer, center camera on player, fade in turn menu and wait for choice (Move, Items, Map, Info)
// 2. Fade out turn menu
// a. Move
// i. Activate spinner. wait for click
// ii. On click, spin spinner. The spinner spins and the movement number is displayed
// iii. Player movement is enabled. The spaces they can move to are highlighted. Wait for a click on one of them
// iv. Player movement disabled. Show confirmation box. Wait for player to confirm or reject. If reject, go back to 3.
// v. Player is moved to the spot they chose. The movenumber updates as their spaces count down. Movenumber is then disabled. Procede to phase 3
//
// Phase 1
state = StateTurn.ChooseAction;
GameObject.Find("PlayerNameGUI").GetComponent<Text>().text = _player.GetComponent<Player>().playerName;
GameObject.Find("UISound").GetComponents<AudioSource>()[0].Play();
// Turn on player-selection particle effect
_player.GetComponentInChildren<ParticleSystem>().Play();
// Center camera on player and zoom in
GameObject cameraObj = GameObject.Find("Main Camera");
cameraObj.GetComponent<SmoothFollow>().target = _player.transform;
cameraObj.GetComponent<SmoothFollow>().distance *= .5f;
cameraObj.GetComponent<SmoothFollow>().height *= .5f;
// Activate and fade in menu
turnMenu.SetActive(true);
/*
* This used to be a an individual button with an Image component, now it is a canvas group. CrossFade alpha does not work
* on canvas groups, so I need to either extend it or refactor my fadeoutanddisable function
*/
//turnMenu.GetComponent<CanvasGroup>().alpha = 0f;
//moveButton.GetComponent<Graphic>().CrossFadeAlpha(1f, .5f, true);
// Wait for a button to be clicked
// Handle whichever action was chosen
while (state != StateTurn.Moving) {
if (_actionChoice == ActionChoice.None)
yield return null;
else {
state = StateTurn.ChooseAction;
switch (_actionChoice) {
case ActionChoice.Move:
state = StateTurn.Spinning;
yield return StartCoroutine(ActionMove());
break;
case ActionChoice.Inventory:
state = StateTurn.ChooseItem;
yield return StartCoroutine(ActionItem());
_actionChoice = ActionChoice.None;
turnMenu.SetActive(true);
state = StateTurn.ChooseAction;
break;
default:
yield return null;
break;
}
}
}
// Subtract 1 from the turn length of all qualities and remove any that are 0
foreach (Quality quality in _player.GetComponent<Player>().qualities) {
if (quality.EndTurn())
_player.GetComponent<Player>().qualities.Remove(quality);
}
// Reset choice and turn state
_actionChoice = ActionChoice.None;
state = StateTurn.None;
}
private IEnumerator FadeOutAndDisable(float seconds, GameObject obj, bool isChild = false){
// Fade out any children as well
foreach (Transform child in obj.transform){
StartCoroutine(FadeOutAndDisable(seconds, child.gameObject, true));
}
Graphic g = obj.GetComponent<Graphic>();
if (g != null) {
g.CrossFadeAlpha(0, seconds, false);
}
// Don't deactivate if this is a child of the object from the original call
if (isChild) {
yield return null;
} else {
yield return new WaitForSeconds(seconds);
//moveButton.GetComponent<Button>().interactable = false;
obj.SetActive(false);
}
}
// Called by the player turn menu buttons
public void ChooseAction(string choice) {
switch (choice) {
case "Move":
_actionChoice = ActionChoice.Move;
break;
case "Inventory":
_actionChoice = ActionChoice.Inventory;
break;
case "Map":
_actionChoice = ActionChoice.Map;
break;
case "Info":
_actionChoice = ActionChoice.Info;
break;
default:
break;
}
}
private IEnumerator ActionMove() {
StartCoroutine(FadeOutAndDisable(.5f, turnMenu));
// Check to see if the player has a multispinner quality
Player player = _player.GetComponent<Player>();
int numSpinners = 1;
foreach (Quality q in player.qualities) {
if (q.Equals(Quality.QualityType.ExtraSpinners))
numSpinners = q.Magnitude;
}
moveNumber = 0;
GameObject[] spinners = UIManager.Instance.ShowSpinners(player, numSpinners, base_spinner);
// Wait for the user to spin then deactivate the spinner
while (hasSpun != numSpinners) {
yield return null;
}
Debug.Log("hasSpun is true and now continuing");
foreach (GameObject spObj in spinners) {
spObj.SetActive(false);
}
//StartCoroutine(FadeOutAndDisable(.8f, base_spinner));
UIManager.Instance.ToggleBackground();
// Zoom out the camera so the player can see the map better
GameObject cameraObj = GameObject.Find("Main Camera");
cameraObj.GetComponent<SmoothFollow>().distance *= 2f;
cameraObj.GetComponent<SmoothFollow>().height *= 2f;
// Update state to activate movement and highlight moveable spots
HashSet<GameObject> reachableSpots = FindReachableSpots(_player.GetComponent<Player>().currentSpot);
List<List<GameObject>> paths = FindAvailablePaths(_player.GetComponent<Player>().currentSpot);
state = StateTurn.ChooseMovement;
foreach (GameObject spot in reachableSpots) {
spot.GetComponent<Light>().enabled = true;
}
// Wait for the player to select a reachable spot and find a path to move towards it
while (state == StateTurn.ChooseMovement) {
if (moveTarget == null){
yield return null;
}
bool reachable = false;
// Check if the spot player clicked on is reachable
foreach (GameObject spotObj in reachableSpots){
if (Object.ReferenceEquals(spotObj, moveTarget)){
reachable = true;
}
}
if (!reachable) {
moveTarget = null;
}
else {
GameObject.Find("UISound").GetComponents<AudioSource>()[1].Play();
// Find a path that connects the spots
List<GameObject> movePath = null;
foreach (List<GameObject> p in paths) {
if (Object.ReferenceEquals(p[p.Count - 1], moveTarget)) {
movePath = p;
}
}
// Disable the spot highlights beside the target
foreach (GameObject spot in reachableSpots) {
spot.GetComponent<Light>().enabled = false;
}
moveTarget.GetComponent<Light>().enabled = true;
// Turn off the player select particle effect
_player.GetComponentInChildren<ParticleSystem>().Stop();
// Move the player
state = StateTurn.Moving;
yield return StartCoroutine(_player.GetComponent<Player>().Move(movePath));
moveTarget.GetComponent<Light>().enabled = false;
yield return new WaitForSeconds(1.5f);
yield return StartCoroutine(moveTarget.GetComponent<Spot>().Activate(_player.GetComponent<Player>()));
// Reset some variables
hasSpun = 0;
moveTarget = null;
}
}
}
public IEnumerator ActionItem() {
Player currentPlayer = _player.GetComponent<Player>();
if (currentPlayer.usedItem)
yield return null;
else {
StartCoroutine(FadeOutAndDisable(.5f, turnMenu));
yield return StartCoroutine(UIManager.Instance.ShowInventory(currentPlayer));
}
}
public void Spun(int number) {
moveNumber += number;
hasSpun += 1;
}
private struct SpotPair
{
public Spot previous, current;
public SpotPair(Spot prev, Spot curr)
{
previous = prev;
current = curr;
}
}
private HashSet<GameObject> FindReachableSpots(GameObject startSpotObj){
int movesLeft = moveNumber;
// Spots can be retread, but you can not double back to the spot you just came from
Spot startSpot = startSpotObj.GetComponent<Spot>();
GameObject[] startAdjacentSpotObjs = startSpot.adjacentSpots;
List<SpotPair> currentSpots = new List<SpotPair>();
List<SpotPair> nextSpots = new List<SpotPair>();
foreach (GameObject spotObj in startAdjacentSpotObjs) {
currentSpots.Add(new SpotPair(startSpot, spotObj.GetComponent<Spot>()));
}
movesLeft--;
while (movesLeft > 0) {
foreach (SpotPair sp in currentSpots) {
foreach (GameObject spotObj in sp.current.adjacentSpots) {
if (!Object.ReferenceEquals(spotObj.GetComponent<Spot>(), sp.previous)){
nextSpots.Add(new SpotPair(sp.current, spotObj.GetComponent<Spot>()));
}
}
}
currentSpots = nextSpots;
nextSpots = new List<SpotPair>();
movesLeft--;
}
List<GameObject> reachableSpots = new List<GameObject>();
foreach (SpotPair sp in currentSpots) {
reachableSpots.Add(sp.current.gameObject);
}
return new HashSet<GameObject>(reachableSpots);
}
private List<List<GameObject>> FindAvailablePaths(GameObject startSpotObj) {
int movesLeft = moveNumber;
// Spots can be retread, but you can not double back to the spot you just came from
Spot startSpot = startSpotObj.GetComponent<Spot>();
GameObject[] startAdjacentSpotObjs = startSpot.adjacentSpots;
List<List<SpotPair>> currentPaths = new List<List<SpotPair>>();
List<List<SpotPair>> nextPaths = new List<List<SpotPair>>();
foreach (GameObject spotObj in startAdjacentSpotObjs) {
List<SpotPair> path = new List<SpotPair>();
path.Add(new SpotPair(startSpot, spotObj.GetComponent<Spot>()));
currentPaths.Add(path);
}
movesLeft--;
while (movesLeft > 0) {
foreach (List<SpotPair> spPath in currentPaths) {
SpotPair last = spPath[spPath.Count - 1];
foreach (GameObject spotObj in last.current.adjacentSpots) {
if (!Object.ReferenceEquals(spotObj.GetComponent<Spot>(), last.previous)){
List<SpotPair> newPath = spPath.ToList();
newPath.Add(new SpotPair(last.current, spotObj.GetComponent<Spot>()));
nextPaths.Add(newPath);
}
}
}
currentPaths = nextPaths;
nextPaths = new List<List<SpotPair>>();
movesLeft--;
}
List<List<GameObject>> objPaths = new List<List<GameObject>>();
foreach (List<SpotPair> spPath in currentPaths) {
objPaths.Add(new List<GameObject>(spPath.Select(sp => sp.current.gameObject)));
}
return objPaths;
}
public void AttemptMove(GameObject target){
if (state != StateTurn.ChooseMovement) {
return;
}
if (target.GetComponent<Spot>() != null){
moveTarget = target;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment