gather-and-defend/Assets/Scripts/Opponent/MultiEyedOpponent.cs
Adam Salah b05a3245c0 implemented desert heavy monster (#16)
Reviewed-on: #16
Reviewed-by: EliaGingras1 <william-gin1@hotmail.com>
Co-authored-by: Adam Salah <adam-hamid.salah-salah.1@ens.etsmtl.ca>
Co-committed-by: Adam Salah <adam-hamid.salah-salah.1@ens.etsmtl.ca>
2025-09-07 22:46:45 +00:00

93 lines
3.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class MultiEyedOpponent : Opponent
{
[SerializeField]
private float _eyeMaxDistance = 2.0f;
[SerializeField]
private float _eyeSpeed = 3.0f;
[SerializeField]
private GameObject[] _eyes;
private int _eyeLossHpInterval;
private List<GameObject> _remainingEyes = new List<GameObject>();
// tuple: (eye instance, start position, distance to end of arc, point to stop mid arc, start angle, modulated speed)
private List<(GameObject eye ,float startX, float distance, float destination, float angle, float speed)> _dyingEyes =
new List<(GameObject eye, float startX, float distance, float destination, float angle, float speed)>();
public override void Start()
{
base.Start();
_remainingEyes.AddRange(_eyes);
_eyeLossHpInterval = Hp / _eyes.Length;
}
public override void Update()
{
base.Update();
// Check if Hp threshold for eye loss is reached
if (_remainingEyes.Count > Hp / _eyeLossHpInterval)
{
int i = Random.Range(0, _remainingEyes.Count);
var removedEye = _remainingEyes[i];
var dyingEye = Instantiate(removedEye, transform);
// Render in front of units
var renderer = dyingEye.GetComponent<SpriteRenderer>();
renderer.sortingLayerName = "Unit";
renderer.sortingOrder = 100;
// Setup launch params
float startX = dyingEye.transform.position.x;
float distance = Mathf.Sign(Random.Range(-1.0f, 1.0f)) * Random.Range(_eyeMaxDistance / 5, _eyeMaxDistance);
float destination = Random.Range(distance / 2, distance);
float angle = Random.Range(30.0f, 80.0f);
float speed = Mathf.Sqrt(90 * 90 - angle * angle) / 90 * _eyeSpeed;
_dyingEyes.Add((dyingEye, startX, distance, destination, angle, speed));
// Remove from remaining eyes
_remainingEyes.RemoveAt(i);
removedEye.SetActive(false);
}
// Update dying eyes position
foreach (var entry in _dyingEyes)
{
var eye = entry.eye;
if (!eye) continue;
// Get tuple launch params
float startX = entry.startX;
float distance = entry.distance;
float destination = entry.destination;
float angle = entry.angle;
float speed = entry.speed;
// Arc function
float k = Mathf.Sign(distance) * Mathf.Tan(angle * Mathf.Deg2Rad);
float a = -1.0f / distance;
float x = (eye.transform.position.x - startX) + Mathf.Sign(distance) * speed * Time.deltaTime;
float y = k * (a * x * x + x);
// Check if reached destination
if (Mathf.Abs(x) > Mathf.Abs(destination))
{
eye.GetComponent<Animator>().SetTrigger("Destroy");
continue;
}
// Apply movement if not in destruction animation
Vector2 newPos = new Vector2(startX + x, transform.position.y + y);
eye.transform.position = newPos;
}
}
}