Creation of Flash game Space Checkers – Step 3
Continuing with the creation of Space Checkers game, we are going to let monsters be eaten and removed from the board after a successful move. It’s a very important step because removing monsters from the board allows players to solve levels and progress through the game.
Starting with some theory, once the player picks a monster, the game highlights the possible moves, if any, as seen in step 2. We also need to store such possible moves somewhere, so I created a vector of points to store possible moves.
Once the player picks a monster, the vector is populated with possible moves, and once the monster is released somewhere in the board, I just need to check for the tile the monster landed on to be one in the vector of possible moves.
Then, since at each successful move a monster is eaten and must be removed from the board, we need to know which monster has to be removed. This is not a big problem, since we know the player just performed a successful move, we just need to know the direction the player moved the monster, and remove the monster which lies in the adjacent tile in the opposite side of the direction the player just moved.
A real world example: if the player moved the monster to the right, the monster to remove is the monster to the left of the tile where the moved monster landed.
Here is the source code:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
package { import flash.display.Sprite; import flash.events.MouseEvent; import flash.geom.Point; public class Main extends Sprite { private var fieldArray:Array; private var pickedMonster:Monster; private var monsterContainer:Sprite=new Sprite(); private var moveContainer:Sprite=new Sprite(); private var localX:Number; private var localY:Number; private var oldX:Number; private var oldY:Number; private var possibleLandings:Vector.<Point>; public function Main() { setupLevel(); } private function setupLevel():void { var squareContainer:Sprite=new Sprite(); addChild(squareContainer); addChild(moveContainer); addChild(monsterContainer); var square:Square; var monster:Monster; fieldArray = [[0,0,1,0,0,0],[1,1,0,1,1,0],[0,0,0,0,0,0]]; for (var i:int=0; i<fieldArray.length; i++) { for (var j:int=0; j<fieldArray[i].length; j++) { square=new Square(); squareContainer.addChild(square); square.x = j * 60; square.y = i * 60; if (fieldArray[i][j] == 1) { monster=new Monster(); monsterContainer.addChild(monster); monster.x = j * 60; monster.y = i * 60; monster.theRow = i; monster.theCol = j; monster.buttonMode = true; monster.addEventListener(MouseEvent.MOUSE_DOWN,pickMonster); } } } squareContainer.x=(stage.stageWidth-squareContainer.width)/2; squareContainer.y=(stage.stageHeight-squareContainer.height)/2; monsterContainer.x = squareContainer.x; monsterContainer.y = squareContainer.y; moveContainer.x = squareContainer.x; moveContainer.y = squareContainer.y; } private function pickMonster(e:MouseEvent):void { localX = e.localX; localY = e.localY; pickedMonster = e.target as Monster; oldX = pickedMonster.x; oldY = pickedMonster.y; checkMonster(pickedMonster); monsterContainer.setChildIndex(pickedMonster,monsterContainer.numChildren-1); stage.addEventListener(MouseEvent.MOUSE_MOVE,moveMonster); stage.addEventListener(MouseEvent.MOUSE_UP,dropMonster); } private function moveMonster(e:MouseEvent):void { pickedMonster.x = mouseX - monsterContainer.x - localX; pickedMonster.y = mouseY - monsterContainer.y - localY; } private function dropMonster(e:MouseEvent):void { var legalMove:Boolean = false; stage.removeEventListener(MouseEvent.MOUSE_MOVE,moveMonster); stage.removeEventListener(MouseEvent.MOUSE_UP,dropMonster); var dropX:int=Math.floor((pickedMonster.x+30)/60); var dropY:int=Math.floor((pickedMonster.y+30)/60); for (var i:int=0; i<possibleLandings.length; i++) { if (possibleLandings[i].x == dropY && possibleLandings[i].y == dropX) { legalMove = true; break; } } if (! legalMove) { pickedMonster.x = oldX; pickedMonster.y = oldY; } else { var rowOffset:int = (dropY - pickedMonster.theRow) / 2; var colOffset:int = (dropX - pickedMonster.theCol) / 2; fieldArray[pickedMonster.theRow][pickedMonster.theCol] = 0; fieldArray[pickedMonster.theRow + rowOffset][pickedMonster.theCol + colOffset] = 0; fieldArray[pickedMonster.theRow + 2 * rowOffset][pickedMonster.theCol + 2 * colOffset] = 1; for (i=0; i<monsterContainer.numChildren; i++) { var currentMonster:Monster = monsterContainer.getChildAt(i) as Monster; if (currentMonster.theRow == pickedMonster.theRow + rowOffset && currentMonster.theCol == pickedMonster.theCol + colOffset) { monsterContainer.removeChildAt(i); } } pickedMonster.x = dropX * 60; pickedMonster.y = dropY * 60; pickedMonster.theRow = dropY; pickedMonster.theCol = dropX; } i = moveContainer.numChildren; while (i--) { moveContainer.removeChildAt(i); } } private function checkMonster(m:Monster):void { var possibleMove:PossibleMove; possibleLandings=new Vector.<Point>(); for (var i:int=0; i<4; i++) { var deltaRow:int=(1-i)*(i%2-1); var deltaCol:int = (2 - i) * (i % 2); if (checkField(m,deltaRow,deltaCol)) { possibleMove=new PossibleMove(); moveContainer.addChild(possibleMove); possibleMove.x = oldX + 120 * deltaCol; possibleMove.y = oldY + 120 * deltaRow; possibleLandings.push(new Point(m.theRow+2*deltaRow,m.theCol+2*deltaCol)); } } if (possibleLandings.length > 0) { var startMove:StartMove=new StartMove(); moveContainer.addChild(startMove); startMove.x = oldX; startMove.y = oldY; } else { var wrongMove:WrongMove=new WrongMove(); moveContainer.addChild(wrongMove); wrongMove.x = oldX; wrongMove.y = oldY; } } private function checkField(m:Monster,rowOffset:int,colOffset:int):Boolean { if (fieldArray[m.theRow + 2 * rowOffset] != undefined && fieldArray[m.theRow + 2 * rowOffset][m.theCol + 2 * colOffset] != undefined) { if (fieldArray[m.theRow + rowOffset][m.theCol + colOffset] == 1 && fieldArray[m.theRow + 2 * rowOffset][m.theCol + 2 * colOffset] == 0) { return true; } } return false; } } } |
Line 14: possibleLandings is the vector of points used to store possible landing tiles
Lines 104-130: I modified a bit checkMonster function to make it shorter. It works the same way, just look how I push possible moves into possibleLandings vector at line 115.
Lines 72-77: Checking if the current landing tile is inside possibleLandings vector. Look at line 73: unfortunately I could not use indexOf method as it does not work with variable passed by reference.
Lines 79-81: This is the old code to place the monster in its starting position if the move is not allowed.
Lines 82-98: code to execute if the move is allowed: monster position and properties are updated, as well as fieldArray values, then I determine the direction the monster moved, and remove the killed monster (lines 88-93).
And this is the result:
Now you can remove monsters by jumping over them. Next time we’ll see how to progress through levels.
They can be easily customized to meet the unique requirements of your project.












This post has 4 comments
Tompa
Very nice!
Found one “bug” tho, if you hold one of the monsters and then rightclick,
your monster will be placed where you pointer is when you leftclick your mouse again.
Creation of Flash game Space Checkers – Step 3 – Emanuele Feronato « eaflash
[...] on http://www.emanueleferonato.com Share this:TwitterFacebookLike this:LikeBe the first to like [...]
veeramani
Nice!!!
Thanks for helping me….
tons of thanks
Rennan
Hi, Emanuele!
First of all, thank you for sharing with us your knowledge. I can´t wait to see the next step of Space Checkers Tutorial.