Finished first chapter, added script code up to Enemy 3

This commit is contained in:
Trianta
2024-03-13 20:01:39 -05:00
parent b2d02e7133
commit f1ae5c383e
28 changed files with 813 additions and 288 deletions
+16 -2
View File
@@ -10,10 +10,14 @@ public class BoundsCheck : MonoBehaviour
{
[Header("Set in Inspector")]
public float radius = 1f;
public bool keepOnScreen = true;
[Header("Set Dynamically")]
public bool isOnScreen = true;
public float camWidth;
public float camHeight;
[HideInInspector]
public bool offRight, offLeft, offUp, offDown;
void Awake() {
camHeight = Camera.main.orthographicSize;
@@ -22,23 +26,33 @@ public class BoundsCheck : MonoBehaviour
void LateUpdate () {
Vector3 pos = transform.position;
isOnScreen = true;
offRight = offLeft = offUp = offDown = false;
if (pos.x > camWidth - radius) {
pos.x = camWidth - radius;
offRight = true;
}
if (pos.x < -camWidth + radius) {
pos.x = -camWidth + radius;
offLeft = true;
}
if (pos.y > camHeight - radius) {
pos.y = camHeight - radius;
offUp = true;
}
if (pos.y < -camHeight + radius) {
pos.y = -camHeight + radius;
offDown = true;
}
isOnScreen = !(offRight || offLeft || offUp || offDown);
if (keepOnScreen && !isOnScreen) {
transform.position = pos;
isOnScreen = true;
offRight = offLeft = offUp = offDown = false;
}
transform.position = pos;
}
// Draw the bounds in the Scene pane using OnDrawGizmos()
+59
View File
@@ -0,0 +1,59 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
[Header("Set in Inspector: Enemy")]
public float speed = 10f; // The speed in m/s
public float fireRate = 0.3f; // Seconds/shot (Unused)
public float health = 10;
public int score = 100; // Points earned for destroying this
protected BoundsCheck bndCheck;
void Awake() {
bndCheck = GetComponent<BoundsCheck>();
}
// This is a Property: A method that acts like a field
public Vector3 pos {
get {
return( this.transform.position );
}
set {
this.transform.position = value;
}
}
public virtual void Move() {
Vector3 tempPos = pos;
tempPos.y -= speed * Time.deltaTime;
pos = tempPos;
}
void OnCollisionEnter(Collision coll) {
GameObject otherGO = coll.gameObject;
if (otherGO.tag == "ProjectileHero") {
Destroy(otherGO); // Destroy the Projectile
Destroy(gameObject); // Destroy this Enemy GameObject
} else {
print("Enemy hit by non-ProjectileHero: " + otherGO.name);
}
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Move();
if (bndCheck != null && bndCheck.offDown) {
// We're off the bottom, so destroy this GameObject
Destroy(gameObject);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bf379ee257cd884c58f85b182bc79ba4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+42
View File
@@ -0,0 +1,42 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Enemy_1 extends the Enemy class
public class Enemy_1 : Enemy
{
[Header("Set in Inspector: Enemy_1")]
// # seconds for a full sine wave
public float waveFrequency = 2;
// sine wave width in meters
public float waveWidth = 4;
public float waveRotY = 45;
private float x0; // The initial x value of pos
private float birthTime;
// Start works well because it's not used by the Enemy superclass
void Start() {
// Set x0 to the initial x position of Enemy_1
x0 = pos.x;
birthTime = Time.time;
}
// Override the Move function on Enemy
public override void Move() {
// Because pos is a property, you can't directly set pos.x
// so get the pos as an editable Vector3
Vector3 tempPos = pos;
// theta adjusts based on time
float age = Time.time - birthTime;
float theta = Mathf.PI * 2 * age / waveFrequency;
float sin = Mathf.Sin(theta);
tempPos.x = x0 + waveWidth * sin;
pos = tempPos;
// rotate a bit about y
Vector3 rot = new Vector3(0, sin*waveRotY, 0);
this.transform.rotation = Quaternion.Euler(rot);
// base.Move() still handles the movement down in y
base.Move();
// print(bndCheck.isOnScreen);
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 67239b4e04039f3d28db4ea469fb531c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+48
View File
@@ -0,0 +1,48 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy_2 : Enemy
{
[Header("Set in Inspector: Enemy_2")]
// Determines how much the Sine wave will affect movement
public float sinEccentricity = 0.6f;
public float lifeTime = 10;
[Header("Set Dynamically: Enemy_2")]
// Enemy_2 uses a Sin wave to modify a 2-point linear interpolation
public Vector3 p0;
public Vector3 p1;
public float birthTime;
void Start() {
// Pick any point on the left side of the screen
p0 = Vector3.zero;
p0.x = -bndCheck.camWidth - bndCheck.radius;
p0.y = Random.Range(-bndCheck.camHeight, bndCheck.camHeight);
// Pick any point on the right side of the screen
p1 = Vector3.zero;
p1.x = bndCheck.camWidth + bndCheck.radius;
p1.y = Random.Range(-bndCheck.camHeight, bndCheck.camHeight);
// Possibly swap sides
if (Random.value > 0.5f) {
// Setting the .x of each point to its negative will move it to
// the other side of the screen
p0.x *= -1;
p1.x *= -1;
}
// Set the birthTime to the current time
birthTime = Time.time;
}
public override void Move() {
// Bezier curves work based on a u value between 0 & 1
float u = (Time.time - birthTime) / lifeTime;
// If u>1, then it has been longer than lifeTime since birthTime
if (u > 1) {
// This Enemy_2 has finished its life
Destroy(this.gameObject);
return;
}
// Adjust u by adding a U Curve based on a Sine wave
u = u + sinEccentricity*(Mathf.Sin(u*Mathf.PI*2));
pos = (1-u)*p0 + u*p1;
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8424fdbcb6a86d74f860fe068d094d3b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+50
View File
@@ -0,0 +1,50 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy_3 : Enemy
{
// Enemy_3 will move following a Bezier curve, which is a linear
// interpolation between more than two points.
[Header("Set in Inspector: Enemy_3")]
public float lifeTime = 5;
[Header("Set Dynamically: Enemy_3")]
public Vector3[] points;
public float birthTime;
// Again, Start works well because its not used by the Enemy superclass
void Start() {
points = new Vector3[3]; // Initialize points
// The start position has already been set by Main.SpawnEnemy()
points[0] = pos;
// Set xMin and xMax that same way that Main.SpawnEnemy() does
float xMin = -bndCheck.camWidth + bndCheck.radius;
float xMax = bndCheck.camWidth - bndCheck.radius;
Vector3 v = Vector3.zero;
// Pick a random middle position in the bottom half of the screen;
v.x = Random.Range(xMin, xMax);
v.y = -bndCheck.camHeight * Random.Range(2.75f, 2);
points[1] = v;
// Pick a random final position above the top of the screen
v = Vector3.zero;
v.y = pos.y;
v.x = Random.Range(xMin, xMax);
points[2] = v;
// Set the birthTime to the current time
birthTime = Time.time;
}
public override void Move() {
// Bezier curves work based on a u value between 0 & 1
float u = (Time.time - birthTime) / lifeTime;
if (u > 1) {
// This Enemy_3 has finished its life
Destroy(this.gameObject);
return;
}
// Interpolate the three Bezier cruve points
Vector3 p01, p12;
u = u - 0.2f*Mathf.Sin(u * Mathf.PI * 2);
p01 = (1-u)*points[0] + u*points[1];
p12 = (1-u)*points[1] + u*points[2];
pos = (1-u)*p01 + u*p12;
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 949d50caf3a9277bd80ee88fcc10bf9a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+18
View File
@@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy_4 : Enemy
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 890512b9c88f600408f25130d273807b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+48 -1
View File
@@ -11,9 +11,14 @@ public class Hero : MonoBehaviour
public float speed = 30;
public float rollMult = -45;
public float pitchMult = 30;
public float gameRestartDelay = 2f;
public GameObject projectilePrefab;
public float projectileSpeed = 40;
[Header("Set Dynamically")]
public float shieldLevel = 1;
public float _shieldLevel = 1;
// This variables holds a reference to the last triggering GameObject
private GameObject lastTriggerGo = null;
void Awake() {
if (S == null) {
@@ -44,5 +49,47 @@ public class Hero : MonoBehaviour
// Rotate the ship to make it feel more dynamic
transform.rotation = Quaternion.Euler(yAxis*pitchMult,xAxis*rollMult,0);
// Allow the ship to fire
if (Input.GetKeyDown(KeyCode.Space)) {
TempFire();
}
}
void TempFire() {
GameObject projGO = Instantiate<GameObject>(projectilePrefab);
projGO.transform.position = transform.position;
Rigidbody rigidB = projGO.GetComponent<Rigidbody>();
rigidB.velocity = Vector3.up * projectileSpeed;
}
void OnTriggerEnter(Collider other) {
Transform rootT = other.gameObject.transform.root;
GameObject go = rootT.gameObject;
//print("Triggered: " + go.name);
// Make sure it's not the same triggering go as last time
if (go == lastTriggerGo) {
return;
}
lastTriggerGo = go;
if (go.tag == "Enemy") {
shieldLevel--;
Destroy(go);
} else {
print("Triggered by non-Enemy: " + go.name);
}
}
public float shieldLevel {
get {
return(_shieldLevel);
}
set {
_shieldLevel = Mathf.Min(value, 4);
// If the shield is going to be set to less than zero
if (value < 0) {
Destroy(this.gameObject);
// Tell Main.S to restart the game after a delay
Main.S.DelayedRestart(gameRestartDelay);
}
}
}
}
+51
View File
@@ -0,0 +1,51 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Main : MonoBehaviour
{
static public Main S;
[Header("Set in Inspector")]
public GameObject[] prefabEnemies;
public float enemySpawnPerSecond = 0.5f;
public float enemyDefaultPadding = 1.5f;
private BoundsCheck bndCheck;
void Awake() {
S = this;
// Set bndCheck to reference the BoundsCheck component of this GameObject
bndCheck = GetComponent<BoundsCheck>();
// Invoke SpawnEnemy() once (in 2 seconds, based on default values)
Invoke("SpawnEnemy", 1f/enemySpawnPerSecond);
}
public void SpawnEnemy() {
// Pick a random Enemy prefab to instantiate
int ndx = Random.Range(0, prefabEnemies.Length);
GameObject go = Instantiate<GameObject>(prefabEnemies[ndx]);
// Position the Enemy above the screen with a random x position
float enemyPadding = enemyDefaultPadding;
if (go.GetComponent<BoundsCheck>() != null) {
enemyPadding = Mathf.Abs(go.GetComponent<BoundsCheck>().radius);
}
// Set the initial position for the spawned Enemy
Vector3 pos = Vector3.zero;
float xMin = -bndCheck.camWidth + enemyPadding;
float xMax = bndCheck.camWidth - enemyPadding;
pos.x = Random.Range(xMin, xMax);
pos.y = bndCheck.camHeight + enemyPadding;
go.transform.position = pos;
// Invoke SpawnEnemy() again
Invoke("SpawnEnemy", 1f/enemySpawnPerSecond);
}
public void DelayedRestart(float delay) {
// Invoke the Restart() method in delay seconds
Invoke("Restart", delay);
}
public void Restart() {
// Reload _Scene_0 to restart the game
SceneManager.LoadScene("_Scene_0");
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e92a40d35c2c59b9c955492aa4ff067a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+26
View File
@@ -0,0 +1,26 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
private BoundsCheck bndCheck;
void Awake() {
bndCheck = GetComponent<BoundsCheck>();
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (bndCheck.offUp) {
Destroy(gameObject);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 74ad9c373a5d2b5e69bdb49a1f50e209
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: