Dungeon Raid iPhone game engine made with Flash and AS3 – making items fall

Read all posts about "" game

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:

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.;
		private var visitedVector:Vector.;// 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.();
			for (var i:int=0; i();
				for (var j:int=0; j();
			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; i0) {
						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

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.

Download the source code.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 2048
// Dots
// Maze
// Pool
// Poux
// Pudi
// qomp
// Turn
// Zhed