Dungeon Raid iPhone game engine made with Flash and AS3 – making items fall
Here we go with a feature which has been requested a lot: taking the Dungeon Raid iPhone game engine made with Flash and AS3 and making items fall once you collect some of them, just like all Bejeweled-like games.
You can find some examples in these posts: Complete Bejeweled game in less than 2KB, Complete Bejeweled prototype made with jQuery and Complete Bejeweled game in less than 2KB – legible version.
The concept is also very similar: once you performed a successful match, scan all items from bottom to top, shifting down floating items and replacing empty spots on the top of the grid with new items.
Moreover, it’s even easier because this kind of game does not feature combos.
Here is the commented 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 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
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 private var colorSelected:int=0;// the color selected by the player 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; // assigning a random value from 1 to 6 to each tile tileObject.val=Math.ceil(Math.random()*6); tileObject.tile=new Tile(); tileObject.tile.x=i*tileSize; tileObject.tile.y=j*tileSize; // displaying the proper frame tileObject.tile.gotoAndStop(tileObject.val); 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.alpha=0.5; tileVector[i][j].taken=true; // saving the color we just selected colorSelected=tileVector[i][j].val; // 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.alpha=1; tileVector[backtrackPoint.x][backtrackPoint.y].taken=false; removeChild(tileVector[backtrackPoint.x][backtrackPoint.y].path); // the infamous bug line tileVector[backtrackPoint.x][backtrackPoint.y].path=null; // adding the arrow to latest path if (visitedVector.length>=2) { tileVector[visitedVector[visitedVector.length-1].x][visitedVector[visitedVector.length-1].y].path.gotoAndStop(tileVector[visitedVector[visitedVector.length-1].x][visitedVector[visitedVector.length-1].y].path.currentFrame+8); } } else { // we aren't backtracking, let's see if the new tile was already taken (illegal move;// moreover we have to check if we are moving over tiles of the same color; if (! tileVector[i][j].taken&&tileVector[i][j].val==colorSelected) { // 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.alpha=0.5; 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 with arrow 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+8); break; case 0 : tileVector[i][j].path.gotoAndStop(5+2*yDiff+8); break; case 1 : tileVector[i][j].path.gotoAndStop(5+yDiff+8); break; } addChild(tileVector[i][j].path); // removing arrow from previous path if (visitedVector.length>=3) { tileVector[visitedVector[visitedVector.length-2].x][visitedVector[visitedVector.length-2].y].path.gotoAndStop(tileVector[visitedVector[visitedVector.length-2].x][visitedVector[visitedVector.length-2].y].path.currentFrame-8); } } 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); // removing and adding tiles if it's a valid move if (e!=null && visitedVector.length>2) { for (var i:int=0; i<visitedVector.length; i++) { // removing old tile removeChild(tileVector[visitedVector[i].x][visitedVector[i].y].tile); // removing old path if (i>0) { removeChild(tileVector[visitedVector[i].x][visitedVector[i].y].path); } // removed tiles are marked with null tileVector[visitedVector[i].x][visitedVector[i].y]=null; } // looking for null tiles from bottom to top for (i=fieldHeight-1; i>0; i--) { for (var j:int=fieldWidth-1; j>=0; j--) { // null tile found if (tileVector[j][i]==null) { var temp:int=i-1; // looking for the first non-null tile above null tile while (temp>=0 && tileVector[j][temp]==null) { temp--; } // found non null tile above null tile if (temp!=-1) { // shifting down non null tile tileVector[j][temp].tile.y+=(i-temp)*tileSize; tileVector[j][i]=tileVector[j][temp]; tileVector[j][temp]=null; } } } } // when all tiles have been shifted down, make new tiles appear for (i=fieldHeight-1; i>=0; i--) { for (j=fieldWidth-1; j>=0; j--) { if (tileVector[j][i]==null) { var tileObject:Object=new Object(); tileObject.taken=false; tileObject.path=null; tileObject.val=Math.ceil(Math.random()*6); tileObject.tile=new Tile(); tileObject.tile.x=j*tileSize; tileObject.tile.y=i*tileSize; tileObject.tile.gotoAndStop(tileObject.val); addChild(tileObject.tile); tileVector[j][i]=tileObject; } } } } else { // turning off all tiles for (i=0; i<fieldWidth; i++) { for (j=0; j<fieldHeight; j++) { tileVector[i][j].tile.alpha=1; tileVector[i][j].taken=false; if (tileVector[i][j].path!=null) { removeChild(tileVector[i][j].path); tileVector[i][j].path=null; } } } } } } } |
and this is the result:
Draw with the mouse to match items of the same color. This prototype does not include any animation, but it should be easy to add them.
They can be easily customized to meet the unique requirements of your project.





(5 votes, average: 4.60 out of 5)






This post has 6 comments
ChrisM
Nice!
I accidentally dragged off the stage (the index is -1 is out of range 8), so it looks like that is being handled, and still works.
Nice addition!
Jae
A cool tutorial, but there is a significant flaw in the design.
It is not only possible, but very likely to start with or quickly get to a board arrangement with no moves. What are some strategies you could use to prevent this?
Also, your color scheme is not colorblind friendly. It is VERY difficult to tell the green and yellow apart.
Dungeon Raid iPhone game engine made with Flash and AS3 ... | Video Gamer Weekly
[...] the original post: Dungeon Raid iPhone game engine made with Flash and AS3 … (function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if [...]
Jae
never mind on the locked position, I didn’t know you could move across diagonals.
Miami accountant
I will have a lot of work to do to achieve these effects (beginner) but it already sucked me up.
Alex
Main.as(23): col: 26 Error: Call to a possibly undefined method Tile.
Main.as(88): col: 35 Error: Call to a possibly undefined method Path.
???