Project Type: Personal Project
Software Used: Unity, Visual Studio, Github
Language Used: C#
Primary Role(s): Gameplay, A.I, Design, Art, Audio, UI
Star Gazer is an endless 2D space shooter survival game developed for mobile devices. Players will shoot incoming obsticles to defend the planet their cannon has been placed on. Obsticles never stop spawning until the game is over. Players will obtain star dust to upgrade their cannons states and can also purchase different planets with the ingame currency.
[expand title=”Variables & Set-up”]
[/expand]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class SpaceCannon_Controller : MonoBehaviour
{
// Shooting
// distance in which we shoot
float range = 200;
// The max ammo the cannon can hold by default
[HideInInspector]
public int maxAmmo = 4;
[Tooltip("What layers is the cannon bullets allowed to hit?")]
public LayerMask whatToHit;
[Tooltip("The current ammo that we have loaded inside the cannon")]
public int currentAmmo;
bool isReloading = false;
public float reloadSpeed = 2f;
private float nextTimeToFire;
public float FireRate = 15f;
private Game_Manager GM;
private AudioSource AS;
private AudioClip shoot;
#region Laser Variables
[Header("Laser Variables")]
public LineRenderer lineRenderer;
// Position where we fire the projectile bullet from
public Transform firePoint;
public GameObject startVFX;
private List<ParticleSystem> LaserParticles = new List<ParticleSystem>();
#endregion
// Effects
public Image reloadImage;
private AudioClip reloadChargeUp, reloadClick;
// Start is called before the first frame update
void Start()
{
if(AS == null)
{
AS = gameObject.AddComponent<AudioSource>();
}
else
{
AS = gameObject.GetComponent<AudioSource>();
}
AS.loop = false;
GM = GameObject.Find("GameManager").GetComponent<Game_Manager>();
// find the first child to get the fire position Transform component
firePoint = gameObject.transform.GetChild(0).GetComponent<Transform>();
// make sure the cannon is loaded with the max amount of bullets
currentAmmo = maxAmmo;
lineRenderer = gameObject.transform.GetChild(1).GetComponentInChildren<LineRenderer>();
startVFX = gameObject.transform.GetChild(1).GetChild(1).gameObject;
reloadImage = GameObject.Find("ReloadImage").GetComponent<Image>();
shoot = Resources.Load<AudioClip>("Audio/Player/Shoot Cannon");
reloadChargeUp = Resources.Load<AudioClip>("Audio/Player/Cannon Reload Charge");
reloadClick = Resources.Load<AudioClip>("Audio/Player/Cannon Reload Click");
FillParticleLost();
DisableLaser();
}
[expand title=”Runtime Function”]
[/expand]
// Update is called once per frame
void Update()
{
if (GM.startGame != true)
return;
else
{
CannonRotation(5, -90);
if (isReloading)
{
for (int i = 0; i < LaserParticles.Count; i++)
LaserParticles[i].Stop();
return;
}
// shoot when we press left click
if (Input.GetButtonDown("Fire1") && currentAmmo > 0 && Time.time > nextTimeToFire)
{
// Calculate next time to shoot cannon
nextTimeToFire = Time.time + FireRate;
// Shoot the cannon
Shoot();
}
// Dont make distant distort sound on shoot
if(AS.time >= 2 && !isReloading)
{
AS.volume = 0;
}
// we are now reloading
if (currentAmmo <= 0)
StartCoroutine(ReloadCannon(reloadSpeed));
}
}
[expand title=”Functions to be called on runtime”]
[/expand]
void CannonRotation(float rotationSpeed, float offset)
{
// OBTAIN DIRECTION \\
// ----------------
// get the mouse position
Vector3 mousePosition = Input.mousePosition;
// get the mouse position on screen
mousePosition = Camera.main.ScreenToWorldPoint(mousePosition);
// get the direction in which we will be facing towards (where the mouse is) // target
Vector2 direction = new Vector2(mousePosition.x - transform.position.x, mousePosition.y - transform.position.y);
// SET ROTATION \\
// -------------
// Get the angle from the current direction to the desired target
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
// set the angle into a quaternion + sprite offset depending on initial sprite facing direction
Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, angle + offset));
rotation.eulerAngles = new Vector3(0, 0, angle + offset);
// Rotate current game object to face the target using a slerp function which adds some smoothing to the movement
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, rotationSpeed * Time.deltaTime);
}
Obsticle_Controller hazzardScript;
void Shoot()
{
AS.volume = 0.5f;
AS.clip = shoot;
// Draw the ray in scene
Debug.DrawRay(firePoint.transform.position, firePoint.transform.TransformDirection(Vector2.up) * range, Color.blue);
// Data to understand what passes through Hit
RaycastHit2D hit = Physics2D.Raycast(firePoint.position, firePoint.transform.TransformDirection(Vector2.up), range, whatToHit);
if(hit)
{
EnableLaser();
startVFX.transform.position = firePoint.position;
StartCoroutine(LaserAnimation(firePoint.position, hit.point));
// Debug message to show we hit something
Debug.Log("Hit Object" + "" + "Name" + "" + hit.collider.name);
currentAmmo--;
hazzardScript = hit.transform.GetComponent<Obsticle_Controller>();
AS.Play();
}
}
IEnumerator ReloadCannon(float reloadTime)
{
AS.volume = 1;
// Start the event
isReloading = true;
// get the current realtime of the reload value time
float currentTime = reloadTime;
// turn on the image that will show when we reload
reloadImage.enabled = true;
// set the value for the fill to be 0 so the effect is about to start
reloadImage.fillAmount = 0;
// show we are reloading in the console
Debug.Log("Reloading . . .");
// play sound
AS.clip = reloadChargeUp;
AS.Play();
// Loop check to see if the time we have is still greater than 0
while (currentTime > 0)
{
// Decrease value of current time
currentTime -= Time.deltaTime;
// fill the image and divide by the duration to make sure it does not increase to fast
reloadImage.fillAmount = currentTime / reloadTime;
// get next frame
yield return null;
}
// AFTER LOOP IS DONE
AS.volume = 0;
// reload the cannon by giving ammo back
currentAmmo = maxAmmo;
// turn off the effect image
reloadImage.enabled = false;
// End function
isReloading = false;
}
[expand title=”Line Renderer Animation control”]
[/expand]
#region Laser Functions
void EnableLaser()
{
lineRenderer.enabled = true;
for (int i = 0; i < LaserParticles.Count; i++)
LaserParticles[i].Play();
}
Vector3 newPos;
IEnumerator LaserAnimation(Vector2 startPosition, Vector2 endPosition)
{
float t = 0;
float time = 0.3f;
startPosition = firePoint.position;
lineRenderer.SetPosition(0, startPosition);
for (; t < time; t+= Time.deltaTime)
{
newPos = Vector2.Lerp(startPosition, endPosition, t / time);
lineRenderer.SetPosition(1, newPos);
yield return null;
}
if(lineRenderer.GetPosition(1) == newPos)
{
hazzardScript.Damage(1);
yield return new WaitForSeconds(1);
DisableLaser();
}
lineRenderer.SetPosition(1, endPosition);
}
void DisableLaser()
{
lineRenderer.enabled = false;
for (int i = 0; i < LaserParticles.Count; i++)
LaserParticles[i].Stop();
}
void FillParticleLost()
{
for(int i = 0; i < startVFX.transform.childCount; i++)
{
var ps = startVFX.transform.GetChild(i).GetComponent<ParticleSystem>();
if (ps != null)
LaserParticles.Add(ps);
}
}
#endregion
[expand title=”AI Spawner StartUp”]
[/expand]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Obsticle_Spawner : MonoBehaviour
{
private GameObject meteor;
private GameObject star;
private const int MAX_AMOUNT = 10;
public float rateOfSpawn;
private float nextTimeToSpawn;
public float distanceAway;
// minute and second calulator
[Tooltip("Time in mins until spawnrate goes down")]
public float Seconds; // default 30 seconds
private float timeRemainingValue;
private float clampValue = 1.2f;
bool clampFound = false;
//[HideInInspector]
public List<GameObject> allSpawner = new List<GameObject>();
Game_Manager GM;
// Start is called before the first frame update
void Start()
{
// obtain Variable
meteor = Resources.Load<GameObject>("Prefabs/Idea #2/Obsticles/Meteor");
star = Resources.Load<GameObject>("Prefabs/Idea #2/Obsticles/Star");
GM = GameObject.Find("GameManager").GetComponent<Game_Manager>();
nextTimeToSpawn = rateOfSpawn;
timeRemainingValue = Seconds;
}
[expand title=”Obsticle Spawner On Runtime”]
[/expand]
// Update is called once per frame
void Update()
{
if(GM.startGame == false)
{
return;
}
else
{
nextTimeToSpawn -= Time.deltaTime;
if (nextTimeToSpawn <= 0)
{
SpawnMeteors();
nextTimeToSpawn = rateOfSpawn;
}
// when to stop altering spawn rate
if (rateOfSpawn <= clampValue)
{
clampFound = true; // locks function from running
}
else
{
// alter time on runtime
TimeAlive();
}
}
}
void SpawnMeteors()
{
// if not run meteor code
if (Random.value > 0.9f) // 30% chance to spawn star
{
Vector3 centre = transform.position;
Vector3 position = RandomCircle(centre, distanceAway);
GameObject s = Instantiate(star, position, Quaternion.identity);
s.name = "Star";
allSpawner.Add(s);
}
else // 70% chance to spawn
{
// centre of radius position
Vector3 center = transform.position;
// Make the spawn position, decided by the centre point and the radius so we know how far away the circle is made.
Vector3 position = RandomCircle(center, distanceAway);
// Spawn meteor object <- Later alter this so we can spawn a star to give us more star dust - money
GameObject m = Instantiate(meteor, position, Quaternion.identity);
m.name = "Meteor";
allSpawner.Add(m);
}
}
[expand title=”Runtime Functions”]
[/expand]
Vector3 RandomCircle(Vector3 center, float radius)
{
// degree of where objects can spawn
float angle = Random.value * 360;
// empty vector to pass data into
Vector3 pos;
// Get the X and Y coodinates of the return value points
pos.x = center.x + radius * Mathf.Sin(angle * Mathf.Deg2Rad);
pos.y = center.y + radius * Mathf.Cos(angle * Mathf.Deg2Rad);
// Z axis need not be altered
pos.z = center.z;
// return this vector to the function
return pos;
}
void TimeAlive()
{
if (!clampFound)
{
if (Seconds > 0)
{
Seconds -= Time.deltaTime;
DisplayTime(Seconds);
}
else
{
Debug.Log("Time has run out");
Seconds = timeRemainingValue;
Mathf.Clamp(rateOfSpawn, clampValue, clampValue);
rateOfSpawn -= 0.2f;
}
}
else
{
Seconds = timeRemainingValue;
}
}
void DisplayTime(float timeToDsiplay)
{
timeToDsiplay += 1;
float minutes = Mathf.FloorToInt(timeToDsiplay / 60);
float seconds = Mathf.FloorToInt(timeToDsiplay % 60);
float milliSeconds = (timeToDsiplay % 1) * 1000;
}
[expand title=”Variables & Start-up”]
[/expand]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Obsticle_Controller : MonoBehaviour
{
private Rigidbody2D Physics;
private Collider2D Collision;
[Header("Health")]
public int currentHealth;
private int maxHealth = 1;
[Header("Movement")]
public GameObject target;
public bool doesRotate = false;
public float RotationSpeed;
public float movementSpeed;
Vector2 startPosition;
public int meteor_Money;
public int star_Money;
GameObject meteorExplosion;
GameObject starExplosion;
GameObject impactEffect;
private Game_Manager GM;
// event to change pulse effect
public static event System.Action ObsticleDestroyed = delegate { };
GameObject hitSoundPrefab;
// Start is called before the first frame update
void Start()
{
SetUp();
// Reset for multi use
ObsticleDestroyed = null;
currentHealth = maxHealth;
}
void SetUp()
{
startPosition = transform.position;
// add component
Physics = gameObject.AddComponent<Rigidbody2D>();
//Physics.isKinematic = true; // no real physics used
Physics.gravityScale = 0;
// add component
Collision = gameObject.AddComponent<PolygonCollider2D>();
target = GameObject.Find("Planet");
GM = GameObject.Find("GameManager").GetComponent<Game_Manager>();
starExplosion = Resources.Load<GameObject>("Prefabs/Idea #2/Particle Effects/Obsticles/Star_ExplosionEffect");
meteorExplosion = Resources.Load<GameObject>("Prefabs/Idea #2/Particle Effects/Obsticles/Meteor_ExplosionEffect");
impactEffect = Resources.Load<GameObject>("Prefabs/Idea #2/Particle Effects/Obsticles/Hit Impact");
hitSoundPrefab = Resources.Load<GameObject>("Audio/Spawnables/HitSound");
// Check to see if the money we have is right
meteor_Money = GM.MeteorPoints;
star_Money = GM.StarPoints;
if(doesRotate)
{
// clockwise or counter RNG
int randomValue = 0;
randomValue = Random.Range(0, 10);
if (randomValue < 5)
{
// clockwise
RotationSpeed = 90f;
}
else
{
// counter clockwise
RotationSpeed = -90f;
}
}
}
[expand title=”Runtime Movement”]
[/expand]
// Update is called once per frame
void Update()
{
if(GM.startGame != true)
{
return;
}
else
{
// Function to move and rotate object
Movement();
// monitor whhen we explode
if (currentHealth <= 0)
{
Explode(true);
}
}
}
void Movement()
{
if(doesRotate)
{
// Rotate Object
this.gameObject.transform.Rotate(Vector3.forward * RotationSpeed * Time.deltaTime);
}
// Move object towards its target
transform.position = Vector2.MoveTowards(transform.position, target.transform.position, movementSpeed * Time.deltaTime);
// Move towards the planet but always hits the dom first for its in the way
}
[expand title=”Obstacle Death Function & Collision”]
[/expand]
public void Damage(int dmg)
{
currentHealth -= dmg;
}
private void OnDisable()
{
ObsticleDestroyed -= GM.RunCo;
}
void Explode(bool playerShot)
{
// send money
if(playerShot && gameObject.layer == 11)
{
// public event happens now
ObsticleDestroyed();
// increase money
Game_Manager.starDust += meteor_Money;
GameObject ps_Meteor = Instantiate(meteorExplosion, transform.position, Quaternion.identity);
Destroy(ps_Meteor, 3f);
}
else if(playerShot && gameObject.layer == 8)
{
// public event happens
ObsticleDestroyed();
// increase money
Game_Manager.starDust += star_Money;
GameObject ps_Star = Instantiate(starExplosion, transform.position, Quaternion.identity);
Destroy(ps_Star, 3f);
}
Destroy(this.gameObject);
GameObject OS = GameObject.Find("Obsticle_Spawner");
OS.GetComponent<Obsticle_Spawner>().allSpawner.Remove(this.gameObject);
if(GameObject.Find("HitSound") == null)
{
GameObject hit = Instantiate(hitSoundPrefab, Vector3.zero, Quaternion.identity) as GameObject;
hit.name = "HitSound";
Destroy(hit, 1f);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
// Planet and Dome (The goal of obsticle)
if(collision.gameObject.layer == 12 || collision.gameObject.layer == 13)
{
GameObject HitEffect = Instantiate(impactEffect, transform.position, Quaternion.identity);
HitEffect.transform.LookAt(startPosition);
Explode(false);
}
if(collision.gameObject.layer == 12)
{
Game_Manager.DomeHealth -= 1;
}
else if(collision.gameObject.layer == 13)
{
// Game Over
Game_Manager.PlanetHealth -= 1;
}
}
[expand title=”Start Up & Variables”]
[/expand]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Game_Manager : MonoBehaviour
{
public GameObject mainMenu;
// Game Over Menu
public GameObject GameOver_Menu;
// the shop menu
public GameObject shop_Menu;
// Menu that appears when the player is done
public GameObject CelebrationMenu;
// The Players in game canvas UI
public GameObject PlayerCanvas;
// Player Controller script
public SpaceCannon_Controller playerController;
// Force Field Object hit detection in scene
public GameObject ForceFieldCollisionDetect;
// The Gameobject for the force field
public GameObject ForceField;
// Force field shader
private Material _ForceField_Shader;
private float crossSectionValue = -8;
// Planet GameObject in scene
private GameObject planet;
// time to fade and dissolve planet
float fade = 1f;
// when do we dissolve
bool dissolving = false;
public static int DomeHealth = 3;
public static int PlanetHealth = 1;
[Tooltip("Boolean that ends the game")]
public bool Game_Over = false;
[Tooltip("Bool to check if the current highscore has been beaten")]
public bool highScore_Beaten = false;
[Tooltip("The currency earned to spend in the shop")]
public static int starDust;
// value stored from the static value
public int money;
// the value to obtain time
private float startTime;
// characters to format so it looks like a timer
private string textTime;
private string savedTextTime;
// Display Value of Time after math
float guiTime;
// This is our time value, the value of the current Time.time
public float CurrentTime = 0;
// the value that we pause at. The CurrentTime we was on before we paused
public float realTime = 0;
// the subtract value which is CurrentTime - Realtime = value
public float value;
// Player Pref Value - Stores High Score
[SerializeField]
float HighScore = 0;
// Player Pref Value - Jump straight back to game when value = 1
int RetryGame = 0;
public bool InShopMenu = false;
public GameObject whatMenu;
// boolean that checks if we are in game or not
public bool startGame = false;
// The Shop Manager script
private ShopManager SM;
// Particle Effects
private GameObject Explosion_ParticleEffect;
private GameObject Confetti_ParticleEffect;
// In Game Timer (How long we have survived)
private Text UITimer;
// The Text that shows the player their new highscore
private Text HighScoreUI;
// The in game money text
private Text moneyDisplay;
// The Money Text in the store
private Text StoreMoneyDisplayText;
// points that feed into obsticle controller for we use these values when we upgrade new amount of money intake
public int MeteorPoints = 20;
public int StarPoints = 40;
// The Sprite in our assets that shows players that the sound is muted
Sprite SoundOff;
// The Sprite in our assets that shows players that the sound is on
Sprite SoundOn;
// boolean that monitors the current situation of mute or unmuted
private bool isMuted = false;
// Fade between UI and Game
#region Fade Effect Variables
public float SpeedScale = 1f;
public Color fadeColor = Color.black;
// Rather than Lerp or Slerp, We allow adaptability with a configuration curve
public AnimationCurve Curve = new AnimationCurve(new Keyframe(0, 1),
new Keyframe(0.5f, 0.5f, -1.5f, -1.5f), new Keyframe(1, 0));
public bool StartFadeOut = false;
public bool FadeEffectHere = false;
private float alpha = 0f;
private Texture2D texture;
private int direction = 0;
private float time = 0f;
public bool TransitioningOver = true;
public float sceneTime;
private float startScenetime;
private AudioSource inGameAS;
private GameObject ExplosionSoundPrefab;
private Text mainMenuHighScore;
#endregion
private void Awake()
{
savedTextTime = PlayerPrefs.GetString("MainMenuHighScore");
FadeEffectHere = true;
startGame = false;
TransitioningOver = false;
// Set up Fade values
OnStartFadeEffect();
startTime = Time.time;
startScenetime = Time.time;
// Find UI
// Find the Text for the timer in game
UITimer = GameObject.Find("InGameTimer").GetComponent<Text>();
UITimer.text = "";
// Obtain UI component for the Money feedback Text
moneyDisplay = GameObject.Find("MoneyValue").GetComponent<Text>();
StoreMoneyDisplayText = GameObject.Find("Shop").transform.GetChild(0).GetChild(3).GetChild(1).GetComponentInChildren<Text>();
//
HighScoreUI = GameObject.Find("HighScore").GetComponent<Text>();
HighScoreUI.text = "";
SM = GameObject.Find("Shop Manager").GetComponent<ShopManager>();
// set the high score up
HighScore = PlayerPrefs.GetFloat("Alivetime");
RetryGame = PlayerPrefs.GetInt("ToGameInstant");
#region UI
//Time.timeScale = 0;
GameOver_Menu = GameObject.Find("Quit_Canvas");
GameOver_Menu.SetActive(false);
mainMenu = GameObject.Find("MainMenu_Canvas");
mainMenuHighScore = mainMenu.transform.GetChild(1).GetChild(8).GetComponent<Text>();
foreach (Button b in mainMenu.GetComponentsInChildren<Button>())
b.interactable = false;
if(HighScore == 0)
{
mainMenuHighScore.gameObject.SetActive(false);
GameObject title = GameObject.Find("HighscoreTitleText");
title.SetActive(false);
}
else
{
mainMenuHighScore.gameObject.SetActive(true);
GameObject title = GameObject.Find("HighscoreTitleText");
title.SetActive(true);
}
CelebrationMenu = GameObject.Find("CelebrationCanvas");
CelebrationMenu.SetActive(false);
PlayerCanvas = GameObject.Find("PC_Canvas");
inGameAS = PlayerCanvas.GetComponent<AudioSource>();
Explosion_ParticleEffect = Resources.Load<GameObject>("Prefabs/Idea #2/Particle Effects/Environment/Explosion");
Confetti_ParticleEffect = Resources.Load<GameObject>("Prefabs/Idea #2/Particle Effects/Confetti");
ExplosionSoundPrefab = Resources.Load<GameObject>("Audio/Spawnables/ExplosionSound");
if(RetryGame == 1)
{
mainMenu.SetActive(false);
TransitioningOver = true;
startGame = true;
inGameAS.Play();
}
else
{
mainMenu.SetActive(true);
}
#endregion
}
// Start is called before the first frame update
void Start()
{
// Find scripts
playerController = GameObject.Find("Space Cannon").GetComponent<SpaceCannon_Controller>();
// Find Objects
ForceFieldCollisionDetect = GameObject.Find("ForceField_CollisionDetection");
ForceField = GameObject.Find("ForceField");
_ForceField_Shader = ForceField.GetComponent<MeshRenderer>().material;
// Find in game planet
planet = GameObject.Find("Planet");
// check to see if we are muting the audio or unmuting
isMuted = PlayerPrefs.GetInt("Muted") == 1;
// mutes session with boolean value
AudioListener.pause = isMuted;
// money save data returned
starDust = PlayerPrefs.GetInt("Money");
// Find sprites
SoundOff = Resources.Load<Sprite>("2D_Sprites/UI/NoSound");
SoundOn = Resources.Load<Sprite>("2D_Sprites/UI/Sound");
// Sprites changed to correct option (Muted - 1)
if (isMuted = PlayerPrefs.GetInt("Muted") == 1)
{
// Make both buttons muted
mainMenu.transform.GetChild(1).transform.GetChild(6).GetComponent<Image>().sprite = SoundOff;
GameOver_Menu.transform.GetChild(1).transform.GetChild(5).GetComponent<Image>().sprite = SoundOff;
PlayerCanvas.transform.GetChild(5).transform.GetChild(3).GetComponent<Image>().sprite = SoundOff;
}
else
{
// Make both buttons muted
mainMenu.transform.GetChild(1).transform.GetChild(6).GetComponent<Image>().sprite = SoundOn;
GameOver_Menu.transform.GetChild(1).transform.GetChild(5).GetComponent<Image>().sprite = SoundOn;
PlayerCanvas.transform.GetChild(5).transform.GetChild(3).GetComponent<Image>().sprite = SoundOn;
} // (UnMuted - 0)
shop_Menu = GameObject.Find("Shop");
shop_Menu.SetActive(false);
}
[expand title=”Runtime Function”]
[/expand]
// Update is called once per frame
void Update()
{
mainMenuHighScore.text = savedTextTime;
if (playerController == null)
{
playerController = GameObject.Find("Space Cannon").GetComponent<SpaceCannon_Controller>();
playerController.currentAmmo = playerController.maxAmmo;
}
else
{
if(GameOver_Menu.activeInHierarchy == true)
{
playerController.gameObject.SetActive(false);
}
}
// Update value // save this value later
money = starDust;
// check if the game is done?
GameOver();
InGameTimer();
// show money obtained
moneyDisplay.text = money.ToString();
// Show instore money
StoreMoneyDisplayText.text = money.ToString();
PlayerPrefs.SetInt("Money", money);
// get start of scene time
sceneTime = Time.realtimeSinceStartup - startScenetime;
#region Fade Effect Button Monitor
if (alpha == 0)
{
if(mainMenu.activeInHierarchy == true && GameOver_Menu.activeInHierarchy == false && InShopMenu == false)
{
foreach (Button b in mainMenu.GetComponentsInChildren<Button>())
b.interactable = true;
}
else if (InShopMenu == true)
{
foreach (Button b in mainMenu.GetComponentsInChildren<Button>())
b.interactable = false;
}
else if(GameOver_Menu.activeInHierarchy == true && mainMenu.activeInHierarchy == false && InShopMenu == false)
{
foreach (Button b in GameOver_Menu.GetComponentsInChildren<Button>())
b.interactable = true;
}
else if (GameOver_Menu.activeInHierarchy == true && mainMenu.activeInHierarchy == false && InShopMenu == true)
{
foreach (Button b in GameOver_Menu.GetComponentsInChildren<Button>())
b.interactable = false;
}
}
else
{
if (mainMenu.activeInHierarchy == true && GameOver_Menu.activeInHierarchy == false && InShopMenu == false)
{
foreach (Button b in mainMenu.GetComponentsInChildren<Button>())
b.interactable = false;
}
else if (InShopMenu == true)
{
foreach (Button b in mainMenu.GetComponentsInChildren<Button>())
b.interactable = false;
}
else if (GameOver_Menu.activeInHierarchy == true && mainMenu.activeInHierarchy == false && InShopMenu == false)
{
foreach (Button b in GameOver_Menu.GetComponentsInChildren<Button>())
b.interactable = false;
}
else if (GameOver_Menu.activeInHierarchy == true && mainMenu.activeInHierarchy == false && InShopMenu == true)
{
foreach (Button b in GameOver_Menu.GetComponentsInChildren<Button>())
b.interactable = false;
}
}
#endregion
if (sceneTime > 0.2)
{
UpdateFadeEffect();
}
// Obtain the current time
CurrentTime = Time.time;
// Obsticle has been destroyed by the player
Obsticle_Controller.ObsticleDestroyed += RunCo;
}
[expand title=”Gameover & Timer Functions”]
[/expand]
// First colour lerp of shader force field
float Lerp = 0;
// second colour shader lerp
float SecondLerp = 0;
// check when lerping so we can stop when required
bool LerpOneOver = false;
bool LerpTwoOver = false;
// remove celebration menu when true
public bool stopCelebrating = false;
private event System.Action endGameExplosion = delegate { };
void GameOver()
{
// when the game is over
if (Game_Over)
{
PlayerCanvas.transform.GetChild(4).GetComponent<Button>().interactable = false;
startGame = false;
// when the effect is about to happen
if (dissolving)
{
// Spawns explosion Sound effect
if (GameObject.Find("ExplosionSound") == null)
{
GameObject ExplosionSound = Instantiate(ExplosionSoundPrefab, Vector3.zero, Quaternion.identity) as GameObject;
ExplosionSound.name = "ExplosionSound";
}
// Obtain spawner in the scene
GameObject spawner = GameObject.Find("Obsticle_Spawner");
// loop through a list of hazzards and destroy them
foreach (GameObject go in spawner.GetComponent<Obsticle_Spawner>().allSpawner)
{
// Destroy all the hazards
// Later i can replace this with the function that holds all the cool effects
Destroy(go);
}
// clear the list of hazzards
spawner.GetComponent<Obsticle_Spawner>().allSpawner.Clear();
// turn off the script
spawner.GetComponent<Obsticle_Spawner>().enabled = false;
// make a material reference and apply the relevent material
Material MatFade = planet.GetComponent<SpriteRenderer>().material;
// turn off the player controller
playerController.enabled = false;
// declide the fade value
fade -= Time.deltaTime / 6;
// when value is less or equal than 0
if(fade <= 0f)
{
// make sure effect value stays at 0
fade = 0f;
// revert boolean o the fade does not run any longer
dissolving = false;
}
if(fade < 0.5f)
{
// if there is no explosion
if(GameObject.Find("Explosion") == null)
{
// Spawn explosion
GameObject explosion = Instantiate(Explosion_ParticleEffect, Vector3.zero, Quaternion.identity)as GameObject;
explosion.name = "Explosion"; // Name explosion
}
// Obtain Objects
GameObject Body = GameObject.Find("Cannon Body");
Body.transform.parent = null;
GameObject Barrel = GameObject.Find("Cannon Barrel");
Barrel.transform.parent = null;
GameObject Base = GameObject.Find("CannonBase");
// check to see if we already have a rigibody on each object (Should start without a Rigidbody2D)
if(Body.GetComponent<Rigidbody2D>() == null && Barrel.GetComponent<Rigidbody2D>() == null
&& Base.GetComponent<Rigidbody2D>() == null)
{
// Add Physics to each Object
Body.AddComponent<Rigidbody2D>();
Barrel.AddComponent<Rigidbody2D>();
Base.AddComponent<Rigidbody2D>();
// Make sure gravity is not on
Body.GetComponent<Rigidbody2D>().gravityScale = 0;
Barrel.GetComponent<Rigidbody2D>().gravityScale = 0;
Base.GetComponent<Rigidbody2D>().gravityScale = 0;
// apply force so it moves in space
Body.GetComponent<Rigidbody2D>().AddForce(new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1), 0) * Time.deltaTime
* 1000, ForceMode2D.Impulse);
Barrel.GetComponent<Rigidbody2D>().AddForce(new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1), 0) * Time.deltaTime
* 1000, ForceMode2D.Impulse);
Base.GetComponent<Rigidbody2D>().AddForce(new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1), 0) * Time.deltaTime
* 1000, ForceMode2D.Impulse);
}
Body.transform.Rotate(Vector3.forward);
Barrel.transform.Rotate(Vector3.forward);
}
// as the fade value declines our effect is visually shown by the shader
MatFade.SetFloat("_Fade", fade);
}
// when the dissolve effect is done
if(!dissolving)
{
inGameAS.Stop();
GameObject Body = GameObject.Find("Cannon Body");
GameObject Barrel = GameObject.Find("Cannon Barrel");
Body.transform.Rotate(Vector3.forward);
Barrel.transform.Rotate(Vector3.forward);
startGame = false;
// first run
if (HighScore == 0 && !InShopMenu)
{
// save value here
PlayerPrefs.SetFloat("Alivetime", guiTime);
PlayerPrefs.SetString("MainMenuHighScore", textTime);
GameOver_Menu.SetActive(true);
}
else if (guiTime < HighScore && !InShopMenu) // first run is over so we check for a comparison
{
ForceField.SetActive(false);
// Game Over only dont save value : we dont want to save a lower value then the current value
// Turn on UI
GameOver_Menu.SetActive(true);
CelebrationMenu.SetActive(false);
}
else if(guiTime > HighScore)
{
// The current time is greater than the stored one
// save value here
PlayerPrefs.SetFloat("Alivetime", guiTime);
PlayerPrefs.SetString("MainMenuHighScore", textTime);
// ##
Debug.Log("YAY, New Hight Score");
// turn on canvas to celebrate
CelebrationMenu.SetActive(true);
// so if we are still n the celebration menu
if(!stopCelebrating && GameOver_Menu.activeInHierarchy != true)
{
// stuff here
// Spawn confetti
if(GameObject.Find("Confetti") == null)
{
// spawn confetti
GameObject Confetti = Instantiate(Confetti_ParticleEffect);
// rename confetti
Confetti.name = "Confetti";
}
// whatever else here
}
else
{
ForceField.SetActive(false);
CelebrationMenu.SetActive(false);
if (InShopMenu)
GameOver_Menu.SetActive(false);
else
{
GameOver_Menu.SetActive(true);
}
stopCelebrating = true;
// Destroy confetti
Destroy(GameObject.Find("Confetti"));
return;
}
}
}
}
else
{
if(DomeHealth == 2)
{
// change the thickness here
_ForceField_Shader.SetFloat("_EdgeThickness", 0.4f);
if(!LerpOneOver)
{
Lerp += Time.deltaTime / 2;
if (Lerp >= 1)
{
Lerp = 1;
LerpOneOver = true;
}
_ForceField_Shader.SetFloat("_Lerp", Lerp);
}
}
else if(DomeHealth == 1)
{
// Make sure shader does not get confused during lerp - if hit twice at the same time
Lerp = 1;
// change the thickness here
_ForceField_Shader.SetFloat("_ColourLerpControl", 0);
_ForceField_Shader.SetFloat("_EdgeThickness", 0.7f);
if (!LerpTwoOver && LerpOneOver == true)
{
// Use keyword to enable the last phase
_ForceField_Shader.EnableKeyword("_LASTHIT_ON");
SecondLerp += Time.deltaTime / 2;
if (SecondLerp >= 1)
{
SecondLerp = 1;
LerpTwoOver = true;
}
_ForceField_Shader.SetFloat("_Lerp", SecondLerp);
}
}
#region Death Check
// when dead
if (DomeHealth <= 0)
{
ForceFieldCollisionDetect.SetActive(false); // turn off
//ForceField.SetActive(false);
_ForceField_Shader.SetInt("_BoolController", 1);
crossSectionValue += Time.deltaTime * 10;
_ForceField_Shader.SetFloat("_CrossSection", crossSectionValue);
}
// when dead
if (PlanetHealth <= 0) //<- check and see if the player has beasted themselves in high score
{
Game_Over = true; // game is over
dissolving = true;
}
#endregion
}
}
private void InGameTimer()
{
// if the game has started or is not over
if(!dissolving && startGame && mainMenu.activeInHierarchy == false)
{
// We input the current time into thhe time we display
// We also subtract the current time of the else condition so time does not fail to be correct
guiTime = CurrentTime - startTime - value;
// Show highscore text in here - Celebration menu does not show until game is over
HighScoreUI.text = textTime;
value = 0;
realTime = 0;
}
else
{
if(guiTime == 0)
{
// Keep this value until we start the game or finish the game
// If not time is unaccurate
startTime = Time.time;
}
else
{
if(realTime == 0)
{
realTime = CurrentTime;
}
value = Mathf.Abs(CurrentTime - realTime);
}
}
// Time ratios
int minuets = (int)guiTime / 60;
int seconds = (int)guiTime % 60;
int fraction = (int)(guiTime * 100) % 100;
// Format string so it knows what to display with the values applied
// Shows miliseconds, seconds and minuets - makes UI look weird
//textTime = string.Format("{0:00}: {1:00}: {2:000}", minuets, seconds, fraction);
// Timer which shows minuets and seconds
textTime = string.Format("{0:00}: {1:00}", minuets, seconds);
// display Format string onto in game UI
UITimer.text = textTime;
}
[expand title=”GUI Fade Effect”]
[/expand]
#region Fade Effect
void OnStartFadeEffect()
{
if (StartFadeOut) alpha = 1f; else alpha = 0f;
texture = new Texture2D(1, 1);
texture.SetPixel(0, 0, new Color(fadeColor.r, fadeColor.g, fadeColor.b, alpha));
texture.Apply();
}
void UpdateFadeEffect()
{
if(direction == 0 && FadeEffectHere == true)
{
if (alpha >= 1f) // Fully faded out
{
alpha = 1f;
time = 0f;
direction = 1;
FadeEffectHere = false;
// if the main menu is active and the transition is done
if (mainMenu.activeInHierarchy == true && !InShopMenu)
{
// when the real time in the new or current scene is less than 5 we rturn
if (sceneTime <= 5) // (5 is just a value that can be reached fast without conflictions)
{
// return before condition is met
return;
}
else // we are over 5 and can play
{
// the transition is over
TransitioningOver = true;
// we are in the game
startGame = true;
inGameAS.Play();
}
// check that its done
if (TransitioningOver)
{
// turn off UI
mainMenu.SetActive(false);
}
}
if(InShopMenu)
{
if (sceneTime <= 5)
return;
else
TransitioningOver = true;
if(TransitioningOver)
{
whatMenu.SetActive(false);
shop_Menu.SetActive(true);
}
}
}
else // Fully faded in
{
alpha = 0f;
time = 1f;
direction = -1;
}
}
}
public void OnGUI()
{
if (alpha > 0f) GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), texture);
if(direction != 0)
{
time += direction * Time.deltaTime * SpeedScale;
alpha = Curve.Evaluate(time);
texture.SetPixel(0, 0, new Color(fadeColor.r, fadeColor.g, fadeColor.b, alpha));
texture.Apply();
if (alpha <= 0 || alpha >= 1f) direction = 0;
}
}
#endregion
[expand title=”Button Click Functions”]
[/expand]
#region OnClick Functions
public void StartGame()
{
FadeEffectHere = true;
// turn off activity of buttons
Button[] B = mainMenu.transform.GetChild(1).GetComponentsInChildren<Button>();
for (int i = 0; i <= B.Length - 1; i++)
B[i].interactable = false;
}
public void Retry()
{
RetryGame = 1;
PlayerPrefs.SetInt("ToGameInstant", RetryGame);
// reset game here
ForceFieldCollisionDetect.SetActive(true);
ForceField.SetActive(true);
DomeHealth = 3;
PlanetHealth = 1;
Application.LoadLevel(0);
}
public void QuitGame()
{
RetryGame = 0;
PlayerPrefs.SetInt("ToGameInstant", RetryGame);
Application.Quit();
}
public void MainMenu()
{
FadeEffectHere = true;
TransitioningOver = false;
RetryGame = 0;
PlayerPrefs.SetInt("ToGameInstant", RetryGame);
ForceFieldCollisionDetect.SetActive(true);
ForceField.SetActive(true);
DomeHealth = 3;
PlanetHealth = 1;
Application.LoadLevel(0);
}
public void GamePaused(bool Paused)
{
startGame = Paused;
}
#region Shop Menu Balancer
public void ShopBoolean(bool inShop)
{
InShopMenu = inShop;
TransitioningOver = false;
}
public void ShopFade(bool DoWeFade)
{
FadeEffectHere = DoWeFade;
}
// Reset shop in here too
public void ToShop()
{
// controls wave animation of the robot
SM.waveController = 0;
// then the data will do itself
PlayerCanvas.GetComponent<Canvas>().enabled = false;
if (GameOver_Menu.activeInHierarchy == true && mainMenu.activeInHierarchy != true)
{
whatMenu = GameOver_Menu;
Button[] Bttn = GameOver_Menu.transform.GetChild(1).GetComponentsInChildren<Button>();
for (int i = 0; i <= Bttn.Length - 1; i++)
Bttn[i].interactable = false;
if (!InShopMenu)
{
for (int i = 0; i <= Bttn.Length - 1; i++)
Bttn[i].interactable = true;
whatMenu.SetActive(true);
PlayerCanvas.GetComponent<Canvas>().enabled = true;
shop_Menu.SetActive(false);
}
}
else if(mainMenu.activeInHierarchy == true && GameOver_Menu.activeInHierarchy != true)
{
whatMenu = mainMenu;
Button[] Bttn = mainMenu.transform.GetChild(1).GetComponentsInChildren<Button>();
for (int i = 0; i <= Bttn.Length - 1; i++)
Bttn[i].interactable = false;
if (!InShopMenu)
{
whatMenu.SetActive(true);
PlayerCanvas.GetComponent<Canvas>().enabled = true;
shop_Menu.SetActive(false);
}
}
else
{
Button[] BT = whatMenu.transform.GetChild(1).GetComponentsInChildren<Button>();
foreach (Button bt in BT)
bt.interactable = true;
shop_Menu.SetActive(false);
PlayerCanvas.GetComponent<Canvas>().enabled = true;
whatMenu.SetActive(true);
}
}
#endregion
public void MuteGame()
{
// Find the sprites in the asset folders
Sprite SoundOff = Resources.Load<Sprite>("2D_Sprites/UI/NoSound");
Sprite SoundOn = Resources.Load<Sprite>("2D_Sprites/UI/Sound");
// The Sound Button indicator
Image Icon;
// boolean alteration for each menu (Start menu, quit menu and pause menu)
if (mainMenu.activeInHierarchy == true)
{
// Icon button on this menu found
Icon = mainMenu.transform.GetChild(1).transform.GetChild(6).GetComponent<Image>();
// When the icon sprite is of sound off
if(Icon.sprite == SoundOff)
{
// We tick this boolean so we can unmute the game
isMuted = false;
}
else
{
// If not the right icon sprite then we tick true which Mutes the game
isMuted = true;
}
}
else if(GameOver_Menu.activeInHierarchy == true)
{
// Find the correlated menus button image component so we correlate muted or unmuted
Icon = GameOver_Menu.transform.GetChild(1).transform.GetChild(5).GetComponent<Image>();
// check to change boolean
if (Icon.sprite == SoundOff)
{
isMuted = false;
}
else
{
isMuted = true;
}
}
else if(PlayerCanvas.activeInHierarchy == true)
{
// Pause Menu Button image Component
Icon = PlayerCanvas.transform.GetChild(5).transform.GetChild(3).GetComponent<Image>();
// Icon sprite check
if (Icon.sprite == SoundOff)
{
isMuted = false;
}
else
{
isMuted = true;
}
}
// When the boolean is true
if (isMuted)
{
// Change Icon for each button to muted sprite
mainMenu.transform.GetChild(1).transform.GetChild(6).GetComponent<Image>().sprite = SoundOff;
GameOver_Menu.transform.GetChild(1).transform.GetChild(5).GetComponent<Image>().sprite = SoundOff;
PlayerCanvas.transform.GetChild(5).transform.GetChild(3).GetComponent<Image>().sprite = SoundOff;
AudioListener.volume = 0;
// Pause all the audio sources
AudioListener.pause = isMuted;
}
else
{
AudioListener.volume = 1;
// unmute the game
AudioListener.pause = isMuted;
// change the sprite
mainMenu.transform.GetChild(1).transform.GetChild(6).GetComponent<Image>().sprite = SoundOn;
GameOver_Menu.transform.GetChild(1).transform.GetChild(5).GetComponent<Image>().sprite = SoundOn;
PlayerCanvas.transform.GetChild(5).transform.GetChild(3).GetComponent<Image>().sprite = SoundOn;
}
// save settings data - On the next play session we know if the game is muted or unmuted
PlayerPrefs.SetInt("Muted", isMuted ? 1 : 0);
}
public void ToQuitMenu(bool Quit)
{
stopCelebrating = Quit;
}
[expand title=”Pulse Text Function”]
[/expand]
IEnumerator TextPulse(bool increase)
{
if(increase)
{
for (float i = 1f; i < 1.2f; i += 0.005f)
{
moneyDisplay.rectTransform.localScale = new Vector3(i, i, i);
yield return new WaitForEndOfFrame();
}
moneyDisplay.rectTransform.localScale = new Vector3(1.2f, 1.2f, 1.2f);
for (float i = 1.2f; i >= 1f; i -= 0.05f)
{
moneyDisplay.rectTransform.localScale = new Vector3(i, i, i);
yield return new WaitForEndOfFrame();
}
moneyDisplay.rectTransform.localScale = new Vector3(1f, 1f, 1f);
}
else
{
for (float i = 1f; i > 0.8f; i -= 0.005f)
{
StoreMoneyDisplayText.rectTransform.localScale = new Vector3(i, i, i);
yield return new WaitForEndOfFrame();
}
StoreMoneyDisplayText.rectTransform.localScale = new Vector3(0.8f, 0.8f, 0.8f);
for (float i = 0.8f; i <= 1f; i += 0.05f)
{
StoreMoneyDisplayText.rectTransform.localScale = new Vector3(i, i, i);
yield return new WaitForEndOfFrame();
}
StoreMoneyDisplayText.rectTransform.localScale = new Vector3(1f, 1f, 1f);
}
}
public void RunCo()
{
// change pulse effect logic depending on current position of UI
if(shop_Menu.activeInHierarchy != true)
{
// increase scale
// Money Made
StartCoroutine(TextPulse(true));
}
else
{
// smaller scale
// Purchase Made
StartCoroutine(TextPulse(false));
}
}
[expand title=”Pulse Text Function”]
[/expand]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ShopManager : MonoBehaviour
{
[Range(0, 0.1f)]
// The speed we lerp by
[Tooltip("The Speed In Which we lerp from the main shop room and the window room")]
public float speed = 1f;
// are we currently lerping?
bool lerp = false;
// check if player wants to go to window menu or main store
bool buttonPressed = false;
// The target of the Lerp positions
Vector3 target;
// Next button to see the next planet
private Button nextButton;
// Button to check previous planet in the array
private Button PreviousButtons;
// The main Planet image we are changing through an array
[Tooltip("The UI image that we are manipulating to change the current planet on screen")]
public Image PlanetImage;
// Array of all the planets the player can buy
[Tooltip("The Array of sprites that will be for our planet purchasing")]
public Sprite[] Planets;
// The scroller for the planet array
[SerializeField]
public int planetScroller;
// Game Manager variable
Game_Manager GM;
// Are we going to let planets fade out or in
bool FadeIn = false;
bool FadeOut = false;
// Arrow Animations
private bool MainShopMenu = true;
// Animations for the UI buttons
Animator ShopRoomSmallArrow, WindowRoomSmallArrow;
// Animators for the robot Vendor
Animator rightArmAnimator, leftArmAnimator, RobotEyes;
AudioSource RobotAS;
AudioClip greet, celebrate;
[Range(0, 8)]
// values that we choose an animation from
public int eyeDirection; // 0 is idle, 8 and onward is an animation
// Time that changes the eye direction
private float timeUntilNextAnim;
private bool PurchasedMade = false;
#region Information Panel Variables
[Header("Information Menu")]
[TextArea(1, 4)]
[Tooltip("A Brief Description of each upgrade")]
public string[] Descriptions;
[Tooltip("The Upgrade Strings that change the Updrage In Question Text Component")]
public string[] UpgradeOrder;
[Tooltip("The Integar scroller that scrolls through the arrays")]
private int scroller = 0;
[Tooltip("The Upgrade Type Text Component that shows the player what upgrade they are readding about")]
private Text UpradeInQuestion;
[Tooltip("The Text Component that tells that player about the current shown Upgrade in the information panel")]
private Text DescriptionText;
[Tooltip("The Logos of the Upgrades so there can be image feedback")]
public Sprite[] Logos;
private Image TypeImage;
// The Information panel parent
private GameObject parentPanelInfo;
#endregion
#region Buy Planet Controller Variables
[Header("Planet Buying Variables")]
// The Planets we equiped to the in game planet
[Tooltip("The planet sprites that are going to be applied to the in game Planet")]
public Sprite[] EquipPlanets;
// The cannons we spawn in when players buy a new planet
[Tooltip("The different Prefab cannons that we spawn in when buying a new cannon")]
public GameObject[] CannonPrefabs;
// the current Cannon prefab in the game
private GameObject CurrentCannon;
// the array of booleans to save so we know what planets the player owns
public bool[] OwnedPlanets;
// The different prices of the planets
[Tooltip("The prices we give each planet to buy")]
public PlanetPrices[] PlanetPrices_;
// The Text component that shows the price of the planets
public Text PlanetPriceText;
// the saved value of what planet we have active
private int planetActive = 0;
// Button that we use to buy planets
Button BuyButton;
// The sprite renderer of the planet in the game on start
private SpriteRenderer RunTimePlanet;
#endregion
#region Fade Controllers Variables
[Tooltip("Boolean which allows the UI information Menu to Fade Out so it is not seen" +
"Fade In Boolean Must be false for this to happen too")]
bool FadeOutPanel = false;
[Tooltip("Boolean in which allows the information panel to fade in")]
bool FadeInPanel = false;
[Tooltip("Color Variable that changes the Alpha channel of the Text components on the Information Panel" +
"When it fades out the Alppa subtracts, the alpha increase when the Panel is fadding back in ")]
Color tempText;
[Tooltip("Color that will change the alpha channel of the Logo UI image changer")]
Color tempImage;
[Tooltip("A Boolean to monitor which button of direction was pressed. This helps with adding and subvtracting the array scroller Integar")]
bool ClickedLeftInfoButton;
[Tooltip("A Boolean to detect if the player clicked the Right Button of the information panel to add 1 to the integar scroller")]
bool ClickedRightInfoButton;
#endregion
[Header("Cannon Upgrade Variables")]
// Upgrade Manager Class
public List<PriceChange> PriceManager = new List<PriceChange>();
// Space Cannon script (Player Controller)
private SpaceCannon_Controller PlayerController;
// an event to allow for pulse text effects
public static event System.Action Purchase = delegate { };
private AudioSource buyButton_AS;
private AudioClip buyPlanet, defaultClick;
private void Awake()
{
Debug.Log("First Line Of Awake Function Runs");
// find current cannon in the scene just in case it needs to be changed later
CurrentCannon = GameObject.Find("Space Cannon");
// Find the planet Object in the game
RunTimePlanet = GameObject.Find("Planet").GetComponent<SpriteRenderer>();
// Saved int so we know what planet we apply to the Planet GameObject
planetActive = PlayerPrefs.GetInt("CurrentPlanet", planetActive);
// Apply correct sprite player chose before they quite
RunTimePlanet.sprite = EquipPlanets[planetActive];
// External file to save Array data as left for the Purchased Planets
OwnedPlanets = PlayerPrefsX.GetBoolArray("SavedPlanets", false, 7);
// Make sure this boolean is always true as its the default planet
OwnedPlanets[0] = true;
// Spawn cannon on First frame
GameObject NewCannon = Instantiate(CannonPrefabs[planetActive], Vector3.zero, Quaternion.identity) as GameObject; NewCannon.name = "Space Cannon";
Destroy(CurrentCannon);
CurrentCannon = NewCannon;
// Find the Next Button and Previous Button for the planet selection
nextButton = GameObject.Find("Next_Button").GetComponent<Button>();
PreviousButtons = GameObject.Find("Previous_Button").GetComponent<Button>();
// Make sure previous button cannot be pressed as we cant go negative into the array
PreviousButtons.interactable = false;
// Find the Image we are going to change while scrolling thrrough the array of planets
PlanetImage = GameObject.Find("DisplayPlanet").GetComponent<Image>();
// Find the Game Manager scrip
GM = GameObject.Find("GameManager").GetComponent<Game_Manager>();
// Find the Arrow Button Animators
ShopRoomSmallArrow = GameObject.Find("ShopRoomSmallArrow").GetComponent<Animator>();
WindowRoomSmallArrow = GameObject.Find("WindowRoomSmallArrow").GetComponent<Animator>();
// Obtain the Text component to change the Value of the Planets Text
PlanetPriceText = GameObject.Find("PriceText").GetComponent<Text>();
RobotAS = GameObject.Find("Robot Body").GetComponent<AudioSource>();
greet = Resources.Load<AudioClip>("Audio/UI/Store/Robot Greeting");
celebrate = Resources.Load<AudioClip>("Audio/UI/Store/Robot Celebration");
// Robot Animators
rightArmAnimator = GameObject.Find("RightArm").GetComponent<Animator>();
leftArmAnimator = GameObject.Find("LeftArm").GetComponent<Animator>();
RobotEyes = GameObject.Find("Eyes").GetComponent<Animator>();
// Find the Panel Text
UpradeInQuestion = GameObject.Find("UpgradeTypeText").GetComponent<Text>();
DescriptionText = GameObject.Find("DescriptionText").GetComponent<Text>();
DescriptionText.text = Descriptions[0];
TypeImage = GameObject.Find("UpgradeTypeImage").GetComponent<Image>();
TypeImage.sprite = Logos[0];
BuyButton = GameObject.Find("BuyButton").GetComponent<Button>();
buyButton_AS = BuyButton.GetComponent<AudioSource>();
// Make local variable to obtain reference and turn it off when done finding components (The panel does not need to be on when the I button has not been pressed)
parentPanelInfo = GameObject.Find("InformationPanel");
// Find Nested List Text and Buttons
PriceManager[0].UpgradeButton = GameObject.Find("AmmoCapacityButton").GetComponent<Button>();
PriceManager[0].PriceToChange = PriceManager[0].UpgradeButton.transform.GetChild(0).GetComponent<Text>();
PriceManager[1].UpgradeButton = GameObject.Find("ReloadSpeedButton").GetComponent<Button>();
PriceManager[1].PriceToChange = PriceManager[1].UpgradeButton.transform.GetChild(0).GetComponent<Text>();
PriceManager[2].UpgradeButton = GameObject.Find("FireRateButton").GetComponent<Button>();
PriceManager[2].PriceToChange = PriceManager[2].UpgradeButton.transform.GetChild(0).GetComponent<Text>();
PriceManager[3].UpgradeButton = GameObject.Find("MoneyIncreaseButton").GetComponent<Button>();
PriceManager[3].PriceToChange = PriceManager[3].UpgradeButton.transform.GetChild(0).GetComponent<Text>();
parentPanelInfo.SetActive(false);
Debugging();
PlayerController = GameObject.Find("Space Cannon").GetComponent<SpaceCannon_Controller>();
Debug.Log("Last Line Of Awake Function Runs");
buyPlanet = Resources.Load<AudioClip>("Audio/UI/Store/Buy Planet Sound");
defaultClick = Resources.Load<AudioClip>("Audio/UI/Button Click 2");
}
// Start is called before the first frame update
void Start()
{
// on complete make sure this resets
#region Save data from the tiers of cannon upgrades
// Pass through the saved Value of these int keys
PriceManager[0].CurrentTier = PlayerPrefs.GetInt("AmmoSave");
PriceManager[1].CurrentTier = PlayerPrefs.GetInt("ReloadSave");
PriceManager[2].CurrentTier = PlayerPrefs.GetInt("FireSave");
PriceManager[3].CurrentTier = PlayerPrefs.GetInt("MoneySave");
#endregion
// needs to happen here after we get the saved data values
// change the text so it shows what tier we are on from the last playtime
UpradeInQuestion.text = UpgradeOrder[0] + " " + "\n" + "Tier: "
+ PriceManager[0].CurrentTier + "/" + PriceManager[0].MaxTier;
// Loop through all the nested Lists To set them up
for (int i = 0; i <= PriceManager.Count - 1; i++)
{
// change price text to current prices
PriceManager[i].PriceToChange.text = PriceManager[i].Prices[PriceManager[i].CurrentTier].ToString();
Debug.Log("In Store Price Change Loop Works Here");
}
Debug.Log(PriceManager.Count + "Length Of Price Manager List");
// reset action for multi use
Purchase = null;
}
void Debugging()
{
// Find all variables to see if they are found
if(rightArmAnimator == null)
{
Debug.LogError("RIGHT ARM ANIMATOR NOT FOUND");
}
else
{
Debug.Log("right arm animator found");
}
if(leftArmAnimator == null)
{
Debug.LogError("LEFT ARM ANIMATOR NOT FOUND");
}
else
{
Debug.Log("Left arm animator found");
}
}
// Update is called once per frame
void Update()
{
// if we dont have this variable
if (PlayerController == null)
{
// Find it again, we cant change values on runtime is we dont have it
PlayerController = GameObject.Find("Space Cannon").GetComponent<SpaceCannon_Controller>();
PlayerController.currentAmmo = PlayerController.maxAmmo;
}
else // We have the variable so its time to just run the logic below
{
if(GM.GameOver_Menu.activeInHierarchy == true)
{
PlayerController.gameObject.SetActive(false);
}
// values in the nested lists to be saved during runtime
CannonUpgradeDataSave(PriceManager[0].CurrentTier, PriceManager[1].CurrentTier, PriceManager[2].CurrentTier, PriceManager[3].CurrentTier);
// run the code to make the text smaller
Purchase += GM.RunCo;
// Run the stats // Changes the cannon states
for (int i = 0; i <= PriceManager.Count - 1; i++)
{
// check names to suggest what state we are changing to stop any conflicts
if(PriceManager[i].UpgradeName == "Ammo Capacity")
{
// get the new max ammo and set the current to the new value
PlayerController.maxAmmo = (int)PriceManager[i].NewStates[PriceManager[i].CurrentTier];
}
else if(PriceManager[i].UpgradeName == "Reload Speed")
{
// set the new reload time to the nested list values current position in the list
PlayerController.reloadSpeed = PriceManager[i].NewStates[PriceManager[i].CurrentTier];
}
else if(PriceManager[i].UpgradeName == "Fire Rate")
{
// fire rate value is now the new value inside nested list
PlayerController.FireRate = PriceManager[i].NewStates[PriceManager[i].CurrentTier];
}
else
{
// sends to GM
// meteor is less points than the star
GM.MeteorPoints = (int)PriceManager[i].NewStates[PriceManager[i].CurrentTier];
// Multiply by 2 so star provides more points (Money)
GM.StarPoints = (int)PriceManager[i].NewStates[PriceManager[i].CurrentTier] * 2;
}
}
}
// So we are about to Fade Out
if(FadeOutPanel && !FadeInPanel)
{
FadeInfoPanelOut();
}
else if(!FadeOutPanel && FadeInPanel) // We are going to fade in now
{
FadeInfoPanelIn();
}
// Controls the structure of the Robots animations
RobotAnimations();
// check if a button has been pressed
if(buttonPressed && GM.InShopMenu)
{
if (lerp)
{
GameObject mainMenu = GameObject.Find("MainShop");
if (mainMenu == null)
{
mainMenu = GameObject.Find("MainShop");
}
else
{
mainMenu.transform.position = Vector3.Lerp(mainMenu.transform.position, target, speed);
if (mainMenu.transform.position == target)
buttonPressed = false;
}
}
else
{
GameObject mainMenu = GameObject.Find("MainShop");
if(mainMenu == null)
{
mainMenu = GameObject.Find("MainShop");
}
else
{
mainMenu.transform.position = Vector3.Lerp(mainMenu.transform.position, target, speed);
if (mainMenu.transform.position == target)
buttonPressed = false;
}
}
}
#region Planet Fadding
if (FadeIn)
{
StartCoroutine(FillIn());
}
if (FadeOut)
{
StartCoroutine(FillOut());
}
#endregion
if (MainShopMenu)
{
ShopRoomSmallArrow.SetBool("Active", true);
// Window animator does not move
WindowRoomSmallArrow.SetBool("Idle", false);
//
ShopRoomSmallArrow.SetBool("Idle", true);
}
else
{
WindowRoomSmallArrow.SetBool("Active", true);
//
ShopRoomSmallArrow.SetBool("Idle", false);
//
WindowRoomSmallArrow.SetBool("Idle", true);
}
// UI Planet Purchanse Monitor
// When the Array of bools is true at a position
if(OwnedPlanets[planetScroller] == true)
{
// We set the price text to owned as we clearly own this Planet
PlanetPriceText.text = "Owned";
// change button text to equip
BuyButton.GetComponentInChildren<Text>().text = "Equip";
// If the scroller is on the array length that is the current active sprite
if(planetScroller == planetActive)
{
// We dont use the button as you cannot apply something twice
BuyButton.interactable = false;
// change the text of the button to Equiped - This is the planet that has been equiped
BuyButton.transform.GetComponentInChildren<Text>().text = "Equiped";
}
else if(planetScroller != planetActive) // When the planet scroller does not equal to the current planet position sprite
{
// Turn the button on
BuyButton.interactable = true;
// But we change the button text to Equip as we can change planets if we own more than 1
BuyButton.transform.GetComponentInChildren<Text>().text = "Equip";
}
}
else
{
// Show the price of the planets via the UI text
PlanetPriceText.text = PlanetPrices_[planetScroller].planetPrice.ToString();
// Turn on the button
BuyButton.interactable = true;
// change the button text component to buy
BuyButton.transform.GetComponentInChildren<Text>().text = "Buy";
}
// check to see if we have enough money for each price in each cannon upgrade
for(int i = 0; i <= PriceManager.Count - 1; i++)
{
if(GM.money < PriceManager[i].Prices[PriceManager[i].CurrentTier])
{
PriceManager[i].UpgradeButton.interactable = false;
}
else
{
PriceManager[i].UpgradeButton.interactable = true;
}
if(PriceManager[i].Maxed == true)
{
PriceManager[i].UpgradeButton.interactable = false;
}
}
for(int i = 0; i <= PlanetPrices_.Length - 1; i++)
{
if (GM.money < PlanetPrices_[i].planetPrice)
BuyButton.interactable = false;
}
}
private void OnDisable()
{
Purchase -= GM.RunCo;
}
// Resets the store when we leave the shop
public void ResetStore()
{
// information Menu
// resets what page we are on
scroller = 0;
// go back to first page description
DescriptionText.text = Descriptions[scroller];
// first page upgrade
UpradeInQuestion.text = UpgradeOrder[scroller] + " " + "\n" + "Tier: "
+ PriceManager[scroller].CurrentTier + "/" + PriceManager[scroller].MaxTier;
// first page logo
TypeImage.sprite = Logos[scroller];
// turn off menu
parentPanelInfo.SetActive(false);
// alpha is full
tempImage.a = 255;
// reset as we want it to be at the beginning
planetScroller = 0; // wont affect PlayerPrefs we store in different value
// change sprite
PlanetImage.sprite = Planets[planetScroller];
}
[HideInInspector]
public int waveController = 0;
public void RobotAnimations()
{
// when in the store
if (GM.InShopMenu && GM.shop_Menu.activeInHierarchy == true)
{
if (!PurchasedMade)
{
// Play celebration animation
///Wave - First animation
// Not playing anything
if (waveController == 0)
{
if (RobotAS.isPlaying == false)
{
RobotAS.clip = greet;
RobotAS.PlayDelayed(0.8f);
rightArmAnimator.SetBool("Greeting", true);
waveController++;
}
}
// count upward to get ready to make a condition
timeUntilNextAnim += Time.deltaTime;
// when value is greater than or equal to 3
if (timeUntilNextAnim >= 3)
{
RobotAS.Stop();
rightArmAnimator.SetBool("Greeting", false);
// reset the timer
timeUntilNextAnim = 0;
// pick a number
eyeDirection = Random.Range(0, 8);
// play animation
RobotEyes.SetInteger("Choice", eyeDirection);
}
}
else
{
if(RobotAS.isPlaying == false)
{
RobotAS.clip = celebrate;
RobotAS.Play();
timeUntilNextAnim = 0;
// play the one shot clip instead of using the controller
rightArmAnimator.Play("Right Arm Celebration"); leftArmAnimator.Play("Left Arm Celebration");
// Tick bool to false
PurchasedMade = false;
}
}
}
}
// detects if we have made a purchase to play robot animation
public void PurchaseMade(bool purchase)
{
Purchase();
PurchasedMade = purchase;
}
#region Functions to change Planets
public void NextPlanet()
{
// Trigger effect
FadeIn = true;
// increase so sprite changes
planetScroller++;
// Change direction of fade
// Left
PlanetImage.fillOrigin = 0;
}
public void PlanetBefore()
{
// tick true
FadeOut = true;
// Decrease value
planetScroller--;
// Change effect origin
// Right
PlanetImage.fillOrigin = 1;
}
// Going Right
// Fads out on Left Fills in on right
// Fade out the planet image as we would be changing the sprite
// gives small effect of moving in space
IEnumerator FillIn()
{
FadeIn = true;
nextButton.interactable = false;
PreviousButtons.interactable = false;
PlanetImage.fillAmount -= Time.deltaTime;
if (PlanetImage.fillAmount == 0)
{
PlanetImage.fillOrigin = 1;
PlanetImage.sprite = Planets[planetScroller];
}
if (PlanetImage.fillOrigin != 0)
{
PlanetImage.fillAmount += Time.deltaTime * 2;
if (PlanetImage.fillAmount == 1)
{
int i = 0;
i = planetScroller + 1;
if (i >= Planets.Length)
{
FadeIn = false;
nextButton.interactable = false;
PreviousButtons.interactable = true;
PlanetImage.fillOrigin = 0;
yield break;
}
else
{
FadeIn = false;
nextButton.interactable = true;
PreviousButtons.interactable = true;
PlanetImage.fillOrigin = 0;
yield break;
}
}
}
}
// Planet reamurges with the new planet sprite in effect and we fill the image in a different direction
IEnumerator FillOut()
{
FadeOut = true;
nextButton.interactable = false;
PreviousButtons.interactable = false;
PlanetImage.fillAmount -= Time.deltaTime;
if (PlanetImage.fillAmount == 0)
{
PlanetImage.fillOrigin = 0;
PlanetImage.sprite = Planets[planetScroller];
}
if (PlanetImage.fillOrigin != 1)
{
PlanetImage.fillAmount += Time.deltaTime * 2;
if (PlanetImage.fillAmount == 1)
{
if (planetScroller == 0)
{
FadeOut = false;
nextButton.interactable = true;
PreviousButtons.interactable = false;
PlanetImage.fillOrigin = 0;
yield break;
}
else
{
FadeOut = false;
nextButton.interactable = true;
PreviousButtons.interactable = true;
PlanetImage.fillOrigin = 0;
yield break;
}
}
}
}
#endregion
#region Lerp Menu Button Functions
public void ButtonPressed(bool pressed)
{
buttonPressed = pressed;
}
public void Lerp(bool lerpChoice)
{
lerp = lerpChoice;
}
public void LerpTarget(Transform Target)
{
target = Target.transform.position;
}
public void MainShopMenuCheck(bool inShopMenu)
{
MainShopMenu = inShopMenu;
}
#endregion
#region InformationPanel
/// <summary>
/// Makes the UI reappear
/// </summary>
public void FadeInfoPanelIn()
{
// Condition to just stop the below code when the parent is not active
if (parentPanelInfo.activeInHierarchy == false)
return;
// Local array to find all the information panel Text Components
Text[] textcomponentChild = parentPanelInfo.GetComponentsInChildren<Text>();
Image[] imageComponentChild = parentPanelInfo.GetComponentsInChildren<Image>();
// increase from alpha channel
tempText.a += Time.deltaTime;
tempImage.a += Time.deltaTime;
// Loop to make each Text component change Alpha
foreach (Text tx in textcomponentChild)
{
// make the Text Components equal the color vairable so it obtains the alpha
tx.color = tempText;
TypeImage.color = tempImage;
}
}
/// <summary>
/// Make the UI on screen vanish over time and so it can reappear
/// </summary>
public void FadeInfoPanelOut()
{
if (parentPanelInfo.activeInHierarchy == false)
return;
//Obtain UI Components in children from parent
Text[] textcomponentChild = parentPanelInfo.GetComponentsInChildren<Text>();
Image[] imageComponentChild = parentPanelInfo.GetComponentsInChildren<Image>();
// obtain the base color forthe Text
tempText = textcomponentChild[0].color;
tempImage = TypeImage.color;
// decrease the alpha
tempText.a -= Time.deltaTime;
tempImage.a -= Time.deltaTime;
// Loop to change all the UI components
foreach (Text tx in textcomponentChild)
{
// Change alpha by using the Temp colour
tx.color = tempText;
TypeImage.color = tempImage;
}
// When the alpha has hit 0
if (tempText.a <= 0)
{
// make sure it does not get deducted anymore
tempText.a = 0;
// Make this false so we can fade in now
FadeOutPanel = false;
// check to see what boolean we clicked to increase or decrease the scroller int
if (ClickedRightInfoButton)
scroller++;
else if (ClickedLeftInfoButton)
scroller--;
// Change the on screen information since the UI does not have Alpha at a visible level
DescriptionText.text = Descriptions[scroller];
UpradeInQuestion.text = UpgradeOrder[scroller] + " " + "\n" + "Tier: "
+ PriceManager[scroller].CurrentTier + "/" + PriceManager[scroller].MaxTier;
// Change Image
TypeImage.sprite = Logos[scroller];
// Now we can fade in
FadeInPanel = true;
}
}
/// <summary>
/// Function to be used OnClick of the Information Panel Buttons
/// Button to go back (Right)
/// </summary>
public void NextUpgrade()
{
#region Controlling the booleans
FadeOutPanel = true;
FadeInPanel = false;
ClickedRightInfoButton = true;
ClickedLeftInfoButton = false;
#endregion
// Button interactive check
if (scroller >= 2)
{
GameObject.Find("RightButton").GetComponent<Button>().interactable = false;
GameObject.Find("LeftButton").GetComponent<Button>().interactable = true;
}
else
{
GameObject.Find("RightButton").GetComponent<Button>().interactable = true;
GameObject.Find("LeftButton").GetComponent<Button>().interactable = true;
}
}
/// <summary>
/// Function to be used OnClick of the Information Panel Buttons
/// Button to go back (Left)
/// </summary>
public void PreviousUpgrade()
{
#region Controlling The Booleans
FadeOutPanel = true;
FadeInPanel = false;
ClickedLeftInfoButton = true;
ClickedRightInfoButton = false;
#endregion
// Buutton interaction check
if (scroller == 1)
{
GameObject.Find("RightButton").GetComponent<Button>().interactable = false;
}
if (scroller <= 1)
{
GameObject.Find("LeftButton").GetComponent<Button>().interactable = false;
GameObject.Find("RightButton").GetComponent<Button>().interactable = true;
}
else
{
GameObject.Find("LeftButton").GetComponent<Button>().interactable = true;
GameObject.Find("RightButton").GetComponent<Button>().interactable = true;
}
}
#endregion
#region Planet Purchase
public void ChangePlanetSprite()
{
// if the planet is owned then we have the option to equipt it
if(OwnedPlanets[planetScroller] == true)
{
if(RunTimePlanet.sprite == EquipPlanets[planetScroller])
{
Debug.Log("<color=cyan> This Planet Is Equipped</color>", this);
BuyButton.GetComponentInChildren<Text>().text = "Equipped";
// save the data on this int so we know what planet we are using
PlayerPrefs.SetInt("CurrentPlanet", planetScroller);
}
else
{
BuyButton.GetComponentInChildren<Text>().text = "Equip";
buyButton_AS.clip = defaultClick;
// Spawn the cannon that matches this planet
GameObject NewCannon = Instantiate(CannonPrefabs[planetScroller], Vector3.zero, Quaternion.identity) as GameObject; NewCannon.name = "Space Cannon";
Destroy(CurrentCannon);
CurrentCannon = NewCannon;
// Change the main game planet sprite
RunTimePlanet.sprite = EquipPlanets[planetScroller];
Debug.Log("<color=cyan> We Just Equipped This Planet</color>", this);
planetActive = planetScroller;
// save the data on this int so we know what planet we are using
PlayerPrefs.SetInt("CurrentPlanet", planetScroller);
}
PlanetPriceText.text = "Owned";
// we can equip these planets
Debug.Log("<color=cyan> We Own This Planet</color>", this);
}
else
{
Debug.Log("<color=red> We Do Not Own This Planet</color>", this);
// because we dont own it we want to buy it instead
if(GM.money >= PlanetPrices_[planetScroller].planetPrice)
{
BuyButton.GetComponentInChildren<Text>().text = "Buy";
buyButton_AS.clip = buyPlanet;
// save the data on this int so we know what planet we are using
PlayerPrefs.SetInt("CurrentPlanet", planetScroller);
// set value so it knows what planet we use
planetActive = planetScroller;
// buy the planet
Debug.Log("<color=cyan> We Now Own This Planet</color>", this);
// we now own this planet
OwnedPlanets[planetScroller] = true;
// we now change the planet in game to the planet we purchased
RunTimePlanet.sprite = EquipPlanets[planetScroller];
// we also spawn the new cannon that corresponds with this planet
GameObject NewCannon = Instantiate(CannonPrefabs[planetScroller], Vector3.zero, Quaternion.identity) as GameObject; NewCannon.name = "Space Cannon";
// we destroy the old planet
Destroy(CurrentCannon);
// the new cannon is set
CurrentCannon = NewCannon;
// deduct money from players funds
Game_Manager.starDust -= PlanetPrices_[planetScroller].planetPrice;
// Save array data to give back later
PlayerPrefsX.SetBoolArray("SavedPlanets", OwnedPlanets);
}
else
{
// Cannot Afford Planet
Debug.Log("<color=red> We Dont Have Enough Money For This Planet</color>", this);
BuyButton.interactable = false;
}
}
}
#endregion
#region Store Upgrader
public void ChangePrice(int Type)
{
// if we do not have the money
if(GM.money <= PriceManager[Type].Prices[PriceManager[Type].CurrentTier])
{
// turn off the corresponding button for that upgrade
PriceManager[Type].UpgradeButton.interactable = false;
}
else
{
// if we do not have a maxed out upgrade we can buy it
if (PriceManager[Type].Maxed != true)
{
// the button is now on for we can buy this upgrade
PriceManager[Type].UpgradeButton.interactable = true;
// extra check to make sure we have not gone past the max tier of upgrades for that upgrade
if (PriceManager[Type].CurrentTier >= PriceManager[Type].MaxTier)
{
// turn this off for we have gone past or equal to the max
PriceManager[Type].UpgradeButton.interactable = false;
// we have maxed out this upgrade
PriceManager[Type].Maxed = true;
// Text tells player its maxed out
PriceManager[Type].PriceToChange.text = "Max";
}
else
{
// if not max we simply deduct the funds from the player
Game_Manager.starDust -= PriceManager[Type].Prices[PriceManager[Type].CurrentTier];
// we are now on a new tier of upgrade for we just purchased
PriceManager[Type].CurrentTier++;
// change the old price to the new one
PriceManager[Type].PriceToChange.text = PriceManager[Type].Prices[PriceManager[Type].CurrentTier].ToString();
}
}
else
{
// if not relevent to any then return with nothing, blockoff
return;
}
}
}
#endregion
// Simple function that saves the data in a nested list so we can store them on runtime and obtain them on new awake or start
void CannonUpgradeDataSave(int AmmoSave, int ReloadSave, int FireSave, int MoneySave)
{
PlayerPrefs.SetInt("AmmoSave", AmmoSave);
PlayerPrefs.SetInt("ReloadSave", ReloadSave);
PlayerPrefs.SetInt("FireSave", FireSave);
PlayerPrefs.SetInt("MoneySave", MoneySave);
}
}
#region Upgrade Classes
[System.Serializable]
public class PriceChange
{
[Tooltip("The Name Of The Array We Are Altering")]
public string UpgradeName = "";
[Tooltip("Text That Changes With Upgrade")]
public Text PriceToChange;
[Tooltip("The List Of Prices For Each Upgrade")]
public List<int> Prices = new List<int>();
[Tooltip("The value that tells us what tier of upgrade we are on")]
public int CurrentTier = 0;
[Tooltip("The Button that belongs to the upgrade")]
public Button UpgradeButton;
[Tooltip("The New States of the different upgrades")]
public List<float> NewStates = new List<float>();
[Tooltip("The Max Amount Of Upgrades We set to do")]
public int MaxTier;
public bool Maxed = false;
}
[System.Serializable]
public class PlanetPrices
{
public string planetName = "";
public int planetPrice;
}
#endregion
[expand title=”Force Field”]
In the project, I wanted to give the player a slight advantage and provide them with a force field that can be damaged and then destroyed. So I decided to make a shader graph to make the effect I wanted to achieve. So visually I saw the force field as a pulsating object which would change colour after every hit. I also saw it as having a hiney comb texture scrolling over it. I made the shader graph for a 3D sphere in unity.
The Final Version of it is here
These are all the variables I used to make the graph these variables control, colour lerping, the electric noise control and also the fill amount of the force field which made the force field more transparent. I also needed the force field to pulse to give an effect of power
So now that I have a way to make the force field glow I made a texture scroller to make a texture wrap around the object
After I made this part of the graph I wanted a way to close the force field when its health had hit zero. So I decided to make a cross-section where the force field would open up from the bottom and disappear when it had reached the top.
This part makes the logic to close the force field
But this part adds to the final result
The only other logic this shader needed was being able to lerp its colour and also having an electric noise outline. I made this logic into subgraphs to save space but this is the outcome.
This is the electric noise being applied to the final emission
This is the lerp in the main graph which is held against a branch condition where the players forcefield will change from blue to orange then red as its final colour.
These are the variables I used in the electric noise subgraph. Being able to change the tiling and offset of the noise texture and then control how much noise gets exposed while also changing its colour.
This is the main contents of the subgraph where time effects the tiling and offset output and using the step node to make the output positive while then linking it to the subtract to making it negative so then just the right amount of noise is exposed
These are the only variables I needed to control the force field lerp. The current colour I have, then the next colour I wanted to change to. Also how long that would take.
Then the variables are hooked up to a Lerp node which then meant I could call this subgraph inside the main graph and then start Lerping colours
[/expand]
[expand title=”Sprite Outline”]
The Sprite outline shader was not that tough to handle, the outline was mainly applying a texture you want to be outlined and applying the texture to the different parts of the sprite so it overlaps a little. This is why thickness is a variable so the texture can get bigger on its outline.
The outline is just the Texture we want to outline but bigger.
This part of the graph finds the left, right, top and bottom part of the sprite. We do this so the entire sprite has an outline.
We then add and clamp the outcome so the outline will never change. then providing an outline colour from our variable and then input it into the end node.
[/expand]
[expand title=”Dissolve”]
The dissolve shader was made to dissolve the planet the player protects when an obstacle hits it. In a way to show that the planet was about to explode. Before the dissolve ends I spawn an explode effect.
The variables for the dissolve graph simply made a texture slowly dissolve, using noise to give the dissolve effect and proving a colour so we see a different colour when we dissolve. Fade just simply determine how long it takes for the dissolve to start and finish.
The noise node then provides its information being given the noise scale we set for the dissolve size. then making sure keeping the dissolve noise stays positive with the step node. also providing the sample texture to then multiply and combine with the final outcome. The Colour variable is also passed through too so the dissolving colour can be changed.
[/expand]
[expand title=”UI Tiles”]
These are the tiles I created for the UI store menu. Although I did not use all of these this was the image I had for the game
[/expand]
[expand title=”Different Planets & Cannon”]
These are different variations of the planets and cannons I made for the game that you can buy in the store. I just liked the different designs and being able to buy a new design I think players would enjoy, it gives them variety.
[/expand]
[expand title=”UI tiles”]
These are the different variations of backgrounds I made for the game and decided to choose the first one for the game as I felt like it fit well with the game more than a brighter colour
[/expand]
While developing this game I learnt a lot about my future goals and what game platform I want to develop on. I plan to focus on making games for android mobile devices, making WebGLs for websites like Itch.IO and making games to release on platforms like steam. It was a fun experience making a project where I created all the assets alone, stressful at times but an experience I don’t plan on forgetting anytime soon. I would say this project allowed me to learn a lot about sound design. I found myself at the best of times enjoying making sound effects and music while using Audacity to achieve it. I also learnt more about shader graph and now understanding what subgraphs do. I had never used them in the past but now after using them, I feel comfortable more with using shader graph. Lastly, I would say I have realised I have a lot to learn when it comes to UI there was a lot of issues I faced when it came to UI and a lot of mistakes like Lerping the game menu but forgetting the idea people don’t all share the same aspect ratio for their devices. I enjoyed making this project a lot and watching every little detail come to life. It was extremely fun starting a project with really basic standard assets like cubes and circles and then seeing them turn into art assets that have visual effects and audio clips to play. If you would like to view this project I have linked my Github, where all the code and assets can be found. But if you would like to play it then I have also linked it on the Google Play Store.