using System.Collections; using System.Collections.Generic; using UnityEngine; //public class MapManager : MonoBehaviour [CreateAssetMenu(menuName = "Major Project/Map Manager")] public class MapManager : ScriptableObject { public GameObject spawn4; //The section to use as a spawn-point for games with 2-5 players public GameObject spawn8; //The section to use a spawn-point for games with 5-8 players //In 5-player games, we choose between them at random public List sections; //The list of sections to choose from after starting public int minConns = 2; //The minimum number of valid connections between two map sections for them to be allowed to link up public float xForward = 28.0f; //How far ahead of the camera's current position do we want to extend the track? public float xBack = -4.0f; //And how far behind the camera's position does a section need to fall before being deleted? public List activeSections; //The list of sections that have been placed on the map (and not removed) MapSection lastSection; //Which map-section was most recently added? float startX = -16.0f; //The x-position of the current start of the track float endX = -16.0f; //The x-position of the current end of the track // Start is called before the first frame update void Start() { } public void init(int players) { activeSections = new List(); if (players < 5) { addSection(spawn4.GetComponent()); } else if (players > 5) { addSection(spawn8.GetComponent()); } else { if (Random.Range(0.0f, 1.0f) < 0.5f) { addSection(spawn4.GetComponent()); } else { addSection(spawn8.GetComponent()); } } switch (players) { case 2: foreach (GameObject spawnBlock in lastSection.spawns2) { spawnBlock.GetComponent().isSpawnable = true; } break; case 3: foreach (GameObject spawnBlock in lastSection.spawns3) { spawnBlock.GetComponent().isSpawnable = true; } break; case 4: foreach (GameObject spawnBlock in lastSection.spawns4) { spawnBlock.GetComponent().isSpawnable = true; } break; case 5: foreach (GameObject spawnBlock in lastSection.spawns5) { spawnBlock.GetComponent().isSpawnable = true; } break; case 6: foreach (GameObject spawnBlock in lastSection.spawns6) { spawnBlock.GetComponent().isSpawnable = true; } break; case 7: foreach (GameObject spawnBlock in lastSection.spawns7) { spawnBlock.GetComponent().isSpawnable = true; } break; case 8: foreach (GameObject spawnBlock in lastSection.spawns8) { spawnBlock.GetComponent().isSpawnable = true; } break; default: foreach (GameObject spawnBlock in lastSection.spawns1) { spawnBlock.GetComponent().isSpawnable = true; } break; } checkForward(); } void chooseNextSection() { //First, we determine which sections are valid List validSections = new List(); foreach (MapSection section in sections) { if (checkSegments(section)) { validSections.Add(section); //If a segment is a valid continuation of the current most-recent segment, add it to the list } } //Having generated our list, we choose a random segment from it /*foreach (MapSection section in validSections) { Debug.Log("Valid section: " + section.name); }*/ Debug.Log("Choosing section"); MapSection nextSection = validSections[(int)Random.Range(0.0f, (float)validSections.Count)]; Debug.Log("Chosen section: " + nextSection.name); addSection(nextSection); } void addSection(MapSection section) { //Instantiate new section at x = endX Vector3 pos = new Vector3(endX, 0.0f, 0.0f); GameObject newSection = (GameObject)Instantiate(section.gameObject, pos, Quaternion.identity); //GameObject.Instantiate(section.gameObject, pos, Quaternion.identity); MapSection newSectionScript = newSection.GetComponent(); newSectionScript.InitSection(activeSections.Count); newSection.name = newSectionScript.name; activeSections.Add(newSectionScript); lastSection = newSectionScript; endX += newSectionScript.length; } bool checkSegments(MapSection second) { return checkSegments(this.lastSection, second); } bool checkSegments(MapSection first, MapSection second) { int connections = 0; //Debug.Log("Checking sections: first = " + first.name + ", second = " + second.name); foreach (GameObject exit in first.exits) { foreach (GameObject entry in second.entrances) { /*Debug.Log("Checking connections: exit = " + exit.transform.localPosition.z + ", " + exit.transform.localPosition.x + ", entry = " + entry.transform.localPosition.z + ", " + entry.transform.localPosition.x);*/ if (checkConnection(exit, entry)) { connections++; } } } //Debug.Log("Connections = " + connections); if (connections >= minConns) { //Debug.Log("Valid section!"); } else { //Debug.Log("Invalid section!"); } return (connections >= minConns); } bool checkConnection(GameObject exit, GameObject entry) { /*Debug.Log("Checking connections: exit = " + exit.transform.localPosition.z + ", " + exit.transform.localPosition.x + ", entry = " + entry.transform.localPosition.z + ", " + entry.transform.localPosition.x);*/ //If the squares being checked don't line up, the connection is invalid if (exit.transform.localPosition.z != entry.transform.localPosition.z) { //Debug.Log(exit.transform.localPosition.z + " != " + entry.transform.localPosition.z); return false; } //Debug.Log("Exit.is_Walkable = " + exit.GetComponent().is_Walkable + ", Entry.is_Walkable = " + entry.GetComponent().is_Walkable); //Since we currently don't let people jump over walls, if either block is a wall, the connection is invalid if (!(exit.GetComponent().is_Walkable) || !(entry.GetComponent().is_Walkable)) { //Debug.Log("Invalid connection - not walkable"); return false; } //Debug.Log("Exit.isWater = " + exit.GetComponent().isWater + ", Entry.isWater = " + entry.GetComponent().isWater); //If both components are water, moving through this connection is technically possible, but we don't count it as valid if ((exit.GetComponent().isWater) && (entry.GetComponent().isWater)) { //Debug.Log("Invalid connection - both water"); return false; } //Debug.Log("Valid connection!"); //If we've passed all these tests, the connection is valid! return true; } //Check whether it's time to extend the track forward void checkForward() { //We check if the end of the last section of track is in sight Vector3 trackEnd = new Vector3(endX, 0.0f); //Get the middle of the end of the last track section //If it is, then we add a new section if (checkView(trackEnd)) { chooseNextSection(); checkForward(); } } //Check whether it's time to delete the oldest section of active track void checkBack() { //We check if the end of the first section of track is still in sight Vector3 firstSectionEnd = new Vector3(startX + activeSections[0].length, 0.0f); //Get the middle of the end of the first track section //If it's not, then we remove it if (!(checkView(firstSectionEnd))) { startX += activeSections[0].length; activeSections[0].destroySection(); activeSections.RemoveAt(0); } } //Check whether a point is in sight or not bool checkView(Vector3 point) { Vector3 screenPoint = Camera.main.WorldToViewportPoint(point); //Map it into viewport space //The camera's field of view is represented by 0 > (x, y) < 1, with z being the distance from the camera return (screenPoint.z > 0 && screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1); } //Checks in both directions for sections needing to be added or removed public void checkTrack() { checkForward(); checkBack(); } // Update is called once per frame void Update() { //checkTrack(); } }