Dungeon Raid iPhone game engine made with Flash and AS3
An iPhone game which I enjoyed a lot last year, a great twist in the “match three” genre, was Dungeon Raid.
Tracing a path and matching tiles you will be able to collect treasures, buy and upgrade weapons and defeat monsters.
In this post I am going to cover the part which traces a path along tiles. While it may seem easy, there are a couple of interesting things to consider:
1) Your path can be traced in diagonal, and this means you have to define hot spots on the tiles which must be smaller than the tile itself, or you surely touch adjacent horizontal and vertical tiles before you touch diagonal ones.
2) You can backtrack through the path, but you can’t walk over already other previously selected tiles. This will require a vector to be used as a stack to manage backtracking.
I made a fully commented script, where Tile and Path are the two movieclips representing respectively the tile (frame 1: unselected, frame 2: selected) and the path (frame 1 to 8: west, north-west, north, north-east and so on in clockwise order).
The darker circle inside tiles is the hot spot.
|
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 |
package { import flash.display.Sprite; import flash.events.MouseEvent; import flash.geom.Point; public class Main extends Sprite { private var fieldWidth:int=8;// field width, in tiles private var fieldHeight:int=6;// field height, in tiles private var tileSize:int=80;// tile size, in pixels private var tileVector:Vector.<Object>; private var visitedVector:Vector.<Point>;// vector to store all visited tiles, as Point as it's easy to store x and y coordinate public function Main() { // adding tiles on stage and initializing tile vector tileVector=new Vector.<Object>(); for (var i:int=0; i<fieldWidth; i++) { tileVector[i]=new Vector.<Object>(); for (var j:int=0; j<fieldHeight; j++) { // each tile is an object var tileObject:Object=new Object(); tileObject.taken=false; tileObject.tile=new Tile(); tileObject.tile.x=i*tileSize; tileObject.tile.y=j*tileSize; tileObject.tile.gotoAndStop(1); addChild(tileObject.tile); tileObject.path=null; tileVector[i][j]=tileObject; } } // trigger mouse down to catch starting tile stage.addEventListener(MouseEvent.MOUSE_DOWN,startDrawing); } private function startDrawing(e:MouseEvent):void { // getting starting tile var i:int=Math.floor(mouseX/tileSize); var j:int=Math.floor(mouseY/tileSize); // initializing and pushing tile into the vector visitedVector=new Vector.<Point>(); visitedVector.push(new Point(i,j)); // highlighting the tile and setting it as "taken"; tileVector[i][j].tile.gotoAndStop(2); tileVector[i][j].taken=true; // updating listeners, removing mouse down, adding mouse move and mouse up; stage.removeEventListener(MouseEvent.MOUSE_DOWN,startDrawing); stage.addEventListener(MouseEvent.MOUSE_MOVE,drawing); stage.addEventListener(MouseEvent.MOUSE_UP,stopDrawing); } private function drawing(e:MouseEvent):void { // getting tile var i:int=Math.floor(mouseX/tileSize); var j:int=Math.floor(mouseY/tileSize); // checking if we are inside the sensible area var distX:Number=mouseX-(i*tileSize+tileSize/2); var distY:Number=mouseY-(j*tileSize+tileSize/2); // 1225 is 35^2, where 35 is the radius of the sensible area if (distX*distX+distY*distY<1225) { // now checking if we moved from the last tile visited if (i!=visitedVector[visitedVector.length-1].x || j!=visitedVector[visitedVector.length-1].y) { // now, let's see if we moved to an adjacent tile. we don't want the player to jump here and there if (Math.abs(i-visitedVector[visitedVector.length-1].x)<=1 && Math.abs(j-visitedVector[visitedVector.length-1].y)<=1) { // ok we moved, now let's see if we are backtracking: if (visitedVector.length>1&&i==visitedVector[visitedVector.length-2].x&&j==visitedVector[visitedVector.length-2].y) { // we are backtracking, so we have to remove the last element from visitedVector and turn off the tile var backtrackPoint:Point=visitedVector.pop(); tileVector[backtrackPoint.x][backtrackPoint.y].tile.gotoAndStop(1); tileVector[backtrackPoint.x][backtrackPoint.y].taken=false; removeChild(tileVector[backtrackPoint.x][backtrackPoint.y].path); } else { // we aren't backtracking, let's see if the new tile was already taken (illegal move) if (! tileVector[i][j].taken) { // it's a new tile, let's insert it into the vector and highlight it visitedVector.push(new Point(i,j)); tileVector[i][j].tile.gotoAndStop(2); tileVector[i][j].taken=true; // then place the path movieclip tileVector[i][j].path=new Path(); tileVector[i][j].path.x=visitedVector[visitedVector.length-2].x*tileSize+tileSize/2; tileVector[i][j].path.y=visitedVector[visitedVector.length-2].y*tileSize+tileSize/2; // showing the right frame var iDiff:int=i-visitedVector[visitedVector.length-2].x; var yDiff:int=j-visitedVector[visitedVector.length-2].y; switch (iDiff) { case -1 : tileVector[i][j].path.gotoAndStop(Math.abs(yDiff)*(4+3*yDiff)+1); break; case 0 : tileVector[i][j].path.gotoAndStop(5+2*yDiff); break; case 1 : tileVector[i][j].path.gotoAndStop(5+yDiff); break; } addChild(tileVector[i][j].path); } else { // invalid move, stop drawing stopDrawing(null); } } } } } } private function stopDrawing(e:MouseEvent):void { // updating listeners stage.addEventListener(MouseEvent.MOUSE_DOWN,startDrawing); stage.removeEventListener(MouseEvent.MOUSE_MOVE,drawing); stage.removeEventListener(MouseEvent.MOUSE_UP,stopDrawing); // turning off all tiles for (var i:int=0; i<fieldWidth; i++) { for (var j:int=0; j<fieldHeight; j++) { tileVector[i][j].tile.gotoAndStop(1); tileVector[i][j].taken=false; if (tileVector[i][j].path!=null) { removeChild(tileVector[i][j].path); tileVector[i][j].path=null } } } } } } |
Enjoy the result:
Select tiles and move the mouse to draw a path and eventually backtrack it.
They can be easily customized to meet the unique requirements of your project.













This post has 6 comments
Bruno
There seems to be a slightly problem.
Here is a pic:
http://desmond.imageshack.us/Himg580/scaled.php?server=580&filename=bugmhl.jpg&res=landing
I dont know exactly how I did this, but I was trying to cross paths.
Bojan
Found a bug, if you select few squares and then stop in last (for example, mouse button is down all the time) and move a mouse in that square a bit then release a mouse and game will not clear squares, they stay selected.
Do you plan part 2 of this tutorial?
Bojan
Edit: You need to go forward and back few times between two or more fields to recreate this bug, it does not show all the time but it can be done pretty often.
pp
seem when i try to make diagonal and longer lines,
then back tracking then make false back tracking diagonal and released mouse
then circles is not reset
Ervin
Anyway it’s a very interesting post. Thank you.
Husky
Wow!
I love this game too,
Thanks for your sharing.