using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.IO;
using UnityEngine.SceneManagement;
using UnityEditor.PackageManager.UI;
using Unity.Collections.LowLevel.Unsafe;
public class Player : MonoBehaviour
{
//getting refranses to other scripts
public Gun gun;
public StartMenu startMenu;
//UI objects
public TextMeshProUGUI dashText;
public TextMeshProUGUI keyText;
public TextMeshProUGUI runTimeText;
public Image dashUi;
Vector2 MousePosition;
//player movment vareables
private Rigidbody2D body;
private const int BASE_SPEED = 5;
private Vector3 savePoint = Vector3.zero;
[SerializeField] private int minKeys;
private int keysCollected;
//abilitie vareables
//dash
private bool canDash = true;
private int dashAmount = 0;
private int dashesCount = 0;
private const int dashSpeed = 5;
private float dashDuration = 0.5f;
private float dashTime;
private int dashCooldownTime = 5;
private float dashCoolDownTimeLeft = 5f;
//Scoring vareables
public float runTime = 1000000000000;
string path = Path.Combine(Application.dataPath, "../Data/hightScore.txt");
///
/// Initializes the script by setting up the necessary components and variables.
/// This method is called before the first frame update.
///
void Start()
{
body = GetComponent(); // Assigns the Rigidbody2D component to the 'body' variable
savePoint = transform.position; // Sets the starting save point
}
///
/// Update is called once per frame
///
void Update()
{
// Check if the left mouse button (if hte player is shooting or not)
if (Input.GetMouseButtonDown(0))
{
//runs the fire method in the gun script
gun.Fire();
}
// Update the MousePosition to the current mouse position in world space
MousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
private void FixedUpdate()
{
//Rotating the player
Vector2 aimDirection = MousePosition - (Vector2)transform.position;
float aimAngle = Mathf.Atan2(aimDirection.y, aimDirection.x) * Mathf.Rad2Deg - 90f;
body.rotation = aimAngle;
// check if I am not holding the shift keys
if (!Input.GetKey(KeyCode.LeftShift) && !Input.GetKey(KeyCode.RightShift))
{
// Check if a dash was in progress
if (dashTime > 0)
{
// Reset dash-related variables if a dash was in progress
canDash = false; // Disable further dashing until the dash cooldown is complete
dashesCount--; // Decrease the count of available dashes
dashTime = 0; // Reset dashTime to zero to indicate no ongoing dash
}
else
{
// If no dash was in progress, reset dash-related variables to default
canDash = true; // Allow dashing again if the cooldown has elapsed
dashTime = 0; // Ensure dashTime is set to zero
}
}
// Dashing logic
if ((Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) && dashesCount > 0 && dashTime < dashDuration && canDash && (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0))
{
// Set the velocity for dashing in all directions
body.velocity = new Vector2(Input.GetAxis("Horizontal") * BASE_SPEED * dashSpeed, Input.GetAxis("Vertical") * BASE_SPEED * dashSpeed);
dashTime += Time.deltaTime;
}
else
{
// Normal movement when not dashing
body.velocity = new Vector2(Input.GetAxis("Horizontal") * BASE_SPEED, Input.GetAxis("Vertical") * BASE_SPEED);
}
// Reset dash state and change dash count when dash duration is exceeded
if (dashTime >= dashDuration)
{
canDash = false;
dashesCount--;
dashTime = 0;
}
//checking if the dash count is less then the dash amount to see if dashes need to be regenarated or not
if (dashesCount < dashAmount)
{
// decreasing the dash amount
dashCoolDownTimeLeft -= Time.deltaTime;
// checking if the dash cooldown has been completed
if (dashCoolDownTimeLeft < 0)
{
//increasing the dash count and reseting the dash cooldown
dashesCount++;
dashCoolDownTimeLeft += dashCooldownTime;
}
}
else
{
//reseting the dash cooldown
dashCoolDownTimeLeft = dashCooldownTime;
}
//dash UI
//checking the dash cooldown symbol should be displayed
if (dashAmount > 0)
{
//filling the dash cooldown symbol based on how much time is left for it to fully charge
//the next dash
dashUi.fillAmount = (1 / (dashCooldownTime / dashCoolDownTimeLeft));
}
else
{
//not displaying the dash cooldown symbol
dashUi.fillAmount = 0;
}
// increasing the run time
runTime += Time.deltaTime;
//displaying the amount of dashes left, keys Collected, and run time
dashText.text = "dashes left: " + dashesCount;
keyText.text = "Keys Collected : " + keysCollected;
runTimeText.text = "Time : " + Math.Round(runTime * 1000f) / 1000f;
}
///
/// this function runs when ever this object (the player object) collides with something, to check
///
///
private void OnCollisionEnter2D(Collision2D collision)
{
//check if the object is tagged 'Death' to reset the player position if it is
if (collision.gameObject.CompareTag("Death"))
{
transform.position = savePoint;
}
}
///
/// This function runs when ever the player enters a trigger collider
///
///
private void OnTriggerEnter2D(Collider2D collision)
{
// checking if the player is colliding with a object taged key
if (collision.gameObject.CompareTag("Key"))
{
//distoy the colliding object and increas keyscollected by one
Destroy(collision.gameObject);
keysCollected++;
}
//checking if the player is colliding with a object taged Dash
else if (collision.gameObject.CompareTag("Dash"))
{
//distoy the colliding object and increas dashAount by one
Destroy(collision.gameObject);
dashAmount++;
dashesCount = dashAmount;
}
//checking if the player is colliding with a object taged Checkpoint
else if (collision.gameObject.CompareTag("Checkpoint"))
{
//seting the players save point to the center of that position
savePoint = collision.transform.position;
}
//checking if the player is colliding with a object taged FinishLine and that they have collected all the keys that they need to to pass the game
else if (collision.gameObject.CompareTag("FinishLine") && keysCollected >= minKeys)
{
// run the newRun function
EndRun();
}
}
///
/// This function runs when ever the player finishes the game
///
public void EndRun()
{
//rounding the runtime value so its not an unapealing large number (large in digits)
runTime = (float)Math.Round(runTime * 1000f) / 1000f;
//this Sets the path to the save data location
string path = Path.Combine(Application.dataPath, "../Data/hightScore.txt");
//try catch structure to check if the files have been temperd with or curupted
try
{
//checking if the file is in the correct format
string[] lines = File.ReadAllLines(path);
if (lines.Length <= 1)
{
// decreasing the runtime by 5 for every key that the user has over the minimum ammount
while(keysCollected > minKeys)
{
keysCollected--;
runTime -= 5;
}
//if the player high score is empty then set the new high score as the current score
if (lines.Length == 0)
{
File.WriteAllText(path, runTime.ToString());
}
// if the player score is better then the high score then set the new high score as the current score
else if (runTime < float.Parse(lines[0]))
{
File.WriteAllText(path, runTime.ToString());
}
}
//if there are too many liens then empty then emptry the file
else
{
File.WriteAllText(path, String.Empty);
}
}
catch
{
}
// change the scene to the finishing scene
SceneManager.LoadScene("Finish");
}
}