07/03/16 Update: Debug mode + Gameplay

Over the past couple of weeks I was able to implement these features:

 

Heads Up Display

I made some HUD components to make the game information clearer to see.

HUD_L

Score + multiplier component

HUD_R

Lives component

HUD_vign

Visor component

We were on the fence about keeping the visor component in as it implies that the player is in first person when they are actually playing in third-person, but it had good synergy with the chromatic aberration effect so we decided to keep it in.

First person HUD GUI_scoreGameShot

Chromatic Aberration impact effect

I took the chromatic aberration effect further and made it so the amount of chromatic aberration spikes briefly when the player is hit, then decreases back to the value I previously set, which when used in conjunction with the visor HUD component creates a burst/pulse effect on the edge of the screen similar to a screen shake. This is useful for giving visual feedback on the player’s current status and it gives the illusion of an impact.

hurt gif.gif

(Hard to see blinking hurt animation because of GIF framerate)

Bullet system rework

My previous solution to our shooting problem was to spawn the bullets inside of enemies, causing them to die when clicked. I’ve been able to code a way for bullets to fly directly towards individual enemies allowing for  a cleaner looking shooting system. The major issue that seems to have popped up through feedback is that it gets harder to click directly on the enemies as time progresses due to it being such a specific thing. I think a lock-on mechanic would fix this problem easily, however  we may not have enough time to implement a thorough system.

shooting gif

 

Stage system

I have implemented a stage system that increases the stage in intervals of 8000 points. This is a temporary interval as our score acquisition rate increases with time meaning that jump from stage 1 to stage 2 is much longer than the jump from stage 4 to stage 5. It will take a lot of trial and error and testing to get more accurate numbers or it might even require an alternate stage progression method. The current stage is displayed at the top of the screen.

stage switch gif

Global Speed

There is now a global speed variable that is applied to all moving assets of the game such as enemies and obstacles, making the game feel faster depending on the current stage number.

Enemies increase in frequency as stage progresses

As the stage number increases so does the enemy spawn rate, making it harder as the player progresses. I intend on changing this from simply spawning more of the same enemy to spawning more difficult variations of our enemies or even new ones.

Debug Mode

Pressing escape in-game brings up the debug menu on the top of the screen.

This gives us the following options:

  • F1-F5: Skip to stage
  • F6: Have a bad time (Insta-kill player for testing purposes)
  • F7: God mode (Invincibility state. Turned off when debug menu is closed)

debug mode

High score system

The high score is now shown on the pause/game over menu. This is only stored while the game is open, meaning the value is lost once the game is closed. My next goal in this area is to store the high score to a local file allowing it to remain consistent between game loading. As a stretch goal we could have a leader board system implemented.

 

Life system implementation

I was able to add a life system into the game today. It works by making the player go invisible on enemy collision to imply invincibility frames until the life count has  decremented to the point that the player gets a game over.

Key lines of code:

public int playerLives = 3;

void Start ()
    {
	Debug.Log("Lives:"+playerLives);
        rend = GetComponent();
        rend.enabled = true;
    }

