Created
July 24, 2016 22:22
-
-
Save cucumbur/5db80e61f84225c99b38cd06355d149b to your computer and use it in GitHub Desktop.
Turn Management code from WIP game
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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