package Checkers { import flash.text.TextField; import flash.display.MovieClip; import flash.display.Sprite; import flash.geom.Point; import flash.system.ApplicationDomain; import de.polygonal.ds.Array2; import flash.text.TextField; import gs.TweenLite; import fl.motion.easing.*; /** * Game Controller * This is the controller that starts, runs the game its its required mode * Referee is initiated here, one Referee in one client * this is the View class as well just to reduce classes involved * Bt default it is single player game * @author Fan Di */ public class Game extends Sprite implements IGameView { private var counter:Object = { x:0 }; public var multiplayer:Boolean = false; public var state:String = "stopped"; private var playerColor:String = "B"; private var referee:RefereeAbstract; private var playerR:ISymPlayer; private var playerB:ISymPlayer; private var gameState:Array2; private var gameBoard:GameBoard; private var messageBox:*; private var messageBoxes:Array; private var aiLoop:int = 0; private var scoreFieldR:TextField; private var mvR:MovieClip; private var scoreFieldB:TextField; private var mvB:MovieClip; /* * Constructor inits everything */ public function Game(mode:Boolean = false) { multiplayer = mode; referee = new CheckersReferee(playerColor); gameState = referee.state; playerR = new SymPlayer(referee, this); playerB = new SymPlayer(referee, this); messageBoxes = new Array(); addChildren(); draw(); setupEvents(); } /* * OnGameObject * Object received from server */ public function onGameObject(move:Object):void { trace("[Checkers Game] onGameObject " + move.fromx + "|" + move.fromy + "|" + move.tox + "|" + move.toy); makeMove(move.fromx, move.fromy, move.tox, move.toy); } /* * Starts the game, and basically you can now make a move * TODO If statements can be cleaned up after game is completed */ public function startGame(isHost:Boolean):void { reset(); if (multiplayer) { if(!isHost) { playerColor = "R"; referee.turn = "B"; state = "waiting"; gameBoard.mode = false; showMessage("PleaseWaitBox"); playerR.addEventListener(CheckersEvent.SEND_GAME_OBJECT, dispatchEvent); } else { playerColor = "B"; referee.turn = playerColor; state = "myturn"; gameBoard.mode = true; aiLoop = 0; showMessage("YourTurnBox"); playerB.addEventListener(CheckersEvent.SEND_GAME_OBJECT, dispatchEvent); } } else { playerColor = "B"; referee.turn = playerColor; state = "myturn"; gameBoard.mode = true; aiLoop = 0; showMessage("YourTurnBox"); } } public function loadData(isHost:Boolean, isMultiplayer:Boolean, username:String, opponent:String):void { multiplayer = isMultiplayer; var playerNameField:TextField = gameBoard.getChildByName("redplayername") as TextField; if(isHost) { playerNameField.text = opponent; } else { playerNameField.text = username; } playerNameField = gameBoard.getChildByName("blackplayername") as TextField; if(isHost) { playerNameField.text = username; } else { playerNameField.text = opponent; } } public function updateLives():void { var countR:int = 0; var countB:int = 0; var c:String; for (var i:int = 0; i < 8; i++) { for (var j:int = 0; j < 8; j++) { c = gameState.get(i, j).color; if (c == "B") { countB++; } else if (c == "R") { countR++; } } } scoreFieldR.text = String(countR); mvR.gotoAndStop((12 - countB + 1)); scoreFieldB.text = String(countB); mvB.gotoAndStop((12 - countR + 1)); } /* * Resets Everything */ private function reset():void { playerB.removeEventListener(CheckersEvent.SEND_GAME_OBJECT, dispatchEvent); playerR.removeEventListener(CheckersEvent.SEND_GAME_OBJECT, dispatchEvent); referee.reset(); draw(); } /* * Calculates a possible solution move for computer * just do stupid AI * Example of a how to make a move * cx and cy could be a result of which square you pressed on screen * and it represent the grid, look at CheckersReferee for an idea of the square * * You can move left/right, up/down 1 space, or eat enemy diagnally * if you eat, u can continue to eat again until u can't eat anymore * u can't move and continue to eat or vice versa * TODO */ private function computerMove():void { trace("[Game] On Computer Move..."); // Delaying the computer move to later showMessage("PlayerMoveBox", false); aiLoop++; if (aiLoop > 1) { // hopefully this will never happen showMessage("ComputerBrainDead"); referee.changeTurn(); } else { TweenLite.killDelayedCallsTo(aiMove); TweenLite.delayedCall(0.5, aiMove); //TweenLite.to(counter, 0.5, { x:1, onComplete:aiMove } ); } } private function aiMove():void { //Calculate here for Computer!! var move:Object = referee.hint(); makeMove(move.fromx, move.fromy, move.tox, move.toy) } /* * Makes the Move from Location to Location * From Coordinate must represent a Piece on board, and to must be a valid position */ private function makeMove(fromx:int, fromy:int, tox:int, toy:int):void { var move:Object = {fromx:fromx, fromy:fromy, tox:tox, toy:toy, eat:false}; move.color = referee.turn; trace("[Game] Move Selected: " + " from " + move.fromx + "|" + move.fromy + " to " + move.tox + "|" + move.toy); if (referee.validate(move)) { trace("[Game] Move Made by " + move.color); if(move.color == "B") { playerB.makeMove(move); } else { playerR.makeMove(move); } } else { // If current is computer keep trying if (state == "computer" && !multiplayer) { computerMove(); } else if (state == "myturn") { showMessage("InvalidMoveBox"); } drawsBoard(); } } private function showMessage(message:String, hide:Boolean = true):void { if (messageBox) { TweenLite.killTweensOf(messageBox); removeChild(messageBox); messageBox = null; } if (!messageBoxes[message]) { trace("New BOXX CREATED"); messageBoxes[message] = getClassObject(message); } messageBox = messageBoxes[message]; trace("[Game] MESSAGEBOX: " + message + " is instantiated as " + messageBox); messageBox.scaleX = messageBox.scaleY = messageBox.alpha = 1 addChild(messageBox); messageBox.mouseChildren = false; messageBox.mouseEnabled = false; messageBox.x = 0; messageBox.y = this.height/2 + messageBox.height/2; if(hide) { TweenLite.from(messageBox, 0.2, { scaleX:0.5, x:messageBox.x - messageBox.width / 4, ease:Elastic.easeOut, onComplete:hideMessage } ); } } private function hideMessage(delay:Number = 0.5, caller:Function = null, callerparams:Array = null):void { if (messageBox) { if(caller != null) { TweenLite.to(messageBox, 0.2, { delay:delay, alpha:0, onComplete:caller, onCompleteParams:callerparams } ); } else { TweenLite.to(messageBox, 0.2, { delay:delay, alpha:0 } ); } } } private function onMovePiece(evt:CheckerEvent):void { trace("[Game] On Player move"); showMessage("PleaseWaitBox", false); var startPoint:Point = evt.data.startPoint; var endPoint:Point = evt.data.endPoint; //trace(startPoint.x + "|" + startPoint.y); //trace(endPoint.x + "|" + endPoint.y); makeMove(startPoint.x, startPoint.y, endPoint.x, endPoint.y); } /* * This draws the display from reading gameState * TODO */ private function drawsBoard():void { gameBoard.x = 60; gameBoard.y = -2; gameBoard.draw(gameState); } /* * Adds any events here, mouse, keyboard etc * TODO */ public function setupEvents():void { referee.addEventListener(CheckerEvent.WIN, onWin); referee.addEventListener(CheckerEvent.TURN_COMPLETE, onTurnComplete); gameBoard.addEventListener(CheckerEvent.MOVE_PIECE, onMovePiece); } /** * On Turn Complete * @param evt * TODO If statements can be cleaned up after game is completed */ private function onTurnComplete(evt:CheckerEvent):void { if (multiplayer) { if (referee.turn == playerColor) { hideMessage(0.5, showMessage, ["YourTurnBox"]); state = "myturn"; gameBoard.mode = true; } else { state = "otherplayer"; gameBoard.mode = false; } } else { if (referee.turn == playerColor) { hideMessage(0.5, showMessage, ["YourTurnBox"]); state = "myturn"; gameBoard.mode = true; } else { TweenLite.killDelayedCallsTo(nextComputerTurn); TweenLite.delayedCall(1, nextComputerTurn); //TweenLite.to(counter, 1, { x:1, onComplete:nextComputerTurn } ); } } } private function nextComputerTurn():void { hideMessage(0); state = "computer"; gameBoard.mode = false; aiLoop = 0; computerMove(); } /* * Adds any events here, mouse, keyboard etc * TODO */ private function onWin(evt:CheckerEvent):void { trace("Somebody WON"); var data:Object = evt.data; var winner:String = data.color; //check if winner is "R" or "B" and check which player is the right one and display the //right message gameBoard.mode = false; state = "stopped"; if(winner == playerColor) { showMessage("GameOverBox", false); } else { showMessage("YouLoseBox", false); } } /* * Adds all the elements * TODO */ public function addChildren():void { createBoard(); scoreFieldR = gameBoard.getChildByName("redlives") as TextField; mvR = gameBoard.getChildByName("redLine") as MovieClip; scoreFieldB = gameBoard.getChildByName("blacklives") as TextField; mvB = gameBoard.getChildByName("blackLine") as MovieClip; } public function createBoard():void { trace(referee); gameBoard = new GameBoard(referee); addChild(gameBoard); } /* * Positions all the elements on screen * TODO */ public function draw():void { if (gameState) { drawsBoard(); updateLives(); } } /* * Update function to update what is visible * state:Object depends on the game */ public function updateView(state:Array2):void { gameState = state; draw(); } public function getClassObject(className:String):* { var v:Class = ApplicationDomain.currentDomain.getDefinition(className) as Class; return new v(); } } }