236 lines
8.3 KiB
C#
236 lines
8.3 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using UnityEngine.UI;
|
|
using System;
|
|
using Unity.VisualScripting;
|
|
using System.Numerics;
|
|
using Vector3 = UnityEngine.Vector3;
|
|
using UnityEditor.Rendering;
|
|
|
|
public class City : MonoBehaviour
|
|
{
|
|
public static City Instance { get; private set; }
|
|
void Awake()
|
|
{
|
|
Instance = this;
|
|
}
|
|
private string[] weekDay = new string[]
|
|
{
|
|
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
|
|
};
|
|
public string curDay;
|
|
public float curTime;
|
|
private bool timeSpeedUp = false; // Flag to check if time is sped up
|
|
private float timeMultiplier = 1f; // Multiplier for time speed
|
|
private float sunriseTime = 21600f; // 6:00 AM in seconds (6 * 3600)
|
|
[SerializeField] GameObject sunriseTarget; // Reference to the sunrise target object for rotation
|
|
private float sunsetTime = 72000f; // 8:00 PM in seconds (20 * 3600)
|
|
[SerializeField] GameObject sunsetTarget; // Reference to the sunset target object for rotation
|
|
private float noonTime = 43200f; // 12:00 PM in seconds (12 * 3600)
|
|
[SerializeField] GameObject noonTarget; // Reference to the noon target object for rotation
|
|
private float minIntensity = 0.1f; // Minimum light intensity (night)
|
|
private float maxIntensity = 2f; // Maximum light intensity (noon)
|
|
[SerializeField]
|
|
private Light sunlight; // Reference to the sunlight light source
|
|
[SerializeField] private GameObject sunTarget; // Reference to the sun target object for rotation
|
|
public int money;
|
|
//public int day;
|
|
public int curPopulation;
|
|
public int curJobs;
|
|
public int curFood;
|
|
public int maxPopulation;
|
|
public int maxJobs;
|
|
public int incomePerJob;
|
|
public TextMeshProUGUI moneyTxt;
|
|
public TextMeshProUGUI dayText;
|
|
public TextMeshProUGUI populationTxt;
|
|
public TextMeshProUGUI jobsTxt;
|
|
public TextMeshProUGUI foodTxt;
|
|
public List<Building> buildings = new List<Building>();
|
|
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
|
void Start()
|
|
{
|
|
UpdateWeekDay(); // Initialize curDay with the correct day name
|
|
UpdateStats();
|
|
timeSpeedUp = false; // Initialize timeSpeedUp to false
|
|
}
|
|
void Update()
|
|
{
|
|
// Set the time multiplier based on whether time is sped up
|
|
timeMultiplier = timeSpeedUp ? 48f : 12f;
|
|
// Update the current time
|
|
UpdateCurrentTime();
|
|
// Update the day cycle
|
|
DayCycle();
|
|
// Make the sunlight always aim at the moving sun target
|
|
if (sunlight != null && sunTarget != null)
|
|
{
|
|
sunlight.transform.LookAt(sunTarget.transform.position);
|
|
}
|
|
}
|
|
//called when placing a building
|
|
public void OnPlaceBuilding(Building building)
|
|
{
|
|
//apply the building preset stats
|
|
money -= building.preset.cost;
|
|
maxPopulation += building.preset.population;
|
|
maxJobs += building.preset.jobs;
|
|
//add the building to the list of buildings
|
|
buildings.Add(building);
|
|
//update the stats text
|
|
UpdateStats();
|
|
}
|
|
//called when bulldozing a building
|
|
public void OnRemoveBuilding(Building building)
|
|
{
|
|
//apply the building preset stats
|
|
maxPopulation -= building.preset.population;
|
|
maxJobs -= building.preset.jobs;
|
|
//remove the building from the list of buildings
|
|
buildings.Remove(building);
|
|
//destroy the building game object
|
|
Destroy(building.gameObject);
|
|
//update the stats text
|
|
UpdateStats();
|
|
}
|
|
|
|
//update the stats text
|
|
void UpdateStats()
|
|
{
|
|
moneyTxt.text = "$" + money;
|
|
populationTxt.text = curPopulation + " / " + maxPopulation;
|
|
jobsTxt.text = curJobs + " / " + maxJobs;
|
|
foodTxt.text = curFood.ToString();
|
|
}
|
|
|
|
//called when clicking "End Turn" button
|
|
public void EndDay()
|
|
{
|
|
//calculate the updated stats
|
|
CalculateMoney();
|
|
CalculatePopulation();
|
|
CalculateJobs();
|
|
CalculateFood();
|
|
UpdateStats();
|
|
UpdateWeekDay(); // Update the current day of the week
|
|
}
|
|
|
|
private void UpdateWeekDay()
|
|
{
|
|
if (curDay == null)
|
|
{
|
|
curDay = weekDay[0]; // Initialize with Sunday
|
|
}
|
|
else
|
|
{
|
|
int currentIndex = Array.IndexOf(weekDay, curDay);
|
|
int nextIndex = (currentIndex + 1) % weekDay.Length; // Loop back to the start after Saturday
|
|
curDay = weekDay[nextIndex];
|
|
}
|
|
}
|
|
|
|
void CalculateMoney()
|
|
{
|
|
money += curJobs * incomePerJob;
|
|
foreach (Building building in buildings)
|
|
{
|
|
money -= building.preset.costPerTurn;
|
|
}
|
|
}
|
|
void CalculatePopulation()
|
|
{
|
|
if (curFood >= curPopulation && curPopulation < maxPopulation)
|
|
{
|
|
curFood -= curPopulation / 4;
|
|
curPopulation = Mathf.Min(curPopulation + (curFood / 4), maxPopulation);
|
|
}
|
|
else if (curFood < curPopulation)
|
|
{
|
|
curPopulation = curFood;
|
|
}
|
|
}
|
|
void CalculateJobs()
|
|
{
|
|
curJobs = Mathf.Min(curPopulation, maxJobs);
|
|
}
|
|
void CalculateFood()
|
|
{
|
|
curFood = 0;
|
|
foreach (Building building in buildings)
|
|
{
|
|
curFood += building.preset.food;
|
|
}
|
|
}
|
|
private float UpdateCurrentTime()
|
|
{
|
|
// Always use the current timeMultiplier based on timeSpeedUp
|
|
float currentMultiplier = timeSpeedUp ? 48f : 12f;
|
|
curTime += Time.deltaTime * 60 * currentMultiplier; // Update current time in seconds
|
|
// Check if a full day has passed (86400 seconds)
|
|
if (curTime >= 86400f) // 24 hours * 60 minutes * 60 seconds
|
|
{
|
|
curTime = 0f; // Reset the timer
|
|
EndDay(); // Call the EndTurn method to process the end of the day
|
|
}
|
|
// Display the current time in hours and minutes
|
|
int hours = (int)(curTime / 3600);
|
|
int minutes = (int)((curTime % 3600) / 60);
|
|
string currentDayName = curDay; // Use the current day name
|
|
dayText.text = $"{currentDayName}\n{hours:D2}:{minutes:D2}";
|
|
return curTime;
|
|
}
|
|
public void SpeedUpTime()
|
|
{
|
|
// Toggle the time speed up flag
|
|
timeSpeedUp = !timeSpeedUp;
|
|
}
|
|
private void DayCycle()
|
|
{
|
|
if (sunlight == null || sunTarget == null) return;
|
|
|
|
float intensity = minIntensity;
|
|
Vector3 sunPosition = sunriseTarget.transform.position; // Default to sunrise
|
|
|
|
if (curTime >= sunriseTime && curTime <= sunsetTime)
|
|
{
|
|
// Daytime period (6 AM to 8 PM)
|
|
if (curTime <= noonTime)
|
|
{
|
|
// Sunrise to noon - intensity increases, sun moves from sunrise to noon position
|
|
float t = (curTime - sunriseTime) / (noonTime - sunriseTime);
|
|
intensity = Mathf.Lerp(minIntensity, maxIntensity, t);
|
|
sunPosition = Vector3.Lerp(sunriseTarget.transform.position, noonTarget.transform.position, t);
|
|
#if UNITY_EDITOR
|
|
Debug.Log($"Sunrise period - Time: {curTime:F0}, Intensity: {intensity:F2}");
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// Noon to sunset - intensity decreases, sun moves from noon to sunset position
|
|
float t = (curTime - noonTime) / (sunsetTime - noonTime);
|
|
intensity = Mathf.Lerp(maxIntensity, minIntensity, t);
|
|
sunPosition = Vector3.Lerp(noonTarget.transform.position, sunsetTarget.transform.position, t);
|
|
#if UNITY_EDITOR
|
|
Debug.Log($"Sunset period - Time: {curTime:F0}, Intensity: {intensity:F2}");
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Nighttime period (8 PM to 6 AM)
|
|
intensity = minIntensity;
|
|
// During night, keep the sun at sunset position (sun is "below horizon")
|
|
sunPosition = sunsetTarget.transform.position;
|
|
#if UNITY_EDITOR
|
|
Debug.Log($"Night cycle active - Time: {curTime:F0}, Intensity: {intensity:F2}");
|
|
#endif
|
|
}
|
|
|
|
// Move the sun target and apply light intensity
|
|
sunlight.transform.position = sunPosition;
|
|
sunlight.intensity = intensity;
|
|
}
|
|
}
|