You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

375 lines
13 KiB

using Networking.Client;
using Networking.Server;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//public class MapManager : MonoBehaviour
[CreateAssetMenu(menuName = "Major Project/Map Manager")]
public class MapManager : ScriptableObject
{
public ClientList clients;
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<MapSection> 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 List<MapSection> 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
int totalSections = 0; //How many sections have been added? Including ones that have been deleted
int initialPlayerCount;
int diffMin; //Minimum difficulty for a map section to be selected
int diffMax; //Maximum difficulty for a map section to be selected
int diffMinStart = 0; //Initial minimum difficulty for a map section to be selected
int diffMaxStart = 1; //Initial maximum difficulty for a map section to be selected
int diffMinMax = 4; //The highest diffMin can go - ensure that it doesn't go too high to have legal map sections
int widthMin; //The minimum widthIn that we want for a new map section
int widthMax; //The maximum widthIn that we want for a new map section
int minPossibleWidth = 3; //The minimum to which widthMin and widthMax can be reduced
public void init()
{
initialPlayerCount = clients.ConnectedClients.Count;
activeSections = new List<MapSection>();
if (initialPlayerCount < 5)
{
addSection(spawn4.GetComponent<MapSection>());
}
else if (initialPlayerCount > 5)
{
addSection(spawn8.GetComponent<MapSection>());
}
else
{
if (Random.Range(0.0f, 1.0f) < 0.5f)
{
addSection(spawn4.GetComponent<MapSection>());
}
else
{
addSection(spawn8.GetComponent<MapSection>());
}
}
widthMin = activeSections[0].widthOut - 2;
widthMax = activeSections[0].widthOut + 2;
//Set the maximum possible diffMin value to 1 less than the highest difficulty on the section list
diffMinMax = 0;
foreach (MapSection section in sections)
{
if (section.difficulty > diffMinMax)
{
diffMinMax = section.difficulty;
}
}
diffMinMax--;
switch (initialPlayerCount)
{
case 2:
foreach (GameObject spawnBlock in lastSection.spawns2)
{
spawnBlock.GetComponent<Block>().isSpawnable = true;
}
break;
case 3:
foreach (GameObject spawnBlock in lastSection.spawns3)
{
spawnBlock.GetComponent<Block>().isSpawnable = true;
}
break;
case 4:
foreach (GameObject spawnBlock in lastSection.spawns4)
{
spawnBlock.GetComponent<Block>().isSpawnable = true;
}
break;
case 5:
foreach (GameObject spawnBlock in lastSection.spawns5)
{
spawnBlock.GetComponent<Block>().isSpawnable = true;
}
break;
case 6:
foreach (GameObject spawnBlock in lastSection.spawns6)
{
spawnBlock.GetComponent<Block>().isSpawnable = true;
}
break;
case 7:
foreach (GameObject spawnBlock in lastSection.spawns7)
{
spawnBlock.GetComponent<Block>().isSpawnable = true;
}
break;
case 8:
foreach (GameObject spawnBlock in lastSection.spawns8)
{
spawnBlock.GetComponent<Block>().isSpawnable = true;
}
break;
default:
foreach (GameObject spawnBlock in lastSection.spawns1)
{
spawnBlock.GetComponent<Block>().isSpawnable = true;
}
break;
}
checkForward();
}
void chooseNextSection()
{
//First, we determine which sections are valid
List<MapSection> validSections = new List<MapSection>();
updateCriteria(); //We update the section selection criteria for the current gamestate
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<MapSection>();
newSectionScript.InitSection(activeSections.Count);
newSection.name = newSectionScript.name;
activeSections.Add(newSectionScript);
lastSection = newSectionScript;
endX += newSectionScript.length;
totalSections++;
}
bool checkSegments(MapSection second)
{
return checkSegments(this.lastSection, second);
}
bool checkSegments(MapSection first, MapSection second)
{
int connections = 0;
if (second.difficulty < diffMin || second.difficulty > diffMax)
{
return false;
}
if (second.widthIn < widthMin || second.widthIn > widthMax)
{
return false;
}
//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<Block>().is_Walkable + ", Entry.is_Walkable = " + entry.GetComponent<Block>().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<Block>().is_Walkable) || !(entry.GetComponent<Block>().is_Walkable))
{
//Debug.Log("Invalid connection - not walkable");
return false;
}
//Debug.Log("Exit.isWater = " + exit.GetComponent<Block>().isWater + ", Entry.isWater = " + entry.GetComponent<Block>().isWater);
//If both components are water, moving through this connection is technically possible, but we don't count it as valid
if ((exit.GetComponent<Block>().isWater) && (entry.GetComponent<Block>().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();
}
//Updates minimum and maximum difficulty, width, etc, based on current gamestate
public void updateCriteria()
{
//By default, we can add a section 1 tile wider or narrower on either side than the last section
widthMin = lastSection.widthOut - 2;
widthMax = lastSection.widthOut + 2;
/* Calculate min & max difficulties & width modifications
* We recalculate from scratch each time (that is,
* each time a section is added) so as to avoid having
* to track which one-off increase has been applied
* and which hasn't
*/
//Start with base values
diffMin = diffMinStart;
diffMax = diffMaxStart;
//As the number of players shrinks, we ramp up the difficulty and contract the track
if (clients.ConnectedClients.Count <= (float)(0.5f * initialPlayerCount))
{
diffMin++;
diffMax++;
widthMin -= 2;
widthMax -= 2;
}
if (clients.ConnectedClients.Count <= (float)(0.25f * initialPlayerCount))
{
diffMin++;
diffMax += 2;
widthMin -= 2;
widthMax -= 2;
}
//Ramp up the difficulty as the game goes on
diffMin += (totalSections - 2) / 2;
diffMax += totalSections / 2;
//Once the difficulty has ramped up, we cause the track to steadily narrow
//It can no longer widen, only remain constant or shrink
if (diffMin > 2)
{
widthMax--;
}
//Apply caps
if (diffMin > diffMinMax)
{
diffMin = diffMinMax;
}
if (widthMin < minPossibleWidth)
{
widthMin = minPossibleWidth;
}
}
// Update is called once per frame
void Update()
{
//checkTrack();
}
}