2024-03-13 20:01:39 -05:00
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
|
|
|
|
2024-03-14 11:56:10 -05:00
|
|
|
/// <summary>
|
|
|
|
/// Enemy_4 will start offscreen and then pick a random point on screen to
|
|
|
|
/// move to. Once it has arrived, it will pick another random point and
|
|
|
|
/// continue until the player has shot it down.
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
[System.Serializable]
|
|
|
|
public class Part {
|
|
|
|
// These three fields need to be defined in the Inspector pane
|
|
|
|
public string name;
|
|
|
|
public float health;
|
|
|
|
public string[] protectedBy;
|
|
|
|
[HideInInspector]
|
|
|
|
public GameObject go;
|
|
|
|
[HideInInspector]
|
|
|
|
public Material mat;
|
|
|
|
}
|
|
|
|
|
2024-03-13 20:01:39 -05:00
|
|
|
public class Enemy_4 : Enemy
|
|
|
|
{
|
2024-03-14 11:56:10 -05:00
|
|
|
[Header("Set in Inspector: Enemy_4")]
|
|
|
|
public Part[] parts;
|
|
|
|
private Vector3 p0, p1; // The two points to interpolate
|
|
|
|
private float timeStart; // Birth time for this Enemy_4
|
|
|
|
private float duration = 4; // Duration of movement
|
|
|
|
|
2024-03-13 20:01:39 -05:00
|
|
|
void Start()
|
|
|
|
{
|
2024-03-14 11:56:10 -05:00
|
|
|
// There is already an initial position chosen by Main.SpawnEnemy()
|
|
|
|
// so add it to points as the initial p0 & p1
|
|
|
|
p0 = p1 = pos;
|
|
|
|
InitMovement();
|
|
|
|
Transform t;
|
|
|
|
foreach(Part prt in parts) {
|
|
|
|
t = transform.Find(prt.name);
|
|
|
|
if (t != null) {
|
|
|
|
prt.go = t.gameObject;
|
|
|
|
prt.mat = prt.go.GetComponent<Renderer>().material;
|
|
|
|
}
|
|
|
|
}
|
2024-03-13 20:01:39 -05:00
|
|
|
}
|
|
|
|
|
2024-03-14 11:56:10 -05:00
|
|
|
void InitMovement() {
|
|
|
|
p0 = p1; // Set p0 to the old p1
|
|
|
|
// Assign a new on-screen location to p1
|
|
|
|
float widMinRad = bndCheck.camWidth - bndCheck.radius;
|
|
|
|
float hgtMinRad = bndCheck.camHeight - bndCheck.radius;
|
|
|
|
p1.x = Random.Range(-widMinRad, widMinRad);
|
|
|
|
p1.y = Random.Range(-hgtMinRad, hgtMinRad);
|
|
|
|
// Reset the time
|
|
|
|
timeStart = Time.time;
|
|
|
|
}
|
|
|
|
public override void Move() {
|
|
|
|
// This completely overrides Enemy.Move() with a linear interpolation
|
|
|
|
float u = (Time.time - timeStart) / duration;
|
|
|
|
if (u >= 1) {
|
|
|
|
InitMovement();
|
|
|
|
u = 0;
|
|
|
|
}
|
|
|
|
u = 1 - Mathf.Pow(1 - u, 2); // Apply East Out easing to u
|
|
|
|
pos = (1 - u) * p0 + u*p1; // Simple linear interpolation
|
2024-03-13 20:01:39 -05:00
|
|
|
}
|
2024-03-14 18:40:19 -05:00
|
|
|
|
|
|
|
// These two functions find a Part in parts based on name or GameObject
|
|
|
|
Part FindPart(string n) {
|
|
|
|
foreach(Part prt in parts) {
|
|
|
|
if (prt.name == n) {
|
|
|
|
return prt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
Part FindPart(GameObject go) {
|
|
|
|
foreach(Part prt in parts) {
|
|
|
|
if (prt.go == go) {
|
|
|
|
return prt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// These functions return true if the Part has been destroyed
|
|
|
|
bool Destroyed(GameObject go) {
|
|
|
|
return Destroyed(FindPart(go));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Destroyed(string n) {
|
|
|
|
return Destroyed(FindPart(n));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Destroyed(Part prt) {
|
|
|
|
if (prt == null) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return prt.health <= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This changes the color of just one Part to red instead of the whole ship
|
|
|
|
void ShowLocalizedDamage(Material m) {
|
|
|
|
m.color = Color.red;
|
|
|
|
damageDoneTime = Time.time + showDamageDuration;
|
|
|
|
showingDamage = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This will override the OnCollisionEnter that is part of Enemy.cs
|
|
|
|
void OnCollisionEnter(Collision coll) {
|
|
|
|
GameObject other = coll.gameObject;
|
|
|
|
switch (other.tag) {
|
|
|
|
case "ProjectileHero":
|
|
|
|
Projectile p = other.GetComponent<Projectile>();
|
|
|
|
// If this Enemy is off screen, don't damage it.
|
|
|
|
if (!bndCheck.isOnScreen) {
|
|
|
|
Destroy(other);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Hurt this Enemy
|
|
|
|
GameObject goHit = coll.contacts[0].thisCollider.gameObject;
|
|
|
|
Part prtHit = FindPart(goHit);
|
|
|
|
if (prtHit == null) {
|
|
|
|
goHit = coll.contacts[0].otherCollider.gameObject;
|
|
|
|
prtHit = FindPart(goHit);
|
|
|
|
}
|
|
|
|
// Check whether this part is still protected
|
|
|
|
if (prtHit.protectedBy != null) {
|
|
|
|
foreach(string s in prtHit.protectedBy) {
|
|
|
|
// If one of the protecting parts hasn't been destroyed...
|
|
|
|
if (!Destroyed(s)) {
|
|
|
|
// ...then don't damage this part yet
|
|
|
|
Destroy(other);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
prtHit.health -= 1;
|
|
|
|
ShowLocalizedDamage(prtHit.mat);
|
|
|
|
if (prtHit.health <= 0) {
|
|
|
|
prtHit.go.SetActive(false);
|
|
|
|
}
|
|
|
|
bool allDestroyed = true;
|
|
|
|
foreach (Part prt in parts) {
|
|
|
|
if (!Destroyed(prt)) {
|
|
|
|
allDestroyed = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (allDestroyed) {
|
|
|
|
Main.S.ShipDestroyed(this);
|
|
|
|
Destroy(this.gameObject);
|
|
|
|
}
|
|
|
|
Destroy(other);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2024-03-13 20:01:39 -05:00
|
|
|
}
|