Initial commit

This commit is contained in:
2021-03-18 11:56:10 -04:00
commit 44f201edd8
1582 changed files with 472891 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
// Sreed33
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BreakableBlock : MonoBehaviour
{
[Tooltip("Seconds to wait before destroying the block")]
[SerializeField] private float destroyTime;
/**********************************************************************************************/
// Unity / game loop functions
void OnTriggerEnter(Collider other)
{
if (other.tag != "Player") return;
// When the player enters the zone, destroy the block
StartCoroutine(DestroyBlock());
}
/**********************************************************************************************/
// Implementation
IEnumerator DestroyBlock()
{
float intervalCount = 5.0f;
float interval = destroyTime / intervalCount;
// Toggle the block mesh off->on 5 times, based on the set destroyTime
for (int i = 0; i < intervalCount; i++)
{
GetComponent<MeshRenderer>().enabled = false;
// Wait for half this iteration's normal interval
yield return new WaitForSeconds(interval / 2.0f);
GetComponent<MeshRenderer>().enabled = true;
yield return new WaitForSeconds(interval / 2.0f);
}
Destroy(this.gameObject);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 22999302d47e4224ab4999b7d8412074
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,108 @@
// SReed33
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class HealthManager : MonoBehaviour
{
[Header("Health Settings")]
[Tooltip("The amount to take from the player's score when being hit by a meteor")]
[SerializeField] private int scorePenalty = 500;
[Tooltip("The length of time for the player to be invincible after being hit")]
[SerializeField] private float invTime = 2.0f;
[Tooltip("The icon to show when the player is invincible")]
[SerializeField] private GameObject sheildIcon;
[Tooltip("The sphere that acts as a forcefield around the player when invincible")]
[SerializeField] private GameObject forceField;
[Tooltip("The HeartPanel to access player hearts")]
[SerializeField] private GameObject heartPanel;
[Tooltip("The YouDied UI panel to enable when the player dies")]
[SerializeField] private GameObject youDied;
[Tooltip("The FadeOut UI panel to enable when the player dies")]
[SerializeField] private GameObject fadeOut;
[Header("Health State")]
[Tooltip("Player hearts, automatically adjusts to UI elements")]
[SerializeField] private GameObject[] playerHearts;
[Tooltip("Player hits, initialized at game start based on heart count with playerHearts.Length")]
[SerializeField] private int playerHits;
[Tooltip("Currrent invincible state of the player")]
[SerializeField] private bool playerInvincible = false;
/**********************************************************************************************/
// Unity / game loop functions
// Start is called before the first frame update
void Start()
{
playerHits = heartPanel.transform.childCount;
}
/**********************************************************************************************/
// Implementation
// Called by Meteor.cs when a meteor hits the player
public void HurtPlayer()
{
// Do nothing if we are invincible; Don't try to reach before child index 0, it doesnt exist
if (playerInvincible) return;
if (playerHits < 0) return;
// Reduce the score of the player for being hit
GlobalScore.currentScore -= scorePenalty;
// Get the last child of the heart's UI panel and deactivate it
// Hides a heart from view on each hit
heartPanel.transform.GetChild(--playerHits).gameObject.SetActive(false);
// If we just removed the last heart, we died :(
if (playerHits == 0) StartCoroutine(KillPlayer());
else StartCoroutine(Invincible()); // Otherwise, make player invincible for invTime
}
// Makes the player invincible for the time set in the editor
IEnumerator Invincible()
{
// Set the invincibility UI element to active
forceField.SetActive(true);
sheildIcon.SetActive(true);
playerInvincible = true;
yield return new WaitForSeconds(invTime);
// Deactivate invincibility after waiting is done
forceField.SetActive(false);
sheildIcon.SetActive(false);
playerInvincible = false;
}
// Ends the game when the player loses all their health
IEnumerator KillPlayer()
{
// Disable player controls and level BGM
UnityChan.UnityChanControlScriptWithRgidBody.controlsActive = false;
GameObject.Find("LevelAudio").GetComponent<AudioSource>().Pause();
// Activate youDied, fadeOut overlays and load next scene
youDied.SetActive(true);
yield return new WaitForSeconds(2);
fadeOut.SetActive(true);
yield return new WaitForSeconds(1);
SceneManager.LoadScene(Level.thisLevel);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0386c431511a3144d882c4feed153306
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Level : MonoBehaviour
{
[Tooltip("The fadeIn gameobject to activate when the level starts")]
[SerializeField] public GameObject fadeIn;
[Tooltip("The name of the next level to load")]
[SerializeField] private string _nextLevel;
[Tooltip("The name of this level")]
[SerializeField] private string _thisLevel;
// Static values used to control game sequence
public static string nextLevel;
public static string thisLevel;
void Start()
{
nextLevel = _nextLevel;
thisLevel = _thisLevel;
GlobalScore.currentScore = 0;
// Reset gravity to default on level start
Physics.gravity = Vector3.down * 9.81f;
StartCoroutine(FadeIn());
}
IEnumerator FadeIn()
{
fadeIn.SetActive(true);
yield return new WaitForSeconds(1);
fadeIn.SetActive(false);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c1b904d19f59f64680cfcd92f2ab007
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LoadNextLevel : MonoBehaviour
{
[Header("Load Screen Settings")]
[Tooltip("Object(s) to activate when the scene starts")]
[SerializeField] private GameObject[] someObjects;
[Tooltip("The amount of time to wait before loading the next level")]
[SerializeField] private float waitTime;
[Tooltip("The name of the next level to load")]
[SerializeField] private string levelToLoad;
/**********************************************************************************************/
// Unity / game loop functions
void Start()
{
StartCoroutine(Transition());
}
/**********************************************************************************************/
// Implementation
IEnumerator Transition()
{
yield return new WaitForSeconds(0.5f);
// Activate the objeccts set in the inspector, then waitTime
foreach (GameObject o in someObjects) o.SetActive(true);
yield return new WaitForSeconds(waitTime);
// Load the next levelToLoad
SceneManager.LoadScene(levelToLoad);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 14767f3ddd779954bbd15c0915de72b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
// Sreed33
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Meteor : MonoBehaviour
{
[Header("Meteor Settings")]
[Tooltip("The root gameobject to enable for playing explosion effects")]
[SerializeField] private GameObject explosionEffect;
[Tooltip("The radius of the explosion force created on impact")]
[SerializeField] private float explosionRadius;
[Tooltip("The force of the explosion")]
[SerializeField] private float explosionForce;
[Tooltip("The upwards lift from the explosion")]
[SerializeField] private float explosionLift;
[Tooltip("The radius used to damage the player")]
[SerializeField] private float damageRadius;
[Tooltip("The radius used to destroy blocks")]
[SerializeField] private float destroyRadius;
[Tooltip("The maximum number of blocks to destroy")]
[SerializeField] private int destroyBlocksCount;
[Tooltip("Set true if the meteor should destroy blocks on collision")]
// Large meteors are set in the editor to destroy blocks
[SerializeField] private bool destroyBlocks = false;
[Header("Meteor State")]
[Tooltip("Once this boolean is false, the meteor will not trigger events again")]
[SerializeField] private bool newMeteor = true;
/**********************************************************************************************/
// Unity / game loop functions
void OnTriggerEnter(Collider other)
{
if (other.GetComponent<GemPickup>()) return;
DamagePlayer();
// Track if this is the first collision for this meteor
if (newMeteor) newMeteor = false;
else return;
// If it has already collided, then do nothing
if (destroyBlocks) DestroyBlocks();
// Disable meteor components, enable explosion effect
GetComponent<MeshRenderer>().enabled = false;
GetComponent<SphereCollider>().enabled = false;
foreach (Light l in GetComponentsInChildren<Light>()) l.enabled = false;
// I attached box collider to explosion effects so they would collide with the ground
// Use it to enable the root gameobject and play all the nested effects
explosionEffect.SetActive(true);
// Check all colliders within a radius around the explosion
Collider[] colliders = Physics.OverlapSphere(transform.position, explosionRadius);
foreach (Collider c in colliders)
{
// If it is not a player, do nothing; Otherwise hurt the player
if (c.gameObject.tag != "Player") continue;
// Apply a force to the player from the explosion
Rigidbody rb = c.gameObject.GetComponent<Rigidbody>();
if (rb != null)
{
rb.AddExplosionForce(explosionForce, transform.position, explosionRadius, explosionLift, ForceMode.Impulse);
}
}
// Destroy the meteor
StartCoroutine(KillMeteor());
}
/**********************************************************************************************/
// Implementation
void DestroyBlocks()
{
int blocksDestroyed = 0;
Collider[] blocks = Physics.OverlapSphere(transform.position, destroyRadius);
foreach (Collider c in blocks)
{
if (c.gameObject.tag == "Blue")
{
Destroy(c.gameObject);
blocksDestroyed++;
if (blocksDestroyed >= destroyBlocksCount) return;
}
}
}
void DamagePlayer()
{
Collider[] blocks = Physics.OverlapSphere(transform.position, damageRadius);
foreach (Collider c in blocks)
{
if (c.gameObject.tag == "Player")
{
print("Ow: " + this.gameObject.name);
FindObjectOfType<HealthManager>().HurtPlayer();
}
}
}
IEnumerator KillMeteor()
{
// Wait two seconds before destroying this gameobject to let the explosion finish
yield return new WaitForSeconds(2.0f);
Destroy(this.gameObject);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f4e85fdad220c274ba5fdf8d685b0bed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,116 @@
// Sreed33
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeteorZone : MonoBehaviour
{
[Header("Meteor Zone Settings")]
[Tooltip("The tag assigned to the GameObject that spawn meteors")]
[SerializeField] private string objectTag;
[Tooltip("Time between meteor spawns")]
[SerializeField] private float spawnInterval;
[Header("Meteor Prefab Assets")]
[Tooltip("Small meteor prefab")]
[SerializeField] private GameObject meteorSmall;
[Tooltip("Medium meteor prefab")]
[SerializeField] private GameObject meteorMedium;
[Tooltip("Large meteor prefab")]
[SerializeField] private GameObject meteorLarge;
[Header("Zone State")]
[Tooltip("Automatically initialized with spawn positions in this zone on game start")]
[SerializeField] private List<GameObject> meteorSpawners;
[Tooltip("A local bool that controls this zone spawning meteors")]
[SerializeField] private bool zoneSpawnMeteors = false;
[Tooltip("A local bool used to throttle the spawn rate of meteors")]
[SerializeField] private bool spawnPending = false;
// A static bool used to control the spawning of meteors across the entire level
public static bool spawnMeteors = true;
/**********************************************************************************************/
// Unity / game loop functions
// Start is called before the first frame update
void Start()
{
spawnMeteors = true;
// Check each object that makes up this meteor zone
foreach (Transform child in this.transform.parent.GetComponentsInChildren<Transform>())
{
// If the object is tagged as a metor spawner, add it to the list
if (child.gameObject.tag == objectTag) meteorSpawners.Add(child.gameObject);
}
}
void FixedUpdate()
{
// Do nothing if either local zone or level meteor bool is false
if (!spawnMeteors || !zoneSpawnMeteors) return;
// StartCoroutine only after the previous meteor is spawned
if (!spawnPending) StartCoroutine(SpawnMeteor());
}
void OnTriggerEnter(Collider other)
{
// Do nothing if the object is not a player
if (other.gameObject.tag != "Player") return;
// Set local meteor spawn bool to true; Start spawning meteors in this zone
zoneSpawnMeteors = true;
}
void OnTriggerStay(Collider other)
{
if (other.gameObject.tag != "Player") return;
// If there is a player in the zone and we are not spawning meteors, set zoneSpawnMeteors
if (!zoneSpawnMeteors) zoneSpawnMeteors = true;
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag != "Player") return;
// When the player leaves the zone, stop spawning meteors
zoneSpawnMeteors = false;
}
/**********************************************************************************************/
// Implementation
IEnumerator SpawnMeteor()
{
spawnPending = true;
// Wait for the set number of seconds until we spawn a meteor
yield return new WaitForSeconds(spawnInterval);
// Using the count of objects in the meteorSpawner list, get a random index to spawn at
int spawnSlot = Random.Range(0, meteorSpawners.Count);
Transform spawnPos = meteorSpawners[spawnSlot].transform;
// Using 10 values (0-9), get a large meteor(20%), medium meteor(30%), or small meteor(50%)
// + large = 0, 1; Medium = 4, 3, 2; Small = 5, 6, 7, 8, 9
int meteorType = Random.Range(0, 9);
GameObject newMeteor;
if (meteorType < 2) newMeteor = meteorLarge;
else if (meteorType < 5 && meteorType >= 2) newMeteor = meteorMedium;
else newMeteor = meteorSmall;
// Spawn this meteor
GameObject.Instantiate(newMeteor, spawnPos.position, meteorSpawners[0].transform.rotation);
// Spawn another meteor in FixedUpdate()
spawnPending = false;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c48341a61cfe0174fa51ec41cd2e52d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
// Sreed33
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Portal : MonoBehaviour
{
[Tooltip("The linked portal to move the player to when entering here")]
[SerializeField] private GameObject friendPortal;
// Boolean to prevent teleporting back and forth infinitely
public static bool teleporting = false;
/**********************************************************************************************/
// Unity / game loop functions
void OnCollisionEnter(Collision other)
{
if (other.gameObject.tag != "Player") return;
// Only teleport if we are not teleporting
if (!teleporting) TeleportChan(other);
}
/**********************************************************************************************/
// Implementation
void TeleportChan(Collision player)
{
teleporting = true;
// Stop applying physics to the player until we finish teleporting
player.rigidbody.isKinematic = true;
// Move the player to the spawn position that is always the only child of Portal.cs
Transform spawnPos = friendPortal.GetComponentInChildren<Portal>().transform.GetChild(0);
player.transform.position = spawnPos.position;
player.transform.rotation = spawnPos.rotation;
// Always force the player down towards whatever surface they are waling on
// + Allows player to walk on walls and ceilings after TP using local->world axis
Physics.gravity = spawnPos.up * -9.81f;
// Resume physics
player.rigidbody.isKinematic = false;
teleporting = false;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a0c0fee4875eafc4b83732211315c48b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: