Untitled

 avatar
unknown
plain_text
2 years ago
24 kB
7
No Index
using UnityEngine;
using Unity.MLAgents;
using UnityEditor.PackageManager;

public class Player : MonoBehaviour 
{
    GameObject shipCenter;
    private UIManager _uiManager;
    private GameManager _gameManager;
    public PlayerStatus _playerStatus;
    public PlayerAgent obj; 

    [SerializeField] public GameObject _playerExplosion;
    [SerializeField] public GameObject _invincibilityAnim;
    [SerializeField] public GameObject _boosterAnim;


    private PlayerAgent _agent;
    [SerializeField] public GameObject _laserPrefab;
    [SerializeField] GameObject _spreadShotPrefab;
    [SerializeField] public GameObject _shieldGameObject;
    [SerializeField] public GameObject _centerGameObject; // The center of the ship from which shots fire out
    enum ControlStyle
    {
        Version1,
        Version2
    }

    [SerializeField] private ControlStyle controlStyle = ControlStyle.Version1;

    [SerializeField] private float playerSpeed = 8f;    
    [SerializeField] private float rotationSpeed = 180f;
    private float diagonalPlayerSpeed;

    [SerializeField] private float _fireRate = 0.08f;
    [SerializeField] public float laserSpeed = 50f;
    [SerializeField] public int lives = 3; // Hitpoints
    private float _fireTime = 0.0f;

    // World borders
    private float topBorder = 4.6f;
    private float bottomBorder = -4.6f;
    private float leftBorder = -10.1f;
    private float rightBorder = 10.1f;

    private float shootingRadius = 0.5f; // Determines the radius around player at which lasers shoot out from    
    public float hitBoxRadius = .5f;
    public bool hasShield = false;
    public float spreadShotTimeLeft = 0.0f;
    public float invincibleTimeLeft = 0.0f;

    public int currentPhase;
    public int previousPhase;

    void Start () 
    {
        _uiManager = GameObject.Find("Canvas").GetComponent<UIManager>();
        _gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
        _playerStatus = GameObject.Find("PlayerStatus").GetComponent<PlayerStatus>();
        obj = gameObject.GetComponent<PlayerAgent>();


        _uiManager.score = 0;
        _uiManager.UpdateScore(0);
        _uiManager.difficulty = 1;

        previousPhase = 1;
        currentPhase = 1;
    }







