Advanced Towers 

Master's Capstone Project

Year: Jan 2016-Dec-2016

Tools:

Unity Game Engine/C#

Description

I created this game as my computer science Masters project. This is a PC game in the tower defense genre. In this game type, the goal is to protect the base from waves of enemies. The player does this by placing towers on the map. The player is given resources at the start of each level. The resources are used to buy and upgrade towers. The player is awarded more money for each enemy he/she kills. Once all of the enemy waves are defeated, the player wins the game.

Programming Methodology

created a base class that most unit's used. I created child classes for specialized units. I used Object oriented to avoid repeating code I created helper classes for unit and tower data. I created separate classes for most gameplay mechanics(ie towers)

Unit Base Class

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Unit_Base : MonoBehaviour {

//get the way points
public GameObject[] waypoints;
private int currentWaypoint = 0;
private float lastWaypointSwitchTime;
public float speed = 1.0f;
public int health;
public float armor;
public enum ResistanceType { Fire, Energy} //May code more of these
public int victoryPoints;//amount deducted from player when the creep reaches the end
public int bounty; //amount of points the player gets when destroyed

 
public float dropRate = 5;
public GameObject lootDrop;

public GameManager gameManager;//Find the game manager class

public void Start()
{
gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
lastWaypointSwitchTime = Time.time; //Puts enemy waypoint switch time at current time
}

void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag.Equals("Projectile"))
{
int damage = other.gameObject.GetComponent<BulletBehavior>().damage; // Get the Bullet's daamage ratings
Destroy(other.gameObject);

//Assign the health background
Transform healthBarTransform = gameObject.transform.FindChild("HealthBar");
HealthBar healthBar =
healthBarTransform.gameObject.GetComponent<HealthBar>();
healthBar.currentHealth -= Mathf.Max(damage, 0);

if (health >= 0)
{
health -= damage;
Debug.Log("ouch");
}
else
{
destroyMe();

 }

}
else if (other.gameObject.tag.Equals("Explosion"))
{

Debug.Log("explosion Damage");
 // int damage = other.gameObject.GetComponent<BulletBehavior>().damage; // Get the Bullet's daamage ratings


//Assign the health background
Transform healthBarTransform = gameObject.transform.FindChild("HealthBar");
HealthBar healthBar =
healthBarTransform.gameObject.GetComponent<HealthBar>();
healthBar.currentHealth -= Mathf.Max(5, 0);

if (health > 0)
{
health -= 5;
Debug.Log("ouch");
}
else
{
destroyMe();
}

}
else if (other.gameObject.tag.Equals("Flame"))
{

Debug.Log("Flame Damage");
int damage = other.gameObject.GetComponent<BulletBehavior>().damage; // Get the Bullet's daamage ratings
 //Destroy(other.gameObject);
 //The flame should not beedestroyed it is 'on' until the enemy is out of its range

//Assign the health background
Transform healthBarTransform = gameObject.transform.FindChild("HealthBar");
HealthBar healthBar =
healthBarTransform.gameObject.GetComponent<HealthBar>();
healthBar.currentHealth -= Mathf.Max(damage, 0);

if (health >= 0)
{
health -= damage;
Debug.Log("ouch");
}
else
{
destroyMe();
}

}
else if (other.gameObject.tag.Equals("SmartBomb"))
{

Debug.Log("Hit by bomb power uo Damage");
// int damage = other.gameObject.GetComponent<BulletBehavior>().damage; // Get the Bullet's daamage ratings
 // Destroy(other.gameObject);
 //Causes bomb projectile to die right away
 // not neccesarilly what we want

//Assign the health background
Transform healthBarTransform = gameObject.transform.FindChild("HealthBar");
HealthBar healthBar =
healthBarTransform.gameObject.GetComponent<HealthBar>();
healthBar.currentHealth -= Mathf.Max(150, 0);

if (health > 0)
{
//hardcoded for now,, maybe add class for explosion meshes later
health -= 150;
Debug.Log("ouch!!");
}
else
{
destroyMe();
}

}
else if (other.gameObject.tag.Equals("Rocket"))
{
int damage = other.gameObject.GetComponent<BulletBehavior>().damage; // Get the Bullet's daamage ratings
Destroy(other.gameObject);

//Assign the health background
Transform healthBarTransform = gameObject.transform.FindChild("HealthBar");
HealthBar healthBar =
healthBarTransform.gameObject.GetComponent<HealthBar>();
healthBar.currentHealth -= Mathf.Max(damage * 2, 0); //updayted 9-25 the rocket does double damage to tank

if (health >= 0)
{
health -= damage; //Take more damage if its a rocket
Debug.Log("ouch");
}
else
{
destroyMe();
}

}

}

public void destroyMe()
{
Destroy(gameObject);
gameManager.Money += bounty;

if(Random.Range(0, 20) <=dropRate)
{
//pick a random number between 1 and 20 
//If the number is less than the droprate, drop some loot
Instantiate(lootDrop, transform.position, transform.rotation);

}

}

public float distanceToGoal()
{
float distance = 0;
distance += Vector3.Distance(
gameObject.transform.position,
waypoints[currentWaypoint + 1].transform.position);
for (int i = currentWaypoint + 1; i < waypoints.Length - 1; i++)
{
Vector3 startPosition = waypoints[i].transform.position;
Vector3 endPosition = waypoints[i + 1].transform.position;
distance += Vector3.Distance(startPosition, endPosition);
}
return distance;
}

private void RotateIntoMoveDirection()
{
//fixed 5-16-16
//1
Vector3 newStartPosition = waypoints[currentWaypoint].transform.position;
Vector3 newEndPosition = waypoints[currentWaypoint + 1].transform.position;
Vector3 newDirection = (newEndPosition - newStartPosition);
 
float x = newDirection.x;
float y = newDirection.y;
float rotationAngle = Mathf.Atan2(y, x) * 180 / Mathf.PI;

SpriteRenderer sprite = (SpriteRenderer)gameObject.transform.GetComponent<SpriteRenderer>();
sprite.transform.rotation =
Quaternion.AngleAxis(rotationAngle, Vector3.forward);
}

public void Update()
{
Vector3 startPosition = waypoints[currentWaypoint].transform.position;
Vector3 endPosition = waypoints[currentWaypoint + 1].transform.position;
// 
float pathLength = Vector3.Distance(startPosition, endPosition);
float totalTimeForPath = pathLength / speed;
float currentTimeOnPath = Time.time - lastWaypointSwitchTime;
gameObject.transform.position = Vector3.Lerp(startPosition, endPosition, currentTimeOnPath / totalTimeForPath);

///check a unit'ds health
///This is just a failsafe to prevent the unit from living when it should be dead
if(health <= 0)
{
//way to make sure objecct is destroyed if health ia 0
destroyMe();
 }

// 3 
if (gameObject.transform.position.Equals(endPosition))
{
if (currentWaypoint < waypoints.Length - 2)
{
// 3.a 
currentWaypoint++;
lastWaypointSwitchTime = Time.time;
//Rotate in a certain direction
RotateIntoMoveDirection();

}
else {
Destroy(gameObject);

//Audio here

//deduct player's health
gameManager.Health -= victoryPoints; // vicrtory points set in uniit

}
}

}

}
embed Block
Add an embed URL or code. Learn more.

Game Overview:

 

The game will be a tower defense strategy game. The goal of the game  is the to protect the base from waves of enemies. The player does this by placing towers on designated spots the map. The player is given resources at the start of each level. The resources are used to buy and upgrade towers. The player is awarded more money for each enemy he/she kills. Once all of the enemy waves are defeated, the player wins the game.

 

 

General Game Rules

 

Waves/Rounds

Each mission consists of a series of rounds. During each round, the enemy will attack with a set number of units. When all the enemy units in a wave are destroyed, the round ends. At the end of each round, the player is awarded additional money. A bonus calculation is used to determine how much money the player gets, See the economy section for more information.

 

 

Winning:

The player can win the game on either defense or offense. The mission type determines the victory condition.  

 

Survival:

The player wins the game when the player survives all the waves.

 

 

Losing:

 

Losing Too Many Lives

The player loses the game if too many enemies get to the base. t

 

 

Enemy MOBS/ Starting Paths

  • Each map has a predefined number of spawn points

  • Enemies are generated from the points

  • Each spawn point has a designated destination

  • Each spawn point has a list of enemy units that is generated in each wave

  • Each spawn point has a ui arrow that shows the path from the destination

 

Post game mission

 

When the mission ends, the player is taken to a post game mission screen. Three states (units killed, towers built, and tower value) are tracked by the gamecontroller script.