package {
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import td.*;
import td.projectiles.*;
import td.towers.*;
import td.utils.*;
[SWF(width="560", height="320", frameRate="30", backgroundColor="#ffffff")]
/**
* The actual TD class that runs the entire logic of the game
*
* @author Garth Henson - Guahan Web (garth@guahanweb.com)
*/
public class MagicTD extends Sprite
{
protected var creep_timer :Timer;
protected var cleanup_timer :Timer;
protected var backgroundMC :Sprite = new Sprite();
protected var bulletMC :Sprite = new Sprite();
protected var creepMC :Sprite = new Sprite();
protected var towerMC :Sprite = new Sprite();
protected var bullets :Array = new Array();
protected var creeps :Array = new Array();
protected var towers :Array = new Array();
protected var map :Map;
protected var starting_point :Array;
protected var ending_point :Array;
protected var points :Array;
protected var full_width :int = 560;
protected var full_height :int = 320;
public var grid_size :int;
/**
* Constructor method for our application
*
* @constructor
* @access public
* @return void
*/
public function MagicTD()
{
this.points = [[2, -1], [2, 5], [6, 5], [6, 16], [28, 16], [28, 4], [12, 4], [12, 19], [22, 19], [22, 12], [36, 12]];
this.grid_size = 16;
this.drawBackground();
this.setupMap();
this.setupTimers();
this.setupListeners();
this.addChild(this.creepMC);
this.addChild(this.bulletMC);
this.addChild(this.towerMC);
this.test();
}
/**
* Used for testing purposes - sets up a test environment for our app
*
* @access protected
* @return void
*/
protected function test() :void
{
var a :Sprite = new Sprite();
a.graphics.lineStyle(1, 0x444444);
a.graphics.beginFill(0xcccccc);
a.graphics.drawCircle(0, 0, 6);
a.graphics.endFill();
a.x = 500;
a.y = 15;
a.buttonMode = true;
a.addEventListener(MouseEvent.CLICK, testNormal);
this.addChild(a);
var b :Sprite = new Sprite();
b.graphics.lineStyle(1, 0x770000);
b.graphics.beginFill(0xffaaaa);
b.graphics.drawCircle(0, 0, 6);
b.graphics.endFill();
b.x = 520;
b.y = 15;
b.buttonMode = true;
b.addEventListener(MouseEvent.CLICK, testFire);
this.addChild(b);
var c :Sprite = new Sprite();
c.graphics.lineStyle(1, 0x000077);
c.graphics.beginFill(0xaaaaff);
c.graphics.drawCircle(0, 0, 6);
c.graphics.endFill();
c.x = 540;
c.y = 15;
c.buttonMode = true;
c.addEventListener(MouseEvent.CLICK, testIce);
this.addChild(c);
}
protected function testNormal(e :MouseEvent) :void
{
var t :Tower = new Tower(this);
t.x = this.parent.mouseX;
t.y = this.parent.mouseY;
this.towers.push(t);
this.towerMC.addChild(t);
}
protected function testFire(e :MouseEvent) :void
{
var t3 :Tower = new FireTower(this);
t3.x = this.parent.mouseX;
t3.y = this.parent.mouseY;
this.towers.push(t3);
this.towerMC.addChild(t3);
}
protected function testIce(e :MouseEvent) :void
{
var t2 :Tower = new IceTower(this);
t2.x = this.parent.mouseX;
t2.y = this.parent.mouseY;
this.towers.push(t2);
this.towerMC.addChild(t2);
}
/**
* Draw the background graphics for this game
*
* @return void
*/
protected function drawBackground() :void
{
var g :Graphics = this.backgroundMC.graphics;
g.beginFill(0xe4e4e4);
g.drawRect(0, 0, this.full_width, this.full_height);
g.endFill();
g.lineStyle(1, 0xaaaaaa);
for (var i :int = 0; i < Math.round(this.full_width / this.grid_size); i++)
{
g.moveTo(i * this.grid_size, 0);
g.lineTo(i * this.grid_size, this.full_height);
}
for (i = 0; i < Math.round(this.full_height / this.grid_size); i++)
{
g.moveTo(0, i * this.grid_size);
g.lineTo(this.full_width, i * this.grid_size);
}
this.addChild(this.backgroundMC);
}
/**
* Set up the map with the points assigned to this member variable
*
* @return void
*/
protected function setupMap() :void
{
this.map = new Map(this.points, this.grid_size, this);
this.map.drawRoad();
this.addChild(this.map);
}
/**
* Set up any timers we need and start them
*
* @access protected
* @return void
*/
protected function setupTimers() :void
{
this.creep_timer = new Timer(1000);
this.creep_timer.start();
this.cleanup_timer = new Timer(15000);
this.cleanup_timer.start();
}
/**
* Set up any listeners we need for this application
*
* @access protected
* @return void
*/
protected function setupListeners() :void
{
this.creep_timer.addEventListener(TimerEvent.TIMER, createCreep);
this.cleanup_timer.addEventListener(TimerEvent.TIMER, cleanup);
this.addEventListener(MouseEvent.CLICK, handleGlobalClick, true);
}
/**
* Creates a new creep with every timer tic
*
* @access protected
* @param {TimerEvent} e The creep timer
* @return void
*/
protected function createCreep(e :TimerEvent) :void
{
var c :Creep = new Creep(this.points, this);
this.creeps.push(c);
this.creepMC.addChild(c);
}
/**
* Handles the user's clicking on anything not handled within an object
*
* @access protected
* @param {MouseEvent} e the click event
* @return void
*/
protected function handleGlobalClick(e :MouseEvent) :void
{
clearSelections();
}
/**
* Fires a bullet from the provided tower towards the next creep in range
*
* @access public
* @param {Tower} the tower from which to fire
* @return void
*/
public function fire(t :Tower) :void
{
try {
var c :Creep = this.obtainTarget(t.x, t.y, t.getRange());
var b :Bullet = t.getNewBullet(c);
this.bullets.push(b);
this.bulletMC.addChild(b);
}
catch (e :Error)
{
}
}
/**
* Time for resource cleanup
*
* @access protected
* @param {TimerEvent} e The timer event calling this method
* @return void
*/
protected function cleanup(e :TimerEvent) :void
{
var i :int = 0;
for (i = 0; i < this.bullets.length; i++)
{
var b :Bullet = this.bullets[i];
if (b.isDestroyed())
{
this.bulletMC.removeChild(b);
this.bullets.splice(i, 1);
}
}
for (i = 0; i < this.creeps.length; i++)
{
var c :Creep = this.creeps[i];
if (c.isDestroyed())
{
this.creepMC.removeChild(c);
this.creeps.splice(i, 1);
}
}
}
/**
* Finds and returns the first creep that is within the given radius from the position provided
*
* @access public
* @param {int} posX the X coordinate
* @param {int} posY the Y coordinate
* @param {int} radius the range to scan
* @return Creep
*/
public function obtainTarget(posX :int, posY :int, radius :int) :Creep
{
targetLoop: for (var i :int = 0; i < this.creeps.length; i++)
{
var diffX :int = Math.abs(posX - this.creeps[i].x);
var diffY :int = Math.abs(posY - this.creeps[i].y);
var dist :int = Math.round(Math.sqrt((diffX * diffX) + (diffY * diffY)));
if (dist <= radius && !this.creeps[i].isDestroyed())
{
return this.creeps[i];
}
}
throw new Error('No targets available');
}
/**
* Since this is the global click handler, we want to deselect anything that was previously selected
*
* @access public
* @return void
*/
public function clearSelections() :void
{
for (var i :int = 0; i < this.towers.length; i++)
{
towers[i].deselect();
}
for (i = 0; i < this.creeps.length; i++)
{
creeps[i].deselect();
}
}
/**
* Calculates the pixels to the given point on the grid
*
* @access public
* @param {Number} x the point to calculate
* @param {Boolean} b whether or not to center the point
* @return Number
*/
public function getPointToPixels(x :Number, b :Boolean) :Number
{
var r :int = x * this.grid_size;
if (b == true)
{
return r - (this.grid_size / 2);
}
return r;
}
}
}