void OnTriggerEnter(Collider col)
	{
		if (col.gameObject.tag == "Enemy" && GodMode == false)
		{   
            if (playerLives <= 1)             {                 Destroy(gameObject);                 PlayerDie.PlayerAlive = false;                 Debug.Log("Death via enemy");             }             if (playerLives >= 2)
            {
                // Health = Health - 100f;
                playerLives--;
                Debug.Log("Player lost a life");
                Debug.Log("Lives:"+playerLives);
                StartCoroutine(blinkTime());
            }

 IEnumerator blinkTime()
    {
        rend.enabled = false;
        yield return new WaitForSeconds(1f);
        rend.enabled = true;
    }

Lives system

I did some research on ways to implement the lives into the HUD and found these examples:

Starfox

Starfox (SNES)

Starfox uses a “Lives x (number of lives)” format which I thought would be quite useful for our game, but decided against it as it implies that the player respawns on the spot which we wanted to avoid. We wanted something that properly showed that the player was getting damaged.

Super street fighter 2

Super Street Fighter 2 – Ryu Portrait

We looked at games that gave feedback of procedural damage to the player and decided that this was a good direction to go in, so I plan to use a similar format for our game. I’ll design a mugshot sprite of the main character with alternative damaged versions.

KHCoM

Kingdom Hearts: Chain of Memories Health HUD

Glitch effect test using After Effects

I got the Twitch plugin for Adobe After Effects and decided to apply it to the pixel version of our title as a test.

I plan to do this to png snapshots of certain assets, and then attach an animated png sequence of the end result as an overlay for certain enemies to show that they are more glitchy and volatile.

Doing this test made me realise that it visually works quite well for the title screen, but it may not make sense to apply it as Project Ikarus is supposed to be the antivirus program of the game world. It very much fits with the theme of our game so I’ll get some outside opinions on this soon.

Icarus: Cylindrical texture, Score, Animations, Bloom Shader

I created a cylinder and mapped this seamless space texture onto it. I also added a bloom effect to the main camera which worked well with this texture as it made the highlights glow slightly.

Original bloom shader test

Second bloom shader test. Update 2 (More textures)

The tiling for the space texture was stretched when I mapped it originally and this created an interesting looking effect which we decided to keep.

We had to do this instead of a skybox because we wanted something that would work with the SpeedUpOverTime function.

I created 2 GUIText objects, one that would be fed a modified SpeedUpOverTime value displaying it (Score*) and one that just said ‘Score:’

One the game runs, it changes to this

This is the script I create to manage the score, as the original speed value rises too quickly.

Score script (ScoreManager):

public class ScoreManager : MonoBehaviour {

	public float score = 1f;

	public float scorescale = 0.2f;

	public Text TextScore;


	public GameObject scoreScreen;
	// Use this for initialization
	void Start () 
	{
		score = 1f;
	}
	
	// Update is called once per frame
	void Update () 
	{
		if (PlayerDie.PlayerAlive == true)
		{
			score = score+(scorescale*Time.time);


			TextScore = scoreScreen.GetComponent();
			TextScore.text = Mathf.Floor(score).ToString();

		}
	}
}

I did most of the animating in unity using the Animation Editor.

Intro animation for the ship to fly into the scene

I also animated the yellow obstacle to make it rotate as it comes towards you.

Malakai gave me a pickup object for me to animate.

I animated the rings to rotate and the middle one to bob up and down.

Animated the middle ring to bob up and down while spinning before proceeding to animate the top and bottom rings

Icarus: Sound Effects

For the sound effects and music I used FL Studio to add various effects such as delay and pitch modifying to create my own sounds out of samples. And create seamless loops.

Game over sound:

Looping static modified to fade out

Adding delay to a sample after changing the pitch. This is the retry/menu select sound after clicking

Icarus: Desynchronised

Video (Low quality)

For the game over screen I created a sequence in after effects. It transitions the screen through a series of bars to a static background with the text ‘Desynchronised’, which slowly fuzzes away and becomes distorted and red as the retry and menu words appear. Though these are not actual buttons, I made them work as such by putting a gameobject behind them that can only be clicked on once the player has globally been confirmed as dead in the game.

The gameobject with the mesh renderer enabled for placement

Clicking on a retry or menu reloads the scene or sends the player to the menu, respectively. It also resets the player’s status and reloads the game scene meaning it can be played again without leaving remnants of the previous gameplay.

Retry code (RestartOnClick):

using UnityEngine;
using System.Collections;

public class RestartOnClick : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	void OnMouseDown()
	{
	        // this object was clicked - do something
		audio.Play();
		Invoke("Load", 1);
		PlayerDie.PlayerAlive = true;
	}   

	void Load()
	{
		Application.LoadLevel ("Debug");  
	}
}

Icarus: Accidental asteroid concept + Movement barriers

Upon adding textures to objects and illuminated shaders to the enemies and obstacles for testing purposes, we realized our game was moving more towards a spacey theme with neon elements similar to geometry wars. Then when I was testing out a custom effect using the instantiate command I accidentally spawned all of these:

Textures + materials disabled

I thought, what if these were asteroids, would it be fun to look at or just make everything a lot more cluttered and detract from the experience.

In the end we decided against it but Musa modelled an asteroid for this reason so the possibility still remains.
I also was able to create a movement barrier for the ship and reticle, keeping the player constrained within the camera.

Image from finalized build (Edited back into post)

I did this by disabling the respective directions’ input by flipping the value, for instance pressing right makes the player move on the x axis by a value of 1, but once they reach the barrier and try to continue moving in the direction the code flips it to make the input conflict with itself resulting in an x axis movement value of 0, meaning the player will not move. The same was done for the reticle.

I used an individual script for each side and called it in the movement script. Here is an example of the script I used for the barrier on the right.

StopRight script:

using UnityEngine;
using System.Collections;

public class StopRight : MonoBehaviour 
{
	public static bool stopPlayerRight = false;
	
	// Use this for initialization
	void Start () 
	{
		stopPlayerRight = false;
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	
	void OnTriggerEnter(Collider col)
	{
		if(col.gameObject.tag == "Player")
		stopPlayerRight = true;
	}
	
	void OnTriggerExit(Collider col)
	{
		if(col.gameObject.tag == "Player")
		stopPlayerRight = false;
	}
}

Called in movement script:

	void Update () 
	{
		float horizontal = Input.GetAxis ("Horizontal");
		float vertical =  Input.GetAxis("Vertical");

		if(StopUp.stopPlayerUp == true)
		{
			vertical = Mathf.Clamp(vertical,-1f, 0f);
		}

		if(StopDown.stopPlayerDown == true)
		{
			vertical = Mathf.Clamp (vertical,0f, 1f);
		}

		if(StopLeft.stopPlayerLeft == true)
		{
			horizontal = Mathf.Clamp (horizontal,0f, 1f);
		}

		if(StopRight.stopPlayerRight == true)
		{
			horizontal = Mathf.Clamp (horizontal,-1f, 0f);
		}

Icarus: Texture Scroll, Particle Effects, Trails, Game Manager Spawning, Aiming & Speed Up Over Time

I decided to remove the MoveForward script from the GameplayPlane group containing the camera and ship and scroll the plane texture using an offset code, giving the illusion that the player is moving when they aren’t.

I also added a global static variable to this that speeds up as the game progresses with the Time.time code. I plan of referencing this in other codes such the the MoveForward code so that obstacles and enemies will come at the player faster as the game progresses.

Texture Scroll code:

public float scrollSpeedY = 5.00f;
public float scrollSpeedX = 0.00f;
public static float updatedSpeed = 0f;
	public float YSpeed = 0f;
	public float maxSpeed = 20f;

void FixedUpdate() 
	
	{
	scrollSpeedY = (scrollSpeedY * YSpeed);
	updatedSpeed = (scrollSpeedY * Time.time);

	float offset = updatedSpeed;
	float offset2 = Time.time * scrollSpeedX;
	renderer.material.mainTextureOffset = new Vector2(offset2,-updatedSpeed);
	
		if (updatedSpeed > maxSpeed)
			updatedSpeed = maxSpeed;

		if (scrollSpeedY > maxSpeed)
			scrollSpeedY = maxSpeed;
	
		if (PlayerDie.PlayerAlive == false) 
		{
//			YSpeed = (YSpeed * -YSpeed);
		}
	}

}

I added a particle effect to the back of the ship to give it more of an animated look and to add to the illusion of it moving when it’s in place. It does look quite extreme though, it could fit depending on how fast the objects are coming towards the player but it looks a bit awkward as the ship turns as the trail just points away from where the player is pointing.

I was able to create a parallax effect by using the texture offset code on these cloud textures that I had put on planes and stretched to give the illusion they’re moving faster. The parallax came from slowing down the texture speed by having a lower scroll speed variable for textures on further planes.

Alpha channel of cloud texture

I set up a game manager script which allowed me to spawn objects from a certain distance. I planned to use this to spawn enemies, objects, and pickups.

GameManager script:

using UnityEngine;
using System.Collections;

public class SpawnerObjCustom : MonoBehaviour {
	
	public GameObject enemy;
	public int enemyCount;
	public float spawnWait;
	public float startWait;
	public float waveWait;
	public float maxEnemies = 5f;
	public float minX = -5.5f;
	public float maxX = -5.5f;
	public float minY = -5.5f;
	public float maxY = -5.5f;
	
	// Use this for initialization
	void Start () 
	{
		StartCoroutine(SpawnWaves ());
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	
	IEnumerator SpawnWaves()
	{
		if (enemyCount < maxEnemies)
		{
			yield return new WaitForSeconds (startWait);
			while(true)
			{
				for(int i = 0; i < enemyCount; i++)
				{
					//Make an enemy
					Vector3 spawnPosition = new Vector3(Random.Range (minX, maxX), Random.Range (minY, maxY), 30);
					Instantiate(enemy, spawnPosition, enemy.transform.rotation);
					
					yield return new WaitForSeconds (spawnWait);
				}
				
				yield return new WaitForSeconds (waveWait);
				
			}
		}
	}
}

Malakai sent me a basic enemy model for us to use as a placeholder for the final enemy model. I set this up in the game manager to spawn an enemy from a distance.

By using my ‘LookAt’ and ‘EnemyAttack’ scripts I was able to create a complex enemy tracking system in which each enemy is assigned a value from 1-5 and there are 5 points on an invisible spinning disc. The next step is for me to get the enemies to repeat this same behavior on a similar object set behind the player, only after a number of seconds have passed.

Enemy tracking system finalized (Final build image, edited into post)

LookAt script:

	public GameObject target;

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () 
	{
		transform.LookAt(target.transform);
	}
}

EnemyAttack script:

using UnityEngine;
using System.Collections;

public class EnemyAttackA : MonoBehaviour 
{
	public GameObject player;
	public GameObject target2;
	public float smoothing = 1f;
	public float stopDis = 1f;
	public int randomEnemy;
	public float waitTime = 15f;
	private int currentTrack;
//	private int currentTrack;

	private bool finalAttack;

	// Use this for initialization
	void Start () 
	{
		GameObject spawnObj = GameObject.FindGameObjectWithTag ("GameManager");
		currentTrack = spawnObj.GetComponent ().currentTrackNum();
		Debug.Log (currentTrack);
		randomEnemy = Random.Range (0, 4);
		//for (int i = 0; i < 4; i++) { 			 		player = GameObject.Find ("EnemyPoint" + currentTrack); 				//} 		target2 = GameObject.Find ("EnemyTimeUp"); 		StartCoroutine(AttackPattern()); 		Invoke ("FinalAttack",6); 	} 	 	// Update is called once per frame 	void Update ()  	{ //		Debug.Log (Time.deltaTime); 	} 	IEnumerator AttackPattern() 	{ 		while(Vector3.Distance(transform.position, player.transform.position) > stopDis)
		{

			if(!finalAttack)
			{
				transform.position = Vector3.Lerp(transform.position, player.transform.position, (smoothing * Time.deltaTime));
			}
			else
			{
				transform.position = Vector3.Lerp(transform.position, target2.transform.position, (smoothing * Time.deltaTime));
			}
			yield return null;
		}
		
		print("Reached the target.");

		yield return new WaitForSeconds(waitTime);
		{
			while(Vector3.Distance(transform.position, player.transform.position) <= stopDis)
			{
			print("Enemy leaving screen.");
			transform.position = Vector3.Lerp(transform.position, target2.transform.position, smoothing * Time.deltaTime);
			}
		}
		

	}


	void FinalAttack()
	{
		finalAttack = true;
	}





} 

I added trails to the tip of the ship via empty gameobjects set as children. However since the ship is actually not moving forward the trail does not show up unless I move up, down, left or right with the arrow keys. I find this annoying as it breaks the illusion slightly, I may switch it back to the previous method I was using before and try and get the same setup working with the MoveForward script on the plane parent.

Added a barrel roll easter egg (Double tap E)

I decided to turn the mesh renderer off on the bullet prefab after discovering how to use trails as I applied it to the prefab and it gave a smoother looking streamlined beam look.

The enemies contain a script that causes them to destroy themselves on contact with bullets and instantiate an empty gameobject prefab that has a explosive particle effect on them with the same colour. The empty gameobject also plays a death sound on awakening.

EnemyDie script:

using UnityEngine;
using System.Collections;

public class EnemyDie : MonoBehaviour {

	public float lifeTime = 2f;
	public Rigidbody explode;
	public float explodeVelocity = 10.0f;

	// Use this for initialization
	void Start () 
	{
		//explode.Pause();
	}
	
	// Update is called once per frame
	void Update () 
	{
		//Destroy (gameObject, lifeTime);
		//replace this with fly away over time
	}
	
	void OnTriggerEnter (Collider col)
	{
		if (col.gameObject.tag == "Bullet")
	{
			Rigidbody newTrail = Instantiate(explode,transform.position,transform.rotation) as Rigidbody;
			newTrail.AddForce(transform.forward*explodeVelocity,ForceMode.VelocityChange);
			Destroy (gameObject);
	}
}
}

I created an object that could be controlled using the arrow keys that will later be transformed into a controllable aiming reticle. The LookAt script was used on the ship so it would always face the reticle no matter what, and it could still be controlled seperately from the reticle as it uses the WASD keys instead of the arrow keys.

I later on replaced this controllable box and the two distance-judging reticle placeholders with a square with an self-illuminated alpha reticle texture.

Reticle texture

Icarus: Movement + Shooting

My first goal in this project was to get the movement working over anything else. So after getting a dummy ship Malakai made I started to work getting it to move.

I attached three circles as child objects to the ship to act as reticles, as I need a clear view of where the ship is pointing and it helps give a sense of distance.

Movement code (ShipMovement):

using UnityEngine;
using System.Collections;

public class ShipMovement : MonoBehaviour 
{
	public float movementSpeed = 20.0f;
	public int yAxisMovSpeed = 1; 
	

	void Update () 
	{
		float horizontal = Input.GetAxis ("Horizontal");
		float vertical =  Input.GetAxis("Vertical");

		Vector3 direction = new Vector3(horizontal,yAxisMovSpeed*vertical,0);
		Vector3 finalDirection = new Vector3(horizontal,yAxisMovSpeed*vertical,1.0f);

		transform.position += direction*movementSpeed*Time.deltaTime;

		transform.rotation = Quaternion.RotateTowards (transform.rotation, Quaternion.LookRotation (finalDirection), Mathf.Deg2Rad * 50.0f);	
	}
}

I may need to rethink the movement algorithm as there is a finite distance the player can travel before reaching the end of the plane.

I also would like to layer the plane with transparency to create the illusion of parallax.

I was also able to create movement by instantiating a prefab and applying a force to it.

Forward shoot script (ShootForward):

using UnityEngine;
using System.Collections;

public class ShootForward : MonoBehaviour 
{
	public Rigidbody bullet;
	public float velocity = 10.0f;
	
	// Update is called once per frame
	void Update () 
	{
		if(Input.GetButtonDown("Fire1")) 
		{
			Rigidbody newBullet = Instantiate(bullet,transform.position,transform.rotation) as Rigidbody;
			newBullet.AddForce(transform.forward*velocity,ForceMode.VelocityChange);
		}
	}
}

Games Mechanic – Term 2: Project Icarus

For this brief we had to create a vertical slice of a 3D game of a genre of our choice.

We decided to go with a third-person space shooter, as we were inspired by various titles such as Starfox and Kid Icarus Uprising, which led us towards the project name ‘Icarus’.

However we wanted less focus on shooting and more on avoiding obstacles, as we were also inspired by games such as Piano Tiles and Sonic Colors.

In this project I am going to be focusing on scripting and animation.

Most of my time will be dedicated to scripting over animation as I’m the only one in the group doing it and animation comes in at much later stages.

As a group we will be recording our progress and organizing ourselves using Trello, this is a link to our board: https://trello.com/b/uxghpaUT/icarus