    private void FixedUpdate()
    {
        if (_gameManager.isPaused == false)
        {
            diagonalPlayerSpeed = playerSpeed / (Mathf.Sqrt(2));

            //Debug.LogError(agents.Length);

            if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow) ||
                Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow) ||
                Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow) ||
                Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
            {
                _boosterAnim.gameObject.SetActive(true);

                if (controlStyle == ControlStyle.Version1)
                {
                    int rotate = 0;
                    int strafe = 0;

                    // Rotation
                    if (Input.GetKey(KeyCode.LeftArrow))
                    {
                        rotate = 1;
                    }
                    else if (Input.GetKey(KeyCode.RightArrow))
                    {
                        rotate = 2;
                    }

                    // Strafing (can be done at the same time as rotating).
                    // Up
                    if (Input.GetKey(KeyCode.W))
                    {
                        strafe = 1;
                    }
                    // Down
                    else if (Input.GetKey(KeyCode.S))
                    {
                        strafe = 2;
                    }
                    // Right
                    else if (Input.GetKey(KeyCode.D))
                    {
                        strafe = 3;
                    }
                    // Left
                    else if (Input.GetKey(KeyCode.A))
                    {
                        strafe = 4;
                    }

                    Movement_V1(rotate, strafe);
                }
                else
                {
                    int strafe = 0;
                    int action = 0;

                    if (Input.GetKey(KeyCode.Space))
                    {
                        strafe = 1;
                    }

                    // Up left
                    if ((Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow)) && (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow)))
                    {
                        action = 1;
                    }
                    // Up right
                    else if ((Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow)) && (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow)))
                    {
                        action = 2;
                    }
                    // Down left
                    else if ((Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow)) && (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow)))
                    {
                        action = 3;
                    }
                    // Down right
                    else if ((Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow)) && (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow)))
                    {
                        action = 4;
                    }
                    else
                    {
                        // Left
                        if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
                        {
                            action = 5;
                        }
                        // Right
                        else if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
                        {
                            action = 6;
                        }
                        // Up
                        else if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
                        {
                            action = 7;
                        }
                        // Down
                        else if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
                        {
                            action = 8;
                        }
                    }

                    Movement_V2(action, strafe);
                }
            }
            else
            {
                _boosterAnim.gameObject.SetActive(false);
            }

            spreadShotTimeLeft -= Time.fixedDeltaTime;
            if (spreadShotTimeLeft > 0)
            {
                _fireRate = 0.075f;
                laserSpeed = 70f;
            }
            else
            {
                _fireRate = 0.08f;
                laserSpeed = 50f;
            }

            invincibleTimeLeft -= Time.fixedDeltaTime;
            if (invincibleTimeLeft <= 0)
            {
                _invincibilityAnim.gameObject.SetActive(false);
            }

            Shoot();
        }
    }

    public void UpdatePhase(int newPhase)
    {
        Debug.Log("update phase " + newPhase + " " + currentPhase);
        // Debug.LogError("you are here");

        //GameObject[] agents = GameObject.FindGameObjectsWithTag("PlayerAgent");
        Component[] components = gameObject.GetComponents(typeof(Component));
        foreach (Component component in components)
        {
            Debug.Log(component.ToString());
            if (component is PlayerAgent)
            {
                Debug.Log("PlayerAgent component found.");
                ((PlayerAgent)component).HandlePhaseAdvance();
            }
        }
        obj.HandlePhaseAdvance();
        if (newPhase > currentPhase)
        {
            previousPhase = currentPhase;
            currentPhase = newPhase;
            //_agent.HandlePhaseAdvance();
            // obj.HandlePhaseAdvance();
            // gameObject.GetComponent<PlayerAgent>().HandlePhaseAdvance();
            //GetComponent<PlayerAgent>().HandlePhaseAdvance();
        }
    }

    public void Movement_V1(int rotate, int strafe)
    {
        // Rotation
        if (rotate == 1)
        {
            transform.rotation = Quaternion.Euler(0, 0, transform.rotation.eulerAngles.z + Time.deltaTime * rotationSpeed);
        }
        else if (rotate == 2)
        {
            transform.rotation = Quaternion.Euler(0, 0, transform.rotation.eulerAngles.z - Time.deltaTime * rotationSpeed);
        }

        // Strafing (can be done at the same time as rotating).
        // Up
        if (strafe == 1)
        {
            transform.position += transform.up * Time.deltaTime * playerSpeed;
        }
        // Down
        else if (strafe == 2)
        {
            transform.position -= transform.up * Time.deltaTime * playerSpeed;
        }
        // Right
        else if (strafe == 3)
        {
            transform.position += transform.right * Time.deltaTime * playerSpeed;
        }
        // Left
        else if (strafe == 4)
        {
            transform.position -= transform.right * Time.deltaTime * playerSpeed;
        }

        transform.position = new Vector3(
            Mathf.Clamp(transform.position.x, leftBorder, rightBorder),
            Mathf.Clamp(transform.position.y, bottomBorder, topBorder),
            0.0f
        );
    }

    public void Movement_V2(int action, int strafe)
    {
        Quaternion target = Quaternion.Euler(0, 0, transform.eulerAngles.z);

        // Up left
        if (action == 1)
        {
            if (transform.position.y < topBorder)
            {
                transform.position += Vector3.up * Time.deltaTime * diagonalPlayerSpeed;
            }
            if (transform.position.x > leftBorder)
            {
                transform.position += Vector3.left * Time.deltaTime * diagonalPlayerSpeed;
            }

            target = Quaternion.Euler(0, 0, 45);
        }
        // Up right
        else if (action == 2)
        {
            if (transform.position.y < topBorder)
            {
                transform.position += Vector3.up * Time.deltaTime * diagonalPlayerSpeed;
            }
            if (transform.position.x < rightBorder)
            {
                transform.position += Vector3.right * Time.deltaTime * diagonalPlayerSpeed;
            }

            target = Quaternion.Euler(0, 0, 315);
        }
        // Down left
        else if (action == 3)
        {
            if (transform.position.y > bottomBorder)
            {
                transform.position += Vector3.down * Time.deltaTime * diagonalPlayerSpeed;
            }
            if (transform.position.x > leftBorder)
            {
                transform.position += Vector3.left * Time.deltaTime * diagonalPlayerSpeed;
            }

            target = Quaternion.Euler(0, 0, 135);
        }
        // Down right
        else if (action == 4)
        {
            if (transform.position.y > bottomBorder)
            {
                transform.position += Vector3.down * Time.deltaTime * diagonalPlayerSpeed;
            }
            if (transform.position.x < rightBorder)
            {
                transform.position += Vector3.right * Time.deltaTime * diagonalPlayerSpeed;
            }

            target = Quaternion.Euler(0, 0, 225);
        }
        else
        {
            // Left
            if (action == 5)
            {
                if (transform.position.x > leftBorder)
                {
                    transform.position += Vector3.left * Time.deltaTime * playerSpeed;
                }
                target = Quaternion.Euler(0, 0, 90);
            }
            // Right
            else if (action == 6)
            {
                if (transform.position.x < rightBorder)
                {
                    transform.position += Vector3.right * Time.deltaTime * playerSpeed;
                }
                target = Quaternion.Euler(0, 0, 270);
            }
            // Up
            else if (action == 7)
            {
                if (transform.position.y < topBorder)
                {
                    transform.position += Vector3.up * Time.deltaTime * playerSpeed;
                }
                target = Quaternion.Euler(0, 0, 0);
            }
            // Down
            else if (action == 8)
            {
                if (transform.position.y > bottomBorder)
                {
                    transform.position += Vector3.down * Time.deltaTime * playerSpeed;
                }
                target = Quaternion.Euler(0, 0, 180);
            }
        }

        if (strafe == 0)
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * rotationSpeed);
        }
    }

    public void Damaged(int damage)
    {
        if (invincibleTimeLeft <= 0)
        {
            if (hasShield == true)
            {
                hasShield = false;
                _shieldGameObject.SetActive(false);
                return;
            }

            else
            {
                lives -= damage;

                if (lives <= 0)
                {
                    // Player died
                    Instantiate(_playerExplosion, transform.position, Quaternion.identity);
                    _gameManager.StopCoroutines();
                    _gameManager.GameOver();
                    resetOnDeath();
                }
                else
                {
                    invincibleTimeLeft = 3.0f;
                    _invincibilityAnim.gameObject.SetActive(true);
                }

                if (_uiManager != null && gameObject != null)
                {
                    _uiManager.UpdateLives(lives);
                }
            }
        }
    }

    void resetOnDeath()
    {
        lives = 3;

        transform.position = new Vector3(0.0f, -4.5f, 0.0f);
        transform.rotation = Quaternion.identity;

        _uiManager.HideBossWarning();
        _uiManager.HideBossInfo();

        hasShield = false;
        _shieldGameObject.SetActive(false);

        spreadShotTimeLeft = 0.0f;
        _fireRate = 0.08f;
        laserSpeed = 50f;
    }

    public void Shoot()
    {
        if (Time.time > _fireTime)
        {
            Vector2 laserDir = Mathf.Sqrt(laserSpeed) * transform.up;

            float laserAng = laserAngle(laserDir.x, laserDir.y);
            Vector2 laserStartPos = laserStartPosition(laserDir.x, laserDir.y);

            shipCenter = _centerGameObject;

            GameObject clone = (GameObject)Instantiate(_laserPrefab, new Vector3(shipCenter.transform.position.x + laserStartPos.x, shipCenter.transform.position.y + laserStartPos.y, 0), Quaternion.Euler(0, 0, laserAng));
            clone.GetComponent<Rigidbody2D>().velocity = laserDir;            

            if (spreadShotTimeLeft > 0)
            {
                spreadShot(laserAng);
            }   

            // Limit fire rate
            _fireTime = Time.time + _fireRate;
        }
    }

    // Spreadshot code
    private float offsetAngleToPositive(float offsetAngle)
    {
        return 360 - (360 - ((360 + offsetAngle) % 360));
    }
    private int angle360ToQuadrant(float angle)
    {
        // Given an angle from 0 to 360, starting north and counterclockwise
        // return the quadrant
        angle = angle % 360;

        if (angle > 0 && angle < 90)
        {
            return 4;
        }
        else if (angle > 90 && angle < 180)
        {
            return 3;
        }
        else if (angle > 180 && angle < 270)
        {
            return 2;
        }
        else if (angle > 270 && angle < 360)
        {
            return 1;
        }
        return -1; // Must be one of the 4 cardinal directions 0, 90, 180 or 270
    }
    private float degreesToRadians(float degrees)
    {
        return degrees * (Mathf.PI / 180f);
    }
    private Vector2 angleAndQuadrantToDirection(float angle, int quadrant)
    {
        float newX = 0;
        float newY = 0;
        float r = Mathf.Sqrt(laserSpeed);
        float radians = 0;

        if (quadrant == -1) // Cardinal directions
        {
            if (angle == 0)
            {
                newX = 0;
                newY = r;
            }
            else if (angle == 90)
            {
                newX = -r;
                newY = 0;
            }
            else if (angle == 180)
            {
                newX = 0;
                newY = -r;
            }
            else if (angle == 270)
            {
                newX = r;
                newY = 0;
            }
        }

        // Approach:
        // Translate each angle to 0-90 degree angles (exclusive).
        // This way sine and cosine always give back positive values
        else
        {
            if (quadrant == 1)
            {
                // +X, +Y
                angle = angle - 270;
                radians = degreesToRadians(angle);

                newX = r * Mathf.Cos(radians);
                newY = r * Mathf.Sin(radians);
            }
            else if (quadrant == 2)
            {
                // +X, -Y
                angle = angle - 180;
                radians = degreesToRadians(angle);

                newX = r * Mathf.Sin(radians);
                newY = -(r * Mathf.Cos(radians));
            }
            else if (quadrant == 3)
            {
                // -X, -Y
                angle = angle - 90;
                radians = degreesToRadians(angle);

                newX = -(r * Mathf.Cos(radians));
                newY = -(r * Mathf.Sin(radians));
            }
            else if (quadrant == 4)
            {
                // -X, +Y
                radians = degreesToRadians(angle);

                newX = -(r * Mathf.Sin(radians));
                newY = r * Mathf.Cos(radians);
            }
        }

        return new Vector2(newX, newY);
    }
    private void spreadShot(float centerAngle)
    {
        // Given the center laser's position, create the other lasers in the spread shot
        // Offset angle to degrees equation
        // new angle (0-360)
        shipCenter = _centerGameObject; // Ship's center
        
        // Spread laser 1
        spreadLaser(centerAngle - 7f);

        // Spread laser 2
        spreadLaser(centerAngle + 7f);

        // 5 laser spread shot
        // spreadLaser(centerAngle - 13f);
        // spreadLaser(centerAngle + 13f);
    }

    private void spreadLaser(float angle)
    {
        GameObject laserclone;
        float laserAng = offsetAngleToPositive(angle);
        int laserQuadrant = angle360ToQuadrant(laserAng);
        Vector2 laserDirection = angleAndQuadrantToDirection(laserAng, laserQuadrant);
        Vector2 laserStartPos = laserStartPosition(laserDirection.x, laserDirection.y);
        laserclone = (GameObject)Instantiate(_laserPrefab, new Vector3(_centerGameObject.transform.position.x + laserStartPos.x, _centerGameObject.transform.position.y + laserStartPos.y, 0), Quaternion.Euler(0, 0, laserAng));
        laserclone.GetComponent<Rigidbody2D>().velocity = laserDirection;
    }

    // Main laser code
    // calculates direction of laser path based on player position and mouse click position        
    private Vector2 laserDirection()
    {                        
        float newX;
        float newY;        

        var curMousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        float mouseX = curMousePosition.x;
        float mouseY = curMousePosition.y;        
        float playerX = transform.position.x;
        float playerY = transform.position.y;
        
        var deltaX = mouseX - playerX;
        var deltaY = mouseY - playerY;
        
        if (deltaX == 0)
        {
            newX = 0;
            newY = Mathf.Sqrt(laserSpeed);
        }
        else if (deltaY == 0)
        {
            newX = Mathf.Sqrt(laserSpeed);
            newY = 0;
        }
        else
        {
            // Maths!
            // Calculate and set the values of x and y such that this holds always
            // x^2 + y^2 = laserSpeed
            float ratio = deltaX / deltaY;            

            float tempx = Mathf.Sqrt(laserSpeed / ((1 + (1 / (ratio * ratio)))));
            float tempy = tempx / ratio;

            newX = tempx;
            newY = tempy;            
        }

        // quadrant determines signs of x and y values
        // this is relative to the position of the player not the world
        int quadrant;

        if (deltaX >= 0 && deltaY >= 0)
        {
            quadrant = 1;
        }
        else if (deltaX >= 0 && deltaY < 0)
        {
            quadrant = 2;
        }
        else if (deltaX < 0 && deltaY < 0)
        {
            quadrant = 3;
        }
        else
        {
            quadrant = 4;
        }
        // Set the quadrant sign
        if (quadrant == 1 || quadrant == 2)
        {
            newX = Mathf.Abs(newX);
        }
        else
        {
            newX = -(Mathf.Abs(newX));
        }
        if (quadrant == 1 || quadrant == 4)
        {
            newY = Mathf.Abs(newY);
        }
        else
        {
            newY = -(Mathf.Abs(newY));
        }
        
        return new Vector2(newX, newY);
    }
    private float laserAngle(float x, float y)
    {
        float angle;
        
        // Check for zeros
        if (x == 0) // Vertical shot
        {
            if (y >= 0) // quadrants 1 and 4
            {
                // Straight up
                angle = 0f;
            }
            else // quadrants 2 and 3
            {
                // straight down
                angle = 180f;
            }
        }
        else if (y == 0) // Horizontal shot
        {
            if (x >= 0) // quadrants 1 and 2
            {
                angle = 270f;
            }
            else
            {
                angle = 90f;
            }
        }
        else
        {
            float radians = Mathf.Atan(y / x);
            angle = radians * (180 / Mathf.PI);

            // quadrant 1
            if (x >= 0 && y >= 0) {
                angle += 270f;   
            }

            // quadrant 2
            if (x >= 0 && y < 0)
            {
                angle += 270f;
            }

            // quadrant 3
            if (x < 0 && y < 0)
            {
                angle += 90;
            }

            // quadrant 4
            if (x < 0 && y >= 0)
            {
                angle += 90;
            }
        }

        return angle;
    }
    private Vector2 laserStartPosition(float x, float y)
    {
        // Make x^2 + y^2 = shootingRadius^2
        // x and y are the velocity vectors.
        // This function will translate the triangle x, y, R to a similar triangle.
        float velocityRadius = Mathf.Sqrt((x * x) + (y * y));
        float newRatio = shootingRadius / velocityRadius;

        float shootingX = newRatio * x;
        float shootingY = newRatio * y;

        return new Vector2(shootingX, shootingY);
    }

    // Powerups implement
    public void powerupHealth()
    {
        lives = Mathf.Min(lives + 1, 5);
        _uiManager.UpdateLives(lives);
    }

    public void powerupShield()
    {
        hasShield = true;
        _shieldGameObject.SetActive(true);
    }
    public void powerupRapidShot()
    {
        spreadShotTimeLeft = 10.0f;
    }
}
Editor is loading...
Leave a Comment