Control and Intro Screen

I decided to create an intro screen to give players a chance to become familiarized with the controls and for them to confirm they are ready before the game starts, after all the assets are loaded.

JpegScreenShot6

Intro screen (Appears after main scene has loaded)

By pressing the spacebar, the following image is loaded to inform the player of the controls:

Controls

Upon pressing enter on either of these screens, the screen moves forward into 3D space and fades out, creating a sense of diving into a  computer screen.

Pickups

Above are the four pickups I designed for the game.

Glitch Time

This pickup fills up a gauge next to the current life mugshot. If the player has at least one section of the gauge stocked up, they can activate Glitch Time at any point to consume one bar to slow down the game time temporarily.

 

MedKit

This pickup only spawns after the player has been damaged. It restores one of the player’s lives.

 

Nuke

This pickup destroys all enemies on screen. It will only drop rarely. This is a work-in-progress idea so we haven’t actually implemented it into the game yet, it depends on our progress in other aspects of the game as it is not essential, though it will help during later stages of the game.

 

Phase Mode

This pickup makes the player invincible for a limited amount of time, making them unable to take any damage. The player model also flickers giving it a digital, ghost-like effect.

 

 

 

 

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

Score multiplier system

Today I was able to implement a score multiplier system. We thought this would be essential for some variation for high scores if we want to include leaderboards.

scoremultiply

Early implementation of HUD multiplier feedback

My next step for this is to set it up so that when the multiplier is not active (when it has a value of 1) it will be hidden.

Code (added to exisiting score manager code):

void Update()
    {
        if (PlayerDie.PlayerAlive == true && pauseGame.paused == false)
        {
            score = score + (scorescale * scoreMultiplier * Time.time); //score growth rate increases over time

            //will add code to make score scale reset to 0 every time damage is taken.

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

            Multiplier = scoreMultiplier;
            //for public inspector feedback on multiplier

            MultiplyScore.text = Mathf.Abs(scoreMultiplier).ToString("0.#");

            ScoreMultiply();
            //run score multiply control system
        }
    }

void ScoreMultiply()
    {
        if (scoreMultiplier > 1f && ResetOK == false)
        {
            ResetOK = true;
            StartCoroutine (MultiplyReset());
        }
    }

    IEnumerator MultiplyReset() //resets the multiplier to 0 after shooting no enemies for a certain amount of time

    {
        yield return new WaitForSeconds(MultiplierResetTime);
        scoreMultiplier = 1f;
        ResetOK = false;
    }

Shooting update

I updated the player shooting script to destroy enemies on click. This is currently the most effective form of shooting so we’ll stick with this for now and try to improve it later on aesthetically.

e7b8aad87c

Enemy being destroyed

It works by creating a bullet inside the enemy at its current location, instantly destroying it. I was able to do this by modifying my previous shooting code, and adding this to it:

if (Physics.Raycast(ray, out hit) && Input.GetMouseButtonDown(0))
			{
				Debug.Log (hit.collider.gameObject);
				enemy = hit.collider.gameObject;
				Invoke("Fire",fireTime);	
				Rigidbody newBullet = Instantiate(bullet,transform.position,transform.rotation) as Rigidbody;
				newBullet.AddForce(transform.forward*velocity,ForceMode.VelocityChange);
				newBullet.transform.position = Vector3.Lerp(newBullet.transform.position, enemy.transform.position, velocity);	//destroy enemy on click

			}

Enemy movement path system

I decided to remake the way the enemies move in this as enemies play a bigger part in this version of Ikarus compared to the previous version. While it would be nice to have complex movement paths it could over complicate things for now.

ss (2015-04-16 at 06.55.21)

Ikarus (previous version) global enemy movement system

I did some experiments with rotating track points using a tracking script that gives each enemy a different value to move towards.

EMP01

Experimenting with ways to create movement paths

I eventually found that the most successful way to do this was to have a point behind the player that the enemies are trying to reach, so I created this script that mirrors the player’s movement (minus the rotation as that caused some serious problems, enemies could essentially all be controlled through aiming). I couldn’t do this via attaching it to the player as it would count as killing the player when the enemies reached this point.

ET01

Gameobject (cube) that enemies move toward, which is attached to the player. They are instantly destroyed on contact to reduce lag. (4 Dec 2015)

Code (Move towards cube):

	public GameObject target;

	void Update () 
	{
		{
		target = GameObject.FindWithTag("EnemyTarget");
		transform.LookAt(target.transform);
	        }
	}

This goes on each enemy.

Code (Mirror player’s XY position):

	public Transform playerme;

	public Vector3 posFollow = new Vector3(0,0,0);

	void Start () 
	{
	
	}
	
	void Update () 
	{
		this.transform.position = playerme.position;
		this.transform.position = this.transform.position + posFollow;
	}

This goes on the cube behind the player.

I started making simple enemy specific movement paths by making the enemies have invisible rotating parent objects.

ss (2015-11-28 at 02.53.49)

Enemy (placeholder) and rotating parent object.

While experimenting with alternative approaches to water I discovered that the cloth component I was using also worked with the enemies.

ss (2015-11-28 at 02.53.31)

I set constraints on the main body of the virus and left the limbs unconstrained so that they could flop about like tentacles, giving the virus an alien-like feel to it.

ss (2015-12-07 at 02.32.06)

The result was a spider-like virus that seemed completely alien. The rotating movement path helped to keep the limbs constantly moving. This was well recieved by the team and from outside feedback so we may keep this enemy for the final build of our game, or build upon it while keeping this characterstic.

Pause/Death UI, Sound

I was able to script a pause and death user interface menu into the game.

The difference between the pause and death menus is that the death menu does not come up with the option to resume. On both menus the user is able to see the cursor, contrary to the cursor being invisible during gameplay. All music and gameplay is also stopped, this was done by enabling the line of code ‘Time.timescale = 0′.

ss (2015-11-29 at 09.41.16).jpg

I found some royalty-free music on Kevin McCleod’s website that fit in well with the theme of the game. They can serve as placeholder tracks for now but I think they could even work for the final product, depending on our other options. The pitches of the tracks are adjusted in-game to fit better, Unity is slightly slower and Rhinocerous is slightly faster.

Title

Gameplay

I was able to make the music slow down to a stop on death by creating this code:

public float pitchSpeed = 1.19f;
	
	void Update () 
	{
		AudioSource audio = GetComponent();
		
		audio.pitch = pitchSpeed;
	
		if (PlayerDie.PlayerAlive == false)
		{
			pitchSpeed = (pitchSpeed * 0.9f);
				if (audio.pitch <= 0)
				{
				audio.pitch = 0;
				}
		}
		
		if (pauseGame.paused == true)
		{
			audio.pitch = 0;
		}
		
		if (pauseGame.paused == false && PlayerDie.PlayerAlive == true)
		{
		audio.pitch = 1.19f;
		}
	}

This works well because it put emphasis on halting the players momentum. Suddenly stopping the music wouldn’t sound very professional so this is most likely the best way we can accomplish a sudden stop in the audio that is easy on the ears.

Score script

Increase score over time

public class ScoreManager : MonoBehaviour {

	public static float score = 1f;

	public float scorescale = 0.2f;
	public static float scoreMultiplier = 1f;
	public static float enemyPoints = 0f;

	public Text TextScore;


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

	// add code to make score scale reset to 0 every time damage is taken.

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

		}
	}
}

Score increment by 50 with basic enemy killed

void OnTriggerEnter (Collider col)
{
if (col.gameObject.tag == "Bullet")
{
Rigidbody newTrail = Instantiate(explode,transform.position,transform.rotation) as Rigidbody; //instantiate particle explosion animation
newTrail.AddForce(transform.forward*explodeVelocity,ForceMode.VelocityChange);
ScoreManager.score = (ScoreManager.score + 50); // add 50 points to score when enemy is killed
Debug.Log ("enemy dead");
Destroy (gameObject);
}
}

This part of code on the EnemyDie script (Destroys enemies when they come into contact with a bullet) creates a small particle explosion effect and adds a flat value of 50 to the player’s score. In the future I plan to change the flat value to a float variable so I can change score values depending on the type of enemy. I would also like to implement a score multiplier based on enemies destroyed in quick succession.

Capture

UI text displaying updating score value

In the future I would like a way to give visual feedback on how much score the player is getting for  destroying enemies, for example a ‘+50’ could pop up next to the score each time an enemy with the score value of 50 is destroyed.

Key Item Pickup, Inventory and Door Open v2 scripts

We needed to sort out some kind of inventory system so that the player could find objects and pick up key items. I tried for a ling time to create my own script but after many failed attempts I was able to find an inventory system script on the unity asset store.

Inventory system

preeE

After doing some setting up I was able to treat this circle as a ‘key object’. When E is pressed the object is destroyed and a global Boolean variable is flipped which allows the player to open the main door.

inventory

You can also hold down the tab button to display the inventory, I created this key sprite so you can identify when you have the key or not.

The code is far too long for me to post here (you can download it + the assets pack here: http://www.mediafire.com/download/w9p98xrg2u9j5tt/InventoryScripts+Assets.zip) but after editing the code and applying it to my door script I was able to create this message that is displayed when you get close to the door without a key.

youneedakey