Updated Tower Defence learning - Work in Progress

This is part 2 of a previous post, I’ve redesigned a lot of the code since then. 

DEMO HERE

This is my latest version of a simple tower defence game. it’s nowhere near finished, but I’ve been learning quite a bit when I have any spare time.

Current Features:

  • Click “Tower 1” to spawn a tower, then it follows the mouse around screen until you click again.
  • You can only spawn towers on black parts of the map / maze (it checks the texture pixel data)
  • You cannot spawn a tower in the same place as a previous tower.
  • You cannot spawn a tower unless you have enough money.
  • You can press ‘c’ to switch into first-person mode (something I might include in my final game)

That’s all I’ve got working so far (there just aren’t enough hours in the day)

Still to do:

  • Creeps + Waypoint system
  • Towers targeting creeps and firing at them
  • learn how to do GUI skins, make it look nice.
  • etc etc

I hope to split this into a couple of projects - one standard tower defence with creeps etc. and then maybe a 2-player game where 1 player drops blocks like a sort of lego building game, and the other player is in first person mode and has to traverse the level with the help of the first player.

You can test out the latest project work here

Here are the more important scripts (BE WARNED: code not optimised or complete, but it might give you some ideas) - most of these have been put together with the help of Unity Answers forum and the Unity Script Reference.

FollowMouseAround.js  [attach this script to Tower Prefab]


var GridSize: float = 5.0;
var ColliderToIgnore: String = "Floor";
var MyLayerMask : int = 1 << 8;
static var hit : RaycastHit;  //this var needs to be accessed in CheckGridColour function

function Update(){
		if (Input.GetButtonDown ("Fire1")) {  //If mouse is clicked (if user tries to place tower)
          		if (CheckGridColour()){ //check if the grid colour is correct, otherwise stay in drag tower mode
				PlaceTheTower();
			} //if the colour isn't correct, we're still in drag+place tower mode
	}

	mousePos = Input.mousePosition;  //Track mouse position as Vector
	var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);

	// TEMPORARY DEBUGGING
	// Debug.DrawRay (ray.origin, ray.direction * 80, Color.red);
	
	if (Physics.Raycast (ray, hit)) {
		transform.position = Vector3 (hit.point.x, 2.5, hit.point.z);
		StickToGrid(); // slightly modify the position so we keep to the grid
    }
}



function StickToGrid(){
	// Now we change the position of the object to make sure it sticks to the grid
	// Don't bother with Y value (height from ground)
	transform.position.x = Mathf.Round(transform.position.x / GridSize) * GridSize;
	transform.position.z = Mathf.Round(transform.position.z / GridSize) * GridSize;
}

function CheckGridColour(){
	var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
	var hit : RaycastHit;
	var hitNorm: Vector3;	

	if (Physics.Raycast (ray, hit)) {

		if (hit.transform.name == ColliderToIgnore){ //only spawn object if you're pointing at the 'Floor'
		
			var TextureMap: Texture2D = hit.transform.renderer.material.mainTexture; //we will use this to figure out the craic
			var pixelUV = hit.textureCoord; //get the points on the texture where the raycast hit (THIS ONLY WORKS WITH MESH COLLIDERS!!!!)
   		        pixelUV.x *= TextureMap.width;
    		        pixelUV.y *= TextureMap.height;
		
			if (TextureMap.GetPixel(pixelUV.x,pixelUV.y)==Color.black){ //We need to double check the colour
				return true;
			}
			else{
				print("you can't place a tower there!");return false;
			}
			
		}
		else{
			print("there's already a tower there!");
		}
	}
}

function PlaceTheTower(){
	gameObject.layer = 0; //put in the default layer, raycasts will now work on this tower
	MoneyCounter.DaMonies -=AllVars.Tower1Price;  // reduce funds by tower cost
	GameObject.Find("TestCube(Clone)").name = "Tower"; // rename clone of tower to a final name so that we can differentiate
        Destroy(this); //delete the follow mouse around script, so the tower is stuck in place.
}

CameraSwitching.js   [camera 1 is main camera, camera2 is First person]


var camera1 : Camera;
var camera2 : Camera;
var fpc : GameObject;
public var currentCamera : int = 1;

function Start () 

{
camera1.enabled = true; camera2.enabled = false;
currentCamera = 1;
KillFPC(); //stop and hide FPC for now (until required)
} 



function Update () {
	if (Input.GetKeyDown ("c") && (currentCamera == 1)){
		currentCamera = 2; camera1.enabled = false; camera2.enabled = true;
		FixFPC();
	}
	else if (Input.GetKeyDown ("c") && (currentCamera == 2)){
		currentCamera = 1; camera1.enabled = true; camera2.enabled = false; 
		KillFPC();
	}
}

function KillFPC(){
		var fpc = GameObject.Find("First Person Controller");
		fpc.GetComponent("MouseLook").enabled = false;
		fpc.GetComponent("CharacterMotor").enabled = false;
		fpc.GetComponent("FPSInputController").enabled = false;
		GameObject.Find("Graphics").renderer.enabled = false;
		guiMenu.guiVisible=true;
}

function FixFPC(){
		var fpc = GameObject.Find("First Person Controller");
		fpc.GetComponent("MouseLook").enabled = true;
		fpc.GetComponent("CharacterMotor").enabled = true;
		fpc.GetComponent("FPSInputController").enabled = true;
		GameObject.Find("Graphics").renderer.enabled = true;
		guiMenu.guiVisible=false;
}

guiMenu.js [I just attach this to an empty gameobject]


var Tower1: Transform;
static var guiVisible : boolean = true;

function OnGUI () {

if (guiVisible){

	// Make a background box for menu
	GUI.Box (Rect (10,10,110,130), "Debug Menu");

	if (GUI.Button (Rect (20,40,95,20), "Clear Towers")) {
		var allTowers = GameObject.FindGameObjectsWithTag ("tower");
		for (var aTower in allTowers) {Destroy(aTower);}
	}

	if (GUI.Button (Rect (20,70,95,20), "Tower 1")) {
		if (CheckMoney(AllVars.Tower1Price)){
			Tower1Spawn = new Vector3(-66, 2, 46);//to the top left of the board
			Instantiate (Tower1, Tower1Spawn, Quaternion.identity);
		}
		else{
			print("not enough funds");
		}
  	}
	
	if (GUI.Button (Rect (20,100,95,20), "Add $100")) {
		MoneyCounter.DaMonies +=100;
	}
	
	// -------------------------------------------------------------
	// SHOW THE MONIES

	GUI.Box (Rect (10,200,100,40), "Money");
	GUI.Label (Rect (50, 220, 100, 20), "$ "+MoneyCounter.DaMonies.ToString());
}


}


function CheckMoney(ThePrice:int){
	if (MoneyCounter.DaMonies < ThePrice){return false;}else{return true;}
}

There are a couple of tiny other scripts but I’m sure anyone with basic UnityScript knowledge will figure them out. (if not let me know I’ll send you the whole project)

If anyone has any questions / critiques please let me know. I love learning this stuff and I realise I’m not doing everything 100%

Thanks for reading

  1. pojomcbooty posted this
Blog comments powered by Disqus