|
|
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using Networking.Server;
- using TMPro;
- using UnityEngine.UI;
- using System.Linq;
-
- [CreateAssetMenu(menuName = "Major Project/GameModes/Racetrack", order = 201)]
- public class RacetrackGameMode : GameMode
- {
- public MapManager mapManager;
- public blockSpawn spawn;
-
- public int MaxRound = 999;
- public string nextScene = "ServerTestScene";
- List<ClientData> ConnectedClients;
- public Material OverlayMaterial;
- public float scrollSpeed = 1.0f; //The rate at which the level will scroll past
-
-
- public int RoundCount { get; private set; }
- private Dictionary<ClientData, List<Block>> BlocksOwned;
- int currentBoulderCount;
-
- /// <summary>
- /// Called once before any players have spawned
- /// </summary>
- protected override void OnPreGameStart()
- {
- mapManager.init();
- }
-
- /// <summary>
- /// Called once all players have finished their moves but before the Objective is checked
- /// </summary>
- protected override void OnRoundEnd(PlayerData[] allPlayers)
- {
- cameraCheck(allPlayers);
-
- //At the end of each round, any stuck players are freed to resume moving next round
- foreach (PlayerData player in allPlayers)
- {
- player.character.stuck = false;
-
- if (player.character.inPit && player.client.Lives > 0)
- {
- player.character.respawnCharacter();
- }
- }
-
- RoundCount++;
- }
-
- void cameraCheck(PlayerData[] allPlayers)
- {
- //Get the average x-position of all players
- float xAvg = 0.0f;
- int livePlayerCount = 0;
-
- foreach (PlayerData player in allPlayers)
- {
- if (player.client.Lives > 0)
- {
- xAvg += player.character.transform.position.x;
- livePlayerCount++;
- }
- }
-
- xAvg = xAvg / livePlayerCount;
-
- //Turn that position into a vector in viewport space
- Vector3 xAvgPos = new Vector3(xAvg, 0.0f, 0.0f);
- Vector3 xAvgVP = Camera.main.WorldToViewportPoint(xAvgPos);
-
- //Debug.Log("xAvgPos = " + xAvgPos + ", xAvgVP = " + xAvgVP);
-
- //We move the camera forward by at least one increment
- //Keep doing it until the average x-position is roughly centred
- do
- {
- Camera.main.transform.Translate(scrollSpeed, 0, 0, Space.World);
- xAvgVP = Camera.main.WorldToViewportPoint(xAvgPos);
-
- //Debug.Log("Camera = " + Camera.main.transform.position + ", xAvgVP = " + xAvgVP);
- } while (xAvgVP.x > 0.5f || xAvgVP.y > 0.5f);
-
- //If the foremost player is off the screen, scroll forward to catch up with them
-
- //Find who's furthest ahead
- PlayerData playerAhead = allPlayers[0];
- foreach (PlayerData player in allPlayers)
- {
- if (player.client.Lives > 0 && player.character.transform.position.x > playerAhead.character.transform.position.x)
- {
- playerAhead = player;
- }
- }
-
- //Turn their position to a viewport vector
- Vector3 playerVP = Camera.main.WorldToViewportPoint(playerAhead.character.transform.position);
-
- //If that position is not in view, advance until it is
- while (playerVP.x > 1 || playerVP.y > 1)
- {
- Camera.main.transform.Translate(scrollSpeed, 0, 0, Space.World);
- playerVP = Camera.main.WorldToViewportPoint(playerAhead.character.transform.position);
- }/**/
-
-
- //We check for track sections we need to add/remove
- mapManager.checkTrack();
- //spawn.wakeup();
-
- //Move the camera forward at a steady rate each round
- /*if (scrollSpeed > 0.0f)
- {
- Camera.main.transform.Translate(scrollSpeed, 0, 0, Space.World);
- mapManager.checkTrack();
- //Debug.Log("New camera position at x = " + Camera.main.transform.position.x);
-
- //Plan: get average position of surviving players, centre camera view on it
- //Also, will need to check every time someone moves: are they still on camera?
- //If ahead of camera, advance it until they're visible
- //If behind camera, they lose a life & respawn
- }
- else
- {
- //Debug.Log("Not scrolling");
- }*/
-
- }
-
-
- /// <summary>
- /// Checks if the Game is finished
- /// </summary>
- /// <returns>returns if game is finished</returns>
- public override bool isGameOver(PlayerData[] allPlayers)
- {
- return (RoundCount >= MaxRound -1);
- }
-
-
- /// <summary>
- /// Called once per player after they have moved onto a block
- /// </summary>
- /// <param name="character">Character which moved</param>
- /// <param name="client">Client of the character</param>
- /// <param name="currentBlock">Block moved onto</param>
- protected override void OnPlayerMoved(Character character, ClientData client, Block currentBlock)
- {
- handleFalling(character, client, currentBlock, character.justMoved);
-
- /*Debug.Log("Moved to square at " + currentBlock.transform.position.x + ", "
- + currentBlock.transform.position.y + ", "
- + currentBlock.transform.position.z);
-
- //If a character has fallen in the water or into a pit, we mark that fact, and they lose the rest of their turn
- character.inWater = currentBlock.isWater;
- character.inPit = currentBlock.isPit;
-
- if (character.inWater == true || character.inPit == true)
- {
- character.stuck = true;
- }
-
- Debug.Log("inWater = " + character.inWater + ", inPit = " + character.inPit + ", stuck = " + character.stuck);*/
-
- //Commented out because we don't do this in the racetrack mode
-
- /*ClientData OwnedClient;
- Material overlay = null;
- if (isOwned(currentBlock, out OwnedClient))
- {
- if (OwnedClient == client)
- return;
-
- BlocksOwned[OwnedClient].Remove(currentBlock);
-
- foreach (Material mat in currentBlock.GetComponent<Renderer>().materials)
- {
- if (mat.name == OverlayMaterial.name + " (Instance)")
- overlay = mat;
- }
- }
-
- if (overlay == null)
- {
- overlay = new Material(OverlayMaterial);
- List<Material> mats = new List<Material>(currentBlock.GetComponent<Renderer>().materials);
- mats.Add(overlay);
- currentBlock.GetComponent<Renderer>().materials = mats.ToArray();
- }
-
- overlay.SetColor("_NewColor", client.Color);
-
- if (!BlocksOwned.ContainsKey(client))
- BlocksOwned.Add(client, new List<Block>());
-
- BlocksOwned[client].Add(currentBlock);
-
- if (overlay != null)
- currentBlock.StartCoroutine(AnimateBlock(overlay, 0.25f));*/
- }
-
- protected override void OnRoundStart(PlayerData[] allPlayers)
- {
-
- }
-
- protected override void OnAllPlayersMoved(PlayerData[] allPlayers)
- {
- foreach (PlayerData player in allPlayers)
- {
- /* The justMoved variable is used to determine whether a player taking their turn in the water should become stuck
- * (because they moved into/in the water), or not (because they're turning while remaining in the same square)
- * It's not needed from move to move, so we clear it
- */
- player.character.justMoved = false;
-
- /* if (BlocksOwned.ContainsKey(player.client))
- player.client.SceneScore = BlocksOwned[player.client].Count;
- else
- player.client.SceneScore = 0;*/
- }
- }
-
- protected override void OnGameOver(PlayerData[] allPlayers)
- {
- throw new System.NotImplementedException();
- }
-
- private bool isOwned(Block block, out ClientData client)
- {
- client = null;
-
- foreach (KeyValuePair<ClientData, List<Block>> ownedList in BlocksOwned)
- {
- if (ownedList.Value.Contains(block))
- {
- client = ownedList.Key;
- return true;
- }
- }
-
- return false;
- }
-
- private void handleFalling(Character character, ClientData client, Block currentBlock, bool didMove)
- {
- //If a character has fallen in the water or into a pit, we mark that fact, and they lose the rest of their turn
- character.inWater = currentBlock.isWater;
- character.inPit = currentBlock.isPit;
- character.onCrystal = currentBlock.isCrystals;
- character.underRock = currentBlock.isRock;
-
- if (didMove && (character.inWater || character.inPit))
- {
- character.stuck = true;
- }
- //Debug.Log("inWater = " + character.inWater + ", inPit = " + character.inPit + ", stuck = " + character.stuck);
- }
-
- protected override void OnPlayerKilled(Character character, ClientData client)
- {
- if (character.inPit || character.onCrystal)
- {
- character.lives -= 1;
- character.ClientLink.Lives = character.lives;
- }
- if(character.underRock && currentBoulderCount < 1)
- {
- character.lives -= 1;
- character.ClientLink.Lives = character.lives;
- }
- }
-
- private IEnumerator AnimateBlock(Material mat, float time)
- {
- float timeElasped = 0;
-
- while (timeElasped < time)
- {
- mat.SetFloat("_Multiplier", (timeElasped / time));
- yield return new WaitForEndOfFrame();
- timeElasped += Time.deltaTime;
- }
- mat.SetFloat("_Multiplier", 1);
- }
-
- protected override void OnGameStart(PlayerData[] AllPlayers)
- {
- BlocksOwned = new Dictionary<ClientData, List<Block>>();
- RoundCount = 0;
- AllPlayers = getPlayerOrder(AllPlayers);
- for (int i = 0; i < AllPlayers.Length; i++)
- {
- OnPlayerMoved(AllPlayers[i].character, AllPlayers[i].client, AllPlayers[i].character.CurrentBlock);
- }
- }
-
- public override PlayerData[] getPlayerOrder(PlayerData[] AllPlayers)
- {
- AllPlayers = AllPlayers.ToArray().OrderBy(unit => unit.character.CurrentBlock.transform.position.x).ToArray();
- return AllPlayers;
- }
- }
|