neon_run/Assets/Scripts/GameManager.cs
2025-11-26 07:41:23 +05:30

253 lines
7.7 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Cinemachine;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using static UnityEngine.ParticleSystem;
public class GameManager : MonoBehaviour
{
public bool isAuto = false;
public static GameManager instance;
public void Awake(){
instance = this;
}
public static float movespeed = 0f;
public float acceleration = 5;
public float maxspeed = 30f;
public CinemachineVirtualCamera cam;
public ParticleSystem speedLinesEffect;
public float minFov = 50;
public float maxFov = 90;
public float Distance;
public float max_shake_ferquency = 2f;
public float max_shake_amplitude = 0.08f;
public TMP_Text txtSpeed;
public TMP_Text txtDistance;
public float FovRange => maxFov - minFov;
[Header("Obstacle avoidance")]
public int currentLaneId = 0;
public float laneSwitchSpeed = 10f;
public float laneSwitchRotationMultiplier = 0.2f;
public float[] laneXs = {-1.5f, 0f, 1.5f};
public Transform car;
public CollisionDetector collisionDetector;
EmissionModule speedLinesEmission;
public CinemachineImpulseSource impulseSource;
public GameObject trafficVehiclePrefab;
public List<GameObject> trafficVehicles = new List<GameObject>();
public int maxTrafficVehicles = 10;
public float trafficVehicleSpawnInterval = 5f;
float trafficVehicleSpawnTimer =0f;
public GameObject gameOverScreen;
[Header("Point system")]
public float pointsMultiplier = 1;
public float maxMult;
public float speedMultIncreaseRate = 0.5f;
public float speedMultDecreaseRate = 2f;
public float points;
public float pointsPerSecond = 10;
public TMP_Text txt_points;
public TMP_Text txt_pointsMultiplier;
public TMP_InputField highscoreNameInput;
public GameObject highscorePanel;
float startRotationY;
void Start()
{
speedLinesEmission = speedLinesEffect.emission;
startRotationY = car.eulerAngles.y;
collisionDetector.OnEnter += OnTriggerEnter;
}
public static void Reset(){
instance = null;
SectionTriger.counter=0;
}
// Update is called once per frame
void FixedUpdate()
{
if(lives <=0){return;}
MoveForward();
}
void Update(){
if(isAuto){return;}
if(lives <=0){return;}
HandlePoints();
SwitchLanes();
TrafficVehicleSpawn();
}
void HandlePoints(){
points += pointsPerSecond * Time.deltaTime * pointsMultiplier;
float moveMult = movespeed / maxspeed * 10;
float targetMult = moveMult;
if(targetMult > pointsMultiplier){
pointsMultiplier += Time.deltaTime * speedMultIncreaseRate;
}
else if(targetMult < pointsMultiplier){
pointsMultiplier -= Time.deltaTime * speedMultDecreaseRate;
}
pointsMultiplier = Mathf.Clamp(pointsMultiplier, 0, maxMult);
txt_points.text = points.ToString("000000"); // Always display at least 6 digits, pad with zeros
txt_pointsMultiplier.text = pointsMultiplier.ToString("n1") + " x";
txt_pointsMultiplier.color = new Color(1, 1, 1, Mathf.Lerp(0.5f, 1f, pointsMultiplier / maxMult));
}
void TrafficVehicleSpawn(){
trafficVehicleSpawnTimer += Time.deltaTime * movespeed / maxspeed;
if(trafficVehicleSpawnTimer >= trafficVehicleSpawnInterval){
trafficVehicleSpawnTimer = 0;
SpawnNextTrafficVehicle();
}
}
void SpawnNextTrafficVehicle(){
trafficVehicles.RemoveAll(item => item == null);
if(trafficVehicles.Count < maxTrafficVehicles){
GameObject trafficVehicle = Instantiate(trafficVehiclePrefab, new Vector3(laneXs[currentLaneId], 0, -500), Quaternion.Euler(0,-90,0));
trafficVehicles.Add(trafficVehicle);
}
}
float laneSwitchTime =0;
void SwitchLanes(){
if(displaySpeed < 10){return;}
float switchSpeedMultiplier = 1 + (displaySpeed/laneSwitchSpeed);
if(Input.GetKeyDown(KeyCode.LeftArrow)){
currentLaneId--;
laneSwitchTime = 0;
}
else if(Input.GetKeyDown(KeyCode.RightArrow)){
currentLaneId++;
laneSwitchTime = 0;
}
if(laneSwitchTime < 1){
laneSwitchTime += Time.deltaTime * 2;
}
currentLaneId = Mathf.Clamp(currentLaneId, 0, laneXs.Length - 1);
float lerper = switchSpeedMultiplier*Time.deltaTime * laneSwitchTime;
car.position = new Vector3(Mathf.Lerp(car.position.x,laneXs[currentLaneId],lerper), car.position.y, car.position.z);
float xDist = (car.position.x - laneXs[currentLaneId]);
Vector3 targetRotation = new Vector3(car.eulerAngles.x, startRotationY + Mathf.Atan2(xDist, 1) * Mathf.Rad2Deg * laneSwitchRotationMultiplier * (1-(movespeed/maxspeed)), car.eulerAngles.z);
car.eulerAngles = Vector3.Lerp(car.eulerAngles, targetRotation, lerper);
}
float displaySpeed = 0;
void MoveForward(){
float input = Input.GetAxis("Vertical");
if(isAuto){input = 0; movespeed = maxspeed /3f;}
movespeed += input * acceleration * Time.deltaTime;
movespeed = Mathf.Clamp(movespeed, 0, maxspeed);
float x = (FovRange / maxspeed) * movespeed;
cam.m_Lens.FieldOfView = minFov + x;
cam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>().m_FrequencyGain = max_shake_ferquency * movespeed / maxspeed;
cam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>().m_AmplitudeGain = max_shake_amplitude * movespeed / maxspeed;
displaySpeed = movespeed * 2.5f;
txtSpeed.text = displaySpeed.ToString("n0") + " km/h";
Distance += displaySpeed * Time.deltaTime / 3600;
txtDistance.text = Distance.ToString("n2") + " km";
float fontSize = Mathf.Lerp(10f, 15f, movespeed / maxspeed);
txtSpeed.fontSize = isAuto ? 0 : fontSize;
txtDistance.fontSize = isAuto ? 0 : fontSize;
speedLinesEmission.rateOverTime = displaySpeed > 100 ? displaySpeed : 0;
}
public int lives = 3;
void OnTriggerEnter(Collider other)
{
Debug.Log("OnTriggerEnter: " + other.gameObject.name + " : " + other.gameObject.tag);
string objectNameLowered = other.gameObject.name.ToLower();
if(objectNameLowered.Contains("section")){
return;
}
if(objectNameLowered.Contains("player")){
return;
}
movespeed = maxspeed / 10f;
lives--;
LivesVisualizer.instance.SetLives(lives);
impulseSource.GenerateImpulse();
//Snap to lane
car.position = new Vector3(laneXs[currentLaneId], car.position.y, car.position.z);
if(other.GetComponent<TrafficVehicle>()!=null){
Destroy(other.gameObject);
}
if(lives <=0){
gameOverScreen.SetActive(true);
movespeed=0;
if(GetHighscore() < points){
highscorePanel.SetActive(true);
}
}
}
public void Retry(){
Reset();
SceneManager.LoadScene("GameScene");
}
public void MainMenu(){
Reset();
SceneManager.LoadScene("MainMenu");
}
int GetHighscore(){
if(PlayerPrefs.HasKey("highscore")){
return PlayerPrefs.GetInt("highscore");
}
return 0;
}
public void SetHighscore(){
}
}