/** * ... * @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 } } Left 2 Die - Zombie Mayhem (Single player version)