Left 2 Die - Zombie Mayhem (Single player version)
...
* @author Swingpants
*
* Left 2 Die - "Zombie Mayhem"
* An exercise in cooperative play
*
* Built for the Moock Checkmate Challenge - ran out of time - misjudged when deadline was
*
* This is a single player version
*
* Aim of game take your team to the safe house (top left corner)
* Got to stay together to survive
*
* To Do:
*
* Register death
* Register Safe House arrival
* Multiplayer layer
* Audio
* Special Infected (Smoker & Hunter)
* Use spawning zones rather than initiating all zombies at beginning
/**
* Copyright swingpants ( http://wonderfl.net/user/swingpants )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/azMY
*/
/**
* ...
* @author Swingpants
*
* Left 2 Die - "Zombie Mayhem"
* An exercise in cooperative play
*
* Built for the Moock Checkmate Challenge - ran out of time - misjudged when deadline was
*
* This is a single player version
*
* Aim of game take your team to the safe house (top left corner)
* Got to stay together to survive
*
* To Do:
*
* Register death
* Register Safe House arrival
* Multiplayer layer
* Audio
* Special Infected (Smoker & Hunter)
* Use spawning zones rather than initiating all zombies at beginning
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.display.Loader
import flash.net.URLRequest
import flash.display.Bitmap
import flash.system.LoaderContext;
[SWF(width = 480, height = 480, backgroundColor = 0x333333)]
public class Main extends Sprite
{
private var _container:Sprite = new Sprite()
private var _message_layer:Sprite=new Sprite()
private var _controller:Controller
private var _turn_timer:TurnTimer = new TurnTimer()
private var _move_panel:MovePanel = new MovePanel()
private var _loader:Loader
private const IMAGE_URLS:Array = ["http://www.swingpantsflash.com/images/terrain.jpg",
"http://www.swingpantsflash.com/images/player1.png",
"http://www.swingpantsflash.com/images/player2.png",
"http://www.swingpantsflash.com/images/player3.png",
"http://www.swingpantsflash.com/images/player4.png",
"http://www.swingpantsflash.com/images/zombie.png"
]
private var _url_index:int = 0
private var _terrain:Sprite = new Sprite()
private var _canvas:Sprite = new Sprite()
private var _p1_bmp:Bitmap
private var _p2_bmp:Bitmap
private var _p3_bmp:Bitmap
private var _p4_bmp:Bitmap
private var _zombie_bmp:Bitmap
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
//this.graphics.beginFill(0xFF0000,0.6)
//this.graphics.drawCircle(60, 60, 100)
//this.graphics.endFill()
loadNextImage()
}
private function loadNextImage():void
{
trace("[loadNextImage]")
var context:LoaderContext = new LoaderContext();
context.checkPolicyFile=true;
_loader= new Loader();
var req:URLRequest = new URLRequest(IMAGE_URLS[_url_index]);
_loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onLoadHandler );
_loader.load(req,context);
}
private function onLoadHandler(event:Event):void
{
trace("[onLoadHandler] - _url_index="+_url_index)
//switch throwing error "Expecting CaseLabel"!!?
if(_url_index==0)_terrain.addChild(_loader);
if(_url_index==1)_p1_bmp = Bitmap(_loader.content);
if(_url_index==2)_p2_bmp = Bitmap(_loader.content);
if(_url_index==3)_p3_bmp = Bitmap(_loader.content);
if(_url_index==4)_p4_bmp = Bitmap(_loader.content);
if(_url_index==5)_zombie_bmp = Bitmap(_loader.content);
_url_index++
if (_url_index < 6)
{
loadNextImage()
}
else
{
this.graphics.beginFill(0x00FF00,0.6)
this.graphics.drawCircle(120, 120, 100)
this.graphics.endFill()
trace("CONTINUEINIT")
continueInit()
}
}
private function continueInit():void
{
var gb:GameBoard = new GameBoard(_terrain)
addChild(gb)
//Set up the controller
_controller = new Controller(this.stage,gb,_message_layer,_move_panel,_turn_timer)
//Add players (max 4)
_controller.addPlayer(GameBoard.ROWS-4,GameBoard.COLS-1,_p1_bmp)
_controller.addPlayer(GameBoard.ROWS-3,GameBoard.COLS-2,_p2_bmp)
_controller.addPlayer(GameBoard.ROWS-2,GameBoard.COLS-3,_p3_bmp)
_controller.addPlayer(GameBoard.ROWS-1,GameBoard.COLS-4,_p4_bmp)
//Need to calc zombie patterns
addZombieCluster(55, 55)
addZombieCluster(54, 59)
var spread:Number=4
for (var i:int = 0; i < GameBoard.COLS; i += Math.round(spread))
{
for (var j:int = 0; j < GameBoard.ROWS; j += Math.round(spread))
{
if((i<GameBoard.COLS-10 || j<GameBoard.ROWS-10) && (i>10 || j>10)) addZombieCluster(i, j)
}
spread*=1.08
}
_turn_timer.x = 200
_turn_timer.y = 300
//
gb.addChild(_message_layer)
_move_panel.x = GameBoard.SCREENW*0.5;_move_panel.y=GameBoard.SCREENH*0.5
_controller.update()
startGame()
}
public function startGame():void
{
addChild(_turn_timer)
addChild(_move_panel)
_controller.startNextTurn()
}
private function addZombieCluster(posx:int, posy:int):void
{
var cluster:Array=[[1,0,0,1],[0,1,1,0],[0,1,1,0],[1,0,0,1]]
for (var i:int = 0; i < 4; i++)
{
for (var j:int = 0; j < 4; j++)
{
if (cluster[i][j] == 1 && posx+j<GameBoard.COLS && posy+i<GameBoard.ROWS)
{
_controller.addZombie(posx+j,posy+i,duplicateImage(_zombie_bmp))
}
}
}
}
private function duplicateImage(original:Bitmap):Bitmap
{
var image:Bitmap = new Bitmap(original.bitmapData.clone());
//image.x = size * numChildren;
//addChild(image);
return image;
}
}
}
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.EventDispatcher
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.geom.Point
import caurina.transitions.Tweener
import flash.display.Stage
import flash.display.Bitmap
/***********************************************************************************************************************************************************
* Controller - control of all views
***********************************************************************************************************************************************************/
class Controller
{
private const COLOURS:Array = [0xFF0000, 0xFF9900, 0x0000FF, 0xFFFF00]
private const ZOMBIE_COLOUR:uint = 0x006600
private const ACTIVE_RANGE:int = 10
private const LONG_RANGE:int = 72
private const ADJACENT:int=11
private var _players:Array = []
private var _distances:Array=[]
private var _turn:Array=[{},{},{},{}]
private var _zombies:Array = []
private var _gameboard:GameBoard
private var _message_layer:Sprite
private var _move_panel:MovePanel
private var _turn_timer:TurnTimer
private var _stage:Stage
private var _target_posn:Point=new Point()
private var _bullets:Array = []
private var _test_canvas:Sprite=new Sprite()
public function Controller(stage:Stage,gameboard:GameBoard,message_layer:Sprite,move_panel:MovePanel,turn_timer:TurnTimer):void
{
_gameboard = gameboard
_message_layer = message_layer
_move_panel=move_panel
_turn_timer = turn_timer
_turn_timer.addEventListener(Event.COMPLETE, turnOverHandler)
_stage = stage
for (var i:int = 0; i < 4;i++){_distances[i]=[]}
}
//Add a player to the game board
public function addPlayer(posx:int, posy:int, bmp:Bitmap):void
{
var p:Actor = new Actor(_message_layer, COLOURS[_players.length])
bmp.x = 20;
bmp.y = -20
bmp.width = 40; bmp.height = 40
bmp.rotation=90
p.addChild(bmp)
p.health=20
p.position=new Point(posx,posy)
p.x = GameBoard.GRID_SIZE * posx+GameBoard.GRID_SIZE*0.5//_players.length
p.y = GameBoard.GRID_SIZE * posy+GameBoard.GRID_SIZE*0.5//_players.length
p.rotation=GameMaths.angleToPoint(p.position,new Point())
var b:Sprite = new Sprite()
b.graphics.beginFill(0xAAAAAA, 0.6)
b.graphics.drawCircle(0, 0, 2)
b.graphics.endFill()
b.alpha=0
//_bullets[_players.length] = b
p.bullet=b
_gameboard.addChild(b)
_gameboard.addChild(p)
p.name="player"+_players.length
p.addMessage(p.name)
_players.push(p)
}
//Add a zombie to the game board
public function addZombie(posx:int,posy:int,bmp:Bitmap):void
{
var zombie:Actor = new Actor(_message_layer, ZOMBIE_COLOUR)
bmp.x = 20;
bmp.y = -20
bmp.width = 40; bmp.height = 40
bmp.rotation = 90
trace("bmp="+bmp)
zombie.addChild(bmp)
zombie.position=new Point(posx,posy)
zombie.x = GameBoard.GRID_SIZE * posx+GameBoard.GRID_SIZE*0.5
zombie.y = GameBoard.GRID_SIZE * posy + GameBoard.GRID_SIZE * 0.5
zombie.name="z_"+_zombies.length
_gameboard.addChild(zombie)
_zombies.push(zombie)
//zombie.addMessage("ZOMBIE_" + _zombies.length)
//trace("NUm zombies so far:"+_zombies.length)
}
private function turnOverHandler(event:Event):void
{trace("turnOverHandler")
_move_panel.outOfTime()
_turn[0] = _move_panel.option_selection
calcPlayerDistances()
calcBotMoves()
turnOver()
}
private function calcPlayerDistances():void
{
var i:int;
var j:int
var active_players:int=0
for (i = 0; i < 3; i++)
{
for (j = i+1; j < 4; j++)
{
_distances[i][j] = GameMaths.distanceFromToSquared(_players[i].position, _players[j].position)
_distances[j][i]=_distances[i][j]
}
}
var tgtx:int
var tgty:int
for (i = 0; i < 4; i++)
{
if (_players[i].active)
{
active_players++
var nearest:int = 9999
var furthest:int= -1
for (j = 0; j < 4; j++)
{
if (i != j)
{
if (_distances[i][j] < nearest) { _players[i].nearest = j; nearest = _distances[i][j] }
if (_distances[i][j] > furthest) { _players[i].furthest = j; furthest = _distances[i][j] }
}
}
tgtx += _players[i].position.x//Calc centre point for group - to be used by long range zombies to aim at.
tgty += _players[i].position.y
}
}
if(active_players>0)_target_posn=new Point(Math.round(tgtx/active_players),Math.round(tgty/active_players))
}
private function calcZombieMoves():void
{
var len:int = _zombies.length
var posn:Point
var nearest_inf:Object
var aim_for :Point
var ang:Number
var adj:Boolean
var diffx:int
var diffy:int
var turn:Object
for (var i:int = 0; i < len; i++)
{
if (_zombies[i].active)
{
posn = _zombies[i].position
adj=false
if (posn.x > _target_posn.x - ACTIVE_RANGE && posn.x < _target_posn.x + ACTIVE_RANGE
&& posn.y > _target_posn.y - ACTIVE_RANGE && posn.y < _target_posn.y + ACTIVE_RANGE)
{//ACTIVE
nearest_inf = findNearestPlayer(posn)
//if (nearest_inf.dist < ADJACENT)
diffx = Math.abs(posn.x - _players[nearest_inf.nearest].position.x)
diffy = Math.abs(posn.y - _players[nearest_inf.nearest].position.y)
//trace("ZOMBIE "+i+" DISTANCE " + nearest_inf.dist+" diffs:"+diffx+","+diffy)
if(diffx<=1 && diffy<=1)
{
trace("ZOMBIE "+i+" ADJACENT SO FIGHT nearest:"+nearest_inf.nearest)
aim_for = _players[nearest_inf.nearest].position
_players[nearest_inf.nearest].health--//=i
_players[nearest_inf.nearest].attackedBy=_zombies[i]
_players[nearest_inf.nearest].doBloodSplatter(3, 0.2)
adj=true
}
else
if (nearest_inf > LONG_RANGE)
{//LONG RANGE
aim_for=_target_posn
}
else
{//SHORT RANGE
aim_for=_players[nearest_inf.nearest].position
}
if (adj)
{
//do attack
trace("*****ADJACENT****")
}
ang = Math.round(GameMaths.angleToPoint(_zombies[i].position, aim_for ) / 45) +3//Div by 45 to make out of 8
ang = ang<0?ang+8:ang>8?ang-8:ang
turn = { sel:adj?"FIGHT":"MOVE", dir:ang }
if (spaceEmptyOfCharacters(_zombies[i], turn)){_zombies[i].doTurn(turn)}
else
{
turn.dir = turn.dir-1>=0?turn.dir-1:turn.dir+7
if (spaceEmptyOfCharacters(_zombies[i], turn)) { _zombies[i].doTurn(turn) }
else
{
turn.dir = turn.dir + 2 < 8?turn.dir + 2:turn.dir - 6
if (spaceEmptyOfCharacters(_zombies[i], turn)) { _zombies[i].doTurn(turn) }
}
}
//trace("####::"+_zombies[i].name+" posn="+posn.x+","+posn.y+" grid coords:"+(posn.x + MovePanel.BUTTON_POSITIONS[ang].x)+","+(posn.y + MovePanel.BUTTON_POSITIONS[ang].y)+" butpos:"+MovePanel.BUTTON_POSITIONS[ang].x+","+MovePanel.BUTTON_POSITIONS[ang].y)
}
_gameboard.positionGrid[posn.x ][posn.y ] = _zombies[i]
//_zombies[i].addMessage("Z_" + i)
}
}
}
private function findNearestPlayer(posn:Point):Object
{
var dist:int
var ndist:int=9999
var nearest:int
for (var i:int = 0; i < 4; i++)
{
if (_players[i].active)
{
dist = GameMaths.distanceFromToSquared(posn, _players[i].position)
if (dist < ndist)
{
nearest = i
ndist=dist
}
}
}
return { nearest:nearest, dist:dist }
}
private function calcBotMoves():void
{
//Randomish for now
//Aim for top left. Avoid stepping onto other players.
var dir_to_use:int = 0
var selection:String="MOVE"
var calcx:int
var calcy:int
var hit_obj:Object
for (var i:int = 1; i < 4; i++)
{
dir_to_use = 0
selection="MOVE"
calcx = Math.abs(_players[i].position.x - _target_posn.x)
calcy = Math.abs(_players[i].position.y - _target_posn.y)
//trace(i + "::" + calcx + "," + calcy + " SQD=" + (calcx * calcx + calcy * calcy) + " TGT POS=" + _target_posn)
if (_players[i].attackedBy)
{//Being attacked so shoot
selection = "SHOOT"
dir_to_use = dirToUse(_players[i].position, _players[i].attackedBy.position)
_players[i].attackedBy=null
}
else
if (calcx>2 || calcy>2)
{//Too far from group
dir_to_use = dirToUse(_players[i].position, _target_posn )
}
else
{//Check if zombie in range for shot
for (var k:int = 0; k < 8; k++)
{
hit_obj=shotWillHit(_players[i], { sel:"SHOOT", dir:k})
if (hit_obj.hit && hit_obj.target.name.substr(0,1)=="z")
{
trace(k+"__ shoot at "+hit_obj.target.name)
selection = "SHOOT"
dir_to_use = k
break;
}
else if (hit_obj.hit) { break;}
}
}
trace("{calcBotMoves} i="+i+" sel="+selection+" dir="+dir_to_use+" calcx/y="+calcx+","+calcy)
_turn[i] = { sel:selection, dir:dir_to_use }
if (selection == "MOVE")
{
if (!spaceEmptyOfCharacters(_players[i], _turn[i]))
{
_turn[i].dir = _turn[i].dir - 1 >= 0?_turn[i].dir - 1:_turn[i].dir + 7
if (!spaceEmptyOfCharacters(_players[i], _turn[i]))
{
_turn[i].dir = _turn[i].dir + 2 < 8?_turn[i].dir + 2:_turn[i].dir - 6
}
}
}
}
}
private function dirToUse(player_posn:Point, target:Point):int
{
var dir_to_use:int = 0
dir_to_use = Math.round(GameMaths.angleToPoint(player_posn, target) / 45) +3//Div by 45 to make out of 8
dir_to_use = dir_to_use<0?dir_to_use+8:dir_to_use>8?dir_to_use-8:dir_to_use
return dir_to_use
}
private function spaceEmptyOfCharacters(player:Actor, turn:Object):Boolean
{
if (turn.sel != "MOVE")
{
return true
}
else if(turn.dir>-1)
{
var posx:int = player.position.x + MovePanel.BUTTON_POSITIONS[turn.dir].x
var posy:int = player.position.y + MovePanel.BUTTON_POSITIONS[turn.dir].y
if (posx >= GameBoard.ROWS || posy >= GameBoard.COLS || posx < 0 || posy < 0)
{
return false
}
else
if (_gameboard.positionGrid[posx][posy] && _gameboard.positionGrid[posx][posy].name!=player.name)
{
if (posx == _gameboard.positionGrid[posx][posy].position.x && posy== _gameboard.positionGrid[posx][posy].position.y)
{
//trace(player.name+" AT "+player.position+" CANT GO HERE "+posx+","+posy+" AS OCCUPIED BY "+_gameboard.positionGrid[posx][posy].name+" AT "+_gameboard.positionGrid[posx][posy].position)
return false
}
else
{
//trace("//FALSE READING// "+player.name+" AT "+player.position+" CANT GO HERE "+posx+","+posy+" AS OCCUPIED BY "+_gameboard.positionGrid[posx][posy].name+" AT "+_gameboard.positionGrid[posx][posy].position)
return true
}
}
else return true
}
else return false
}
private function shotWillHit(player:Actor,turn:Object):Object
{
var obj:Object = { }
var posx:int
var posy:int
var dir:Object = MovePanel.BUTTON_POSITIONS[turn.dir]
for (var i:int = 0; i < 6; i++)
{
posx = player.position.x + dir.x * (i + 1)
posy = player.position.y + dir.y * (i + 1)
//trace("bullet path i="+i+" pos="+posx+","+posy)
if (posx >= 0 && posy >= 0 && posx < GameBoard.COLS && posy < GameBoard.ROWS)
{
if (_gameboard.positionGrid[posx][posy])
{
if (_gameboard.positionGrid[posx][posy].active)
{
obj.hit=true
obj.target = _gameboard.positionGrid[posx][posy]
obj.position = obj.target.position
obj.dist = i
break;
}
}
}
}
if (!obj.hit)
{
obj.hit = false
obj.position = { x:player.position.x + dir.x * 6, y:player.position.y + dir.y * 6 }
obj.dist = 6
}
return obj
}
public function turnOver():void
{
//DO MOVE
var i:int
for (i = 0; i < 4; i++)
{
if (_players[i].active)
{
if (_turn[i].sel == "MOVE")
{
_gameboard.positionGrid[_players[i].position.x][_players[i].position.y]=null//Remove player from board
if (spaceEmptyOfCharacters(_players[i], _turn[i])) _players[i].doTurn(_turn[i])//Do turn
_gameboard.positionGrid[_players[i].position.x][_players[i].position.y] = _players[i]//Put player back on board
}
else
if (_turn[i].sel == "SHOOT" && _turn[i].dir>-1)
{
var shot:Object = shotWillHit(_players[i], _turn[i])
if (shot.hit)
{
trace("-------------BANG!-------------" + shot.position)
shot.target.health--
shot.target.doBloodSplatter(_turn[i].dir, shot.dist * 0.2)
if (!shot.target.active)
{
_gameboard.positionGrid[shot.position.x][shot.position.y]=null
Tweener.addTween(shot.target,{alpha:0,delay:shot.dist * 0.2,time:1.5})
}
}
else
{
trace("-------------BANG! MISSED-------------"+shot.position)
}
_players[i].bullet.alpha = 0.6
_players[i].bullet.x = _players[i].x
_players[i].bullet.y = _players[i].y
Tweener.addTween(_players[i].bullet, { x:(shot.position.x+0.5) * GameBoard.GRID_SIZE, y:(shot.position.y+0.5) * GameBoard.GRID_SIZE, time:shot.dist * 0.2, transition:"Linear" } )
Tweener.addTween(_players[i].bullet, { alpha:0, delay:shot.dist * 0.2, time:0.1 } )
_players[i].doTurn(_turn[i])
}
}
}
_gameboard.clearPositionGrid()
for (i = 0; i < 4; i++) { if (_players[i].active)_gameboard.positionGrid[_players[i].position.x][_players[i].position.y] = _players[i] }
calcZombieMoves()
//PLAYER HEALTH CHECK
for (i = 0; i < 4; i++)
{
if (!_players[i].active && _players[i].parent)
{
_players[i].parent.removeChild(_players[i])
_gameboard.positionGrid[_players[i].position.x][_players[i].position.y]=null
}
}
if (_turn_timer.parent)_turn_timer.parent.removeChild(_turn_timer)
Tweener.addTween(_stage,{time:3,onComplete:update})
Tweener.addTween(_stage,{time:5,onComplete:startNextTurn})
}
public function startNextTurn():void
{
_turn_timer.startTimer()
_move_panel.startPanel()
_stage.addChild(_turn_timer)
}
public function update():void
{
_gameboard.centrePlayerPiece(_players[0])
}
}
/***********************************************************************************************************************************************************
* Actor - Class to contain actor view
***********************************************************************************************************************************************************/
class Actor extends Sprite
{
private var _holder:Sprite = new Sprite()
private var _bubble:Sprite = new Sprite()
private var _bubble_bg:Sprite = new Sprite()
private var _bullet:Sprite
private var _tf:TextField = new TextField()
private var _position:Point = new Point()
private var _nearest:int
private var _furthest:int
private var _close_fighting:int = -1
private var _health:int = 1
private var _active:Boolean = true
private var _blood_splatter:Array = []
private var _attacked_by:Actor
public function Actor(message_layer:Sprite, colour:uint=0xFFFF00):void
{
var gsize:int=GameBoard.GRID_SIZE
//_holder.graphics.lineStyle(6, colour)
//_holder.graphics.drawCircle(gsize * 0.5, gsize * 0.5, gsize * 0.3)
//_holder.graphics.drawRoundRect(gsize * 0.4, gsize * 0.1, gsize * 0.2, gsize * 0.8, 5, 5)
//_holder.x = _holder.y = -gsize * 0.5
//addChild(_holder)
message_layer.addChild(_bubble)
//Set up textfield
_tf.textColor=0x000000
_tf.selectable=false
_tf.x = gsize+3
_tf.y = -gsize * 0.2
_bubble.addChild(_bubble_bg)//Add background container for bubble
}
//Add a message to speech bubble
public function addMessage(msg:String):void
{
var gsize:int = GameBoard.GRID_SIZE
_bubble.x = this.x-gsize*0.5
_bubble.y = this.y-gsize*0.5
trace("___"+_bubble.x+","+_bubble.y)
_bubble.addChild(_tf)
_tf.text = msg//Add message
Tweener.removeTweens(_bubble) //1st remove current tweens on this bubble
Tweener.addTween(_bubble, { alpha:1, time:0.5 } ) //Tween on
Tweener.addTween(_bubble, { alpha:0, delay:3, time:0.5, onComplete:removeTextFromBubble } )//Tween off after delay
//Draw bubble to correct size
_bubble_bg.graphics.clear()
_bubble_bg.graphics.lineStyle(2, 0xFFFFFF)
_bubble_bg.graphics.beginFill(0xDDDDDD,0.7)
_bubble_bg.graphics.drawRoundRectComplex(gsize,-gsize*0.2,_tf.textWidth+10,gsize*0.5,10,10,1,10)
}
//Needed to get rid of text - can't be bothered dealing with embedding text, etc at this stage.
private function removeTextFromBubble():void { _bubble.removeChild(_tf); }
public function get active():Boolean { return _active }
public function set health(val:int):void { _health = val;_active=_health>0?true:false }
public function get health():int { return _health }
public function set bullet(b:Sprite):void { _bullet = b }
public function get bullet():Sprite { return _bullet }
public function set position(pt:Point):void { _position = pt }
public function get position():Point { return _position }
public function set furthest(val:int):void { _furthest = val}
public function get furthest():int { return _furthest }
public function set nearest(val:int):void { _nearest = val}
public function get nearest():int { return _nearest }
public function set fighting(val:int):void { _close_fighting = val}
public function get fighting():int { return _close_fighting }
public function set attackedBy(attacker:Actor):void { _attacked_by = attacker}
public function get attackedBy():Actor { return _attacked_by }
public function doTurn(turnObj:Object):void
{
//trace("[Actor] - doTurn turnObj.sel="+turnObj.sel+" dir="+turnObj.dir)
if (turnObj.sel == "MOVE" && turnObj.dir >= 0) { moveActor(turnObj.dir) }
else if (turnObj.sel == "FIGHT") fightActor()
else if(turnObj.sel=="SHOOT") rotateActor(MovePanel.BUTTON_POSITIONS[turnObj.dir].rot-90)
}
public function rotateActor(rotate:Number):void
{
Tweener.addTween(this,{rotation:rotate, time:0.3})
}
private function fightActor():void
{
trace("FIGHT"+this.rotation)
var orig_rot:Number=this.rotation
Tweener.addTween(this, { rotation:orig_rot - 60, time:0.2 } )
Tweener.addTween(this, { rotation:orig_rot, delay:0.2,time:2, transition:"easeOutElastic"})
}
public function moveActor(dir_index:int):void
{
if (_close_fighting == -1)
{
var move_obj:Object = MovePanel.BUTTON_POSITIONS[dir_index]
rotateActor(move_obj.rot - 90)
Tweener.addTween(this, { x:this.x + move_obj.x * GameBoard.GRID_SIZE, y:this.y + move_obj.y * GameBoard.GRID_SIZE, delay:1, time:3 } )
_position.x += move_obj.x
_position.y += move_obj.y
}
}
public function doBloodSplatter(hit_from:int, delay:Number=0):void
{
var splatter_dir:int = hit_from - 4 < 0?hit_from + 4:hit_from - 4//Opposite direction for splatter
var dir_obj:Object=MovePanel.BUTTON_POSITIONS[splatter_dir]
if (!_blood_splatter[splatter_dir]) _blood_splatter[splatter_dir] = new Sprite()
//_blood_splatter[splatter_dir].x = dir_obj.x * GameBoard.GRID_SIZE * 0.3
//_blood_splatter[splatter_dir].y = dir_obj.y * GameBoard.GRID_SIZE * 0.3
_blood_splatter[splatter_dir].alpha=0
addChild(_blood_splatter[splatter_dir])
bloodSplatter(_blood_splatter[splatter_dir], 20)
Tweener.addTween(_blood_splatter[splatter_dir],{alpha:1,delay:delay})
Tweener.addTween(_blood_splatter[splatter_dir],{alpha:0,delay:delay,time:1.5,transition:"Linear"})
}
private function bloodSplatter(container:Sprite,radius:Number):void
{
var diameter:Number=radius*2
container.graphics.clear()
container.graphics.beginFill(0xFF0000,0.8)
container.graphics.drawRoundRectComplex(-radius, -radius, diameter, diameter, radius-diameter*Math.random(), radius*2-diameter*2*Math.random(), radius-diameter*Math.random(), radius*2-diameter*Math.random())
container.graphics.endFill()
container.rotation = Math.random() * 360
container.width = radius + radius * Math.random()
container.height = radius+radius*Math.random()
}
}
/***********************************************************************************************************************************************************
* GameBoard - class to contain gameboard view
***********************************************************************************************************************************************************/
class GameBoard extends Sprite
{
private var _holder:Sprite = new Sprite()
public static const GRID_SIZE:int = 40
public static const COLS:int = 32
public static const ROWS:int = 32
public static const SCREENW:int = 480
public static const SCREENH:int = 480
private var _pos_grid:Array
private var _blank_grid:Array
public function GameBoard(terrain:Sprite):void
{
addChild(terrain)
_holder.graphics.lineStyle(4, 0x000000)
_holder.graphics.beginFill(0x666666,0.5)
_holder.graphics.drawRect(0, 0, ROWS * GRID_SIZE, COLS * GRID_SIZE)
_holder.graphics.endFill()
for (var i:int = 0; i < ROWS; i++)
{
for (var j:int = 0; j < COLS; j++)
{
_holder.graphics.lineStyle(1, 0x333333)
_holder.graphics.drawRect(i*GRID_SIZE,j*GRID_SIZE, GRID_SIZE,GRID_SIZE)
}
}
addChild(_holder)
initPositionGrid()
}
private function initPositionGrid():void
{
var r:Array = []
for (var i:int = 0; i < COLS; i++)
{
r[i]=new Array(ROWS)
}
_blank_grid = r
clearPositionGrid()
}
public function clearPositionGrid():void { _pos_grid = _blank_grid.concat() }
public function get positionGrid():Array { return _pos_grid }
//Move player piece on game board to centre of screen
public function centrePlayerPiece(p:Actor):void
{
Tweener.addTween(this,{x:SCREENW * 0.5 - p.x+GRID_SIZE*0.5, y:SCREENH * 0.5 - p.y+GRID_SIZE*0.5,time:1})
}
}
/***********************************************************************************************************************************************************
* TurnTimer - class to run & display timer
***********************************************************************************************************************************************************/
class TurnTimer extends Sprite
{
private var _tf:TextField = new TextField()
private var _colour_block:Sprite=new Sprite()
public function TurnTimer():void
{
addChild(_colour_block)
_colour_block.graphics.beginFill(0xFF0000)
_colour_block.graphics.drawRect(2, 1, 100, 6)
addChild(_colour_block)
_tf.x = 5
_tf.y = 8
_tf.textColor=0xEEEEEE
addChild(_tf)
addMessage("ENTER TURN")
var brder:Sprite = new Sprite()
addChild(brder)
brder.graphics.lineStyle(2, 0x003300)
brder.graphics.drawRoundRect(0, 0, 102, 8, 5, 5)
//startTimer()
}
public function addMessage(msg:String):void
{
_tf.text=msg
}
public function startTimer():void
{
Tweener.removeTweens(_colour_block)
Tweener.addTween(_colour_block, { width:1, time:5, transition:"Linear", onComplete:timesUp } )
}
private function timesUp():void
{
_colour_block.width = 100
dispatchEvent(new Event(Event.COMPLETE))
//startTimer()
}
}
/***********************************************************************************************************************************************************
* MovePanel - panel containing movement buttons
***********************************************************************************************************************************************************/
class MovePanel extends Sprite
{
private var _button_array:Array = []
public static const BUTTON_POSITIONS:Array = [ { x:-1, y:-1, rot: -45 }, { x:0, y:-1, rot:0 }, { x:1, y:-1, rot:45 }, { x:1, y:0, rot:90 }, { x:1, y:1, rot:135 }, { x:0, y:1, rot:180 }, { x:-1, y:1, rot: -135 }, { x:-1, y:0, rot: -90 } ]
private var _directions:Sprite = new Sprite()
private var _buttons:Sprite = new Sprite()
private var _selection:Object={}
public function MovePanel():void
{
var unit:Number = GameBoard.GRID_SIZE * 0.5
var b1:Button = new Button("MOVE", "rectangle")
b1.x=-5
_buttons.addChild(b1)
var b2:Button = new Button("SHOOT", "rectangle")
b2.x=-5
b2.y = 25
_buttons.addChild(b2)
b1.addEventListener(MouseEvent.CLICK, buttonClickedHandler)
b2.addEventListener(MouseEvent.CLICK,buttonClickedHandler)
addChild(_buttons)
for (var i:int = 0; i < 8; i++)
{
var b:Button = new Button("b" + i, "triangle",8)
b.setPosition(BUTTON_POSITIONS[i].x * unit, BUTTON_POSITIONS[i].y * unit, BUTTON_POSITIONS[i].rot)
b.extra=i
_button_array.push(b)
_directions.addChild(b)
b.addEventListener(MouseEvent.CLICK, directionClickedHandler)
}
_directions.x = _directions.y=unit
}
public function outOfTime():void
{
if (_buttons.parent) removeChild(_buttons)
if(_directions.parent) removeChild(_directions)
}
public function startPanel():void
{
_selection = {dir:-1 }
addChild(_buttons)
}
private function buttonClickedHandler(event:MouseEvent):void
{
_selection.sel = event.target.name
trace(event.target.name)
removeChild(_buttons)
addChild(_directions)
}
private function directionClickedHandler(event:MouseEvent):void
{
trace("directionClickedHandler dir="+event.target.extra)
_selection.dir = event.target.extra
removeChild(_directions)
}
public function timeStarted():void { _selection = { }}
public function get option_selection():Object{return _selection}
}
/***********************************************************************************************************************************************************
* Button - generic button class - triangle or rectangle
***********************************************************************************************************************************************************/
class Button extends Sprite
{
private var _alpha:Number = 0.5
private var _extra:Object={}
public function Button(id:String, type:String, size:int=6,bg_colour:uint=0x0000FF,br_colour:uint=0x000099):void
{
this.name=id
this.graphics.beginFill(bg_colour, 1)
this.graphics.lineStyle(2,br_colour)
switch(type)
{
case "triangle":
this.graphics.moveTo(0, -size)
this.graphics.lineTo(size, size)
this.graphics.lineTo( -size, size)
this.graphics.lineTo(0, -size)
break;
case "rectangle":
this.graphics.drawRoundRect(0, 0, 50, 20, 5, 5)
var tf:TextField = new TextField()
tf.x = 2; tf.y = 2;
tf.textColor=0xFFFFFF
tf.text = id
tf.selectable = false
tf.mouseEnabled=false
addChild(tf)
_alpha=0.8
break;
}
this.graphics.endFill()
this.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler)
this.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler)
//this.addEventListener(MouseEvent.CLICK, mouseClickHandler)
this.useHandCursor = true
this.buttonMode = true
this.alpha=_alpha
}
private function mouseOverHandler(event:MouseEvent):void { this.alpha = 1 }
private function mouseOutHandler(event:MouseEvent):void { this.alpha = _alpha }
private function mouseClickHandler(event:MouseEvent):void { dispatchEvent(event) }
public function setPosition(posx:Number, posy:Number, rot:Number=9999):void
{
this.x = posx
this.y = posy
if(rot!=9999)this.rotation=rot
}
public function set extra(obj:Object):void { _extra = obj }
public function get extra():Object { return _extra }
}
/*
class CommsInterface extends EventDispatcher
{
private var _player_moves:Array=[]
public function CommsInterface():void
{
}
public function prepareToReceiveMoves():void
{
_player_moves=[]
}
//Player moves convert to... F is fire, M is move. 0-7 are directions
public function receivePlayerMove(player_num:int,obj:Object):void
{
var str:String="N"
if (obj.sel)
{
if (obj.sel == "MOVE") str = "M"
else str = "F"
if (obj.dir)
{
str+=String(obj.dir+1)
}
}
_player_moves[player_num]=str
}
}
*/
class GameMaths extends EventDispatcher
{
public function GameMaths():void {}
public static function angleToPoint(from:Point, to:Point):Number
{
var dx:Number = to.x - from.x
var dy:Number = to.y - from.y
return Math.atan2(dy,dx) *57.29577951308232 // 180/Math.PI=57.29577951308232
}
public static function distanceFromToSquared(from:Point, to:Point):Number
{
var dx:Number = from.x - to.x
var dy:Number = from.y - to.y
return dx*dx+dy*dy
}
}