• (3 Pages)
  • +
  • 1
  • 2
  • 3

Sliding Puzzle Game Using classes and AS2 Rate Topic: ***** 2 Votes

#1 thehat  Icon User is offline

  • awake ? web();
  • member icon

Reputation: 106
  • View blog
  • Posts: 951
  • Joined: 28-February 08

Posted 09 March 2008 - 02:50 PM

Flash Sliding Puzzle Game
In this tutorial, we are going to create a sliding tile puzzle game component using actionscript. Sliding puzzle games work by spreading an image accross a number of tiles then jumbling the tiles up, so you have to re-assemble the image by moving the tiles one at a time. There is always one empty space, and you can only move a tile into a space that is in direct contact with it.

The component will accept any image, and generate a puzzle from a few simple settings. This tutorial is as much a learning exercise for me as for you dear reader, so please feel free to show me corrections and places where I could've done better.

Requirements:
  • Flash 8 or later.
  • Some actionscript knowledge (well, this is a programming site!).
  • If you don't like the image I'm providing, you'll need your own.
  • An actionscript editor is optional, but I like to code in SE|PY, you might like it too.


Getting Started
During this tutorial we will create four actionscript classes. I like to keep my classes seperate from my other source files, so in your working directory, create a new folder and call it "com". Now we're ready to begin.


The code
As I've already mentioned, this component is comprised of four classes. These are:
  • eventBroadcaster.as - The event broadcaster is a very simple class that allows us to access the Flash event model easily.
  • bitmapGenerator.as - The bitmap generator uses the bitmapData object to split your image into several pieces that can then be attached to the tiles.
  • slidingPuzzleTile.as - Each tile is an instance of this class. Properties such as ID and initial positions are stored, and there is movement method. This class also extends the event broadcaster.
  • slidingPuzzleMain.as - This class extends the event broadcaster, and governs the main game. It creates the tiles, and handles the logic required to move the tiles.

So, lets get down to it. We'll start with the easy one.


eventBroadcaster

import mx.events.EventDispatcher; 

class com.eventBroadcaster extends MovieClip {
	
   public var addEventListener : Function;
   public var removeEventListener : Function;
   public var dispatchEvent : Function;
   
   public function eventBroadcaster() {
	   EventDispatcher.initialize( this );
   }
   
}


As you can see, this is a very simple class that sets up the event related functions we are going to use later and initializes the EventDispatcher. Save the class in your com folder as eventBroadcaster.as.


bitmapGenerator

/*
* Imports
*/
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;

class com.bitmapGenerator {
	
	/*
	* Properties
	*/
	private var mainImage		:BitmapData;
	
	private var tileW			:Number;
	private var tileH			:Number;
	
	private var bitmapArray		:Array;
	
	/*
	* Constructor
	*/
	function bitmapGenerator() {
		//empty
	}
	
	/*
	* Split the source image into a grid of bitmapData objects and return as 2D array 
	*/
	public function createTiles(clipRef:String,tileX:Number,tileY:Number):Array {
		
		mainImage = BitmapData.loadBitmap(clipRef);
		
		tileW = mainImage.width / tileX;
		tileH = mainImage.height / tileY;
		
		bitmapArray = new Array();
		
		for (var i:Number = 0; i < tileX; i++) {
			
			bitmapArray[i] = new Array();
			
			for (var n:Number = 0; n < tileY; n++) {
				
				var tempData:BitmapData = new BitmapData(tileW,tileH);
				var tempRect = new Rectangle((tileW * i),(tileH * n),tileW,tileH);
				
				tempData.copyPixels(mainImage,tempRect,new Point(0,0));
				
				bitmapArray[i][n] = tempData;
				
			}
			
		}
		
		return bitmapArray;
		
	}
	
}



The bitmapGenerator is quite a small class with only one method, createTiles, which receives three properties. These are the linkage identifier of your image in the library as a string, and the number of tiles you want to split the image into along the x and y axis.

The first things that happen are a bitmapData object called mainImage is created and populated with your image from the library, and the dimensions of mainImage are then used with the required number of tiles to determine each tiles dimensions. An array is created, which is populated by more arrays in the outer for loop to create a two dimensional array.

A temporary bitmapData object is created, using the tile dimensions. Next, a rectangle is created to the dimensions of one tile, and used as a marker for pixel data to be copied from mainImage to our temporary bitmap object. The temporary bitmap Data is inserted into the two dimensional array and the loop iterates. When the array is fully populated it is returned.

Save this file in the com folder as bitmapGenerator.as.


slidingPuzzleTile

/*
* Imports
*/
import com.eventBroadcaster;
import flash.display.BitmapData;
import mx.utils.Delegate;
import mx.transitions.Tween;

class com.slidingPuzzleTile extends eventBroadcaster {
	
	/*
	* Properties
	*/
	// reference for click event
	public static var TILECLICK = "onTileClicked";
	
	//unique tile id
	public var tileID		:Number;
	//tile dimensions
	private var tileW		:Number;
	private var tileH		:Number;
	//Initial x and y positions
	public var xIndex		:Number;
	public var yIndex		:Number;
	//tile movieclip
	public var targMC		:MovieClip;
	
	
	/*
	* Constructor
	*/
	function slidingPuzzleTile(mc:MovieClip,bmp:BitmapData,id:Number,xI:Number,yI:Number,bC:Number,bW:Number,bA:Number) {
		
		tileID = id;
		tileW = bmp.width;
		tileH = bmp.height;
		xIndex = xI;
		yIndex = yI;
		targMC = mc;
		
		init(bmp,bC,bW,bA);
		
	}
	
	/*
	* Attach bitmapData to tile moveclip, create a border and set the onRelease listener
	*/
	private function init(bmp:BitmapData,bC:Number,bW:Number,bA:Number):Void {
		
		targMC.attachBitmap(bmp,1);
		
		if (bW > 0) {
			var tileBorder:MovieClip = targMC.createEmptyMovieClip("tileHighlight",2);
			var innerLine:Number = Math.floor(bW/2);
			tileBorder.lineStyle(bW,bC,bA);
			tileBorder.moveTo(innerLine,innerLine);
			tileBorder.lineTo(tileW-innerLine,innerLine);
			tileBorder.lineTo(tileW-innerLine,tileH-innerLine);
			tileBorder.lineTo(innerLine,tileH-innerLine);
			tileBorder.lineTo(innerLine,innerLine);
		}
		
		targMC.onRelease = Delegate.create(this, tileClick);
		
	}
	
	/*
	* Dispatch event on tile click 
	*/
	public function tileClick():Void {
		
		dispatchEvent({ type:TILECLICK, target:this, tile:tileID });
		
	}
	
	/*
	* Recieve a direction and call the animation function 
	*/
	public function moveTile(dir:String):Void {
		
		switch (dir) {
			
			case "up":
				doTween("_y",targMC._y,targMC._y-tileH);
			break;
			
			case "down":
				doTween("_y",targMC._y,targMC._y+tileH);
			break;
			
			case "left":
				doTween("_x",targMC._x,targMC._x-tileW);
			break;
			
			case "right":
				doTween("_x",targMC._x,targMC._x+tileW);
			break;
			
		}
		
	}
	
	/*
	* Move the tile 
	*/
	private function doTween(dir:String,curr:Number,dist:Number):Void {
		
		var myTween:Tween = new Tween(targMC, dir, mx.transitions.easing.Strong.easeOut, curr, dist, .4, true);
		
	}
		
}



The slidingPuzzleTile class is instantiated once for every tile in the puzzle. Lets look first at its properties. There is a reference for the tile clicked event, which will be dispatched to slidingPuzzleMain. The other properties are a unique ID, the tiles dimensions, it's initial array coordinates and a reference to its movieclip. The initial array coordinates are used when checking if the puzzle has been completed.

There are several arguments received by the constructor. These are: a reference to the tiles movieclip, the bitmapData for the tile to display, the tiles ID, it's coordinates in the tiles array stored in slidingPuzzleMain, the tile's border color, its border width and its border alpha. The movieclip reference, array position and ID are stored, and the tile dimensions are found from the bitmapData object, then the bitmap object is passed to the init method, along with the border properties.

In the init method the bitmapData is first attached to the tile movieclip, then the requested border width is checked. If the requested width is larger than zero, an empty movieclip is attached to the tile and the border is drawn around the edge. The border is inset onto the tile to prevent the tiles from being pushed apart. Finally, the onRelease is set up, and delegated to a method called tileClick.

The tileClick method is very simple. Its only purpose it to dispatch the onTileClicked event back to slidingPuzzleMain.

The remaining two methods in this class handle movement, if it required. If slidingPuzzleMain decides that the tile can move it calls moveTile, passing a single string argument which specifies the movement direction. The moveTile method then calls doTween, passing to it the direction movement, and the start and end positions. An instance of the tween class is instantiated to perform the animation.

This file can now be saved in the com folder as slidingPuzzleTile.as. Now we get on to the big one...


slidingPuzzleMain

This is a much bigger class, so we'll break it down into chunks. First of all we'll start the class, look at the properties and write the constructor. Hopefully the comments are suitably descriptive.

/*
*  Imports
*/
import com.eventBroadcaster;
import com.bitmapGenerator;
import com.slidingPuzzleTile;


class com.slidingPuzzleMain extends eventBroadcaster {
	
	
	/*
	* Properties
	*/
	// references for events
	public static var TILECLICK	:String = "onTileClick";
	public static var COMPLETE	:String = "onPuzzleComplete";
	
	// tiles array holds references to the tile objects
	public var tiles		            :Array;
	// bitmaps array holds references to the slices of the initial image
	private var bitmaps		:Array;
	// bitmap generator class breaks up the initial images into smaller pieces
	private var bitmapGen		:bitmapGenerator;
	
	// tile properties
	private var tilesX		:Number;
	private var tilesY		:Number;
	private var borderCol		:Number;
	private var borderWidth		:Number;
	private var borderAlpha		:Number;
	
	//holds the number of moves to jumble the puzzle by
	private var initMoves		:Number;
	
	// holds the linkage id of the image to use
	private var imageRef		:String;
	
	
	/*
	* constructor
	*/
	function slidingPuzzleMain() {
		
		prepareBitmaps();
		createTiles();
		
	}



After the imports and the class declaration we find the properties. The first two declare the two events that this class will dispatch. Next are two arrays. These will be 2 dimensional arrays (an array of arrays) that represent our image when it's cut up into tiles, like a grid or table. The first is to hold the references to each tile instance, and the second is to hold the output from the bitmap generator.

The rest of the properties are holders for values that you will set with the component or property inspector. We'll come back to the setting of those later.

Finally we have the constructor, which calls the next two methods:

           /*
	* Instantiate the bitmapGenerator to slice the image and return the seperate bitmaps
	*/
	private function prepareBitmaps():Void {
		
		bitmapGen = new bitmapGenerator(this);
		bitmaps = bitmapGen.createTiles(imageRef,tilesX,tilesY);
		
	}
	
	/*
	* Create the tiles
	*/
	private function createTiles():Void {
		
		var tileID:Number = 0;
		
		tiles = new Array();
		//for every tile on the x axis
		for (var i:Number = 0; i < tilesX; i++) {
			
			tiles[i] = new Array();
			//for every tile on the y axis
			for (var n:Number = 0; n < tilesY; n++) {
				
				var tempMC:MovieClip = this.createEmptyMovieClip("tile"+tileID,this.getNextHighestDepth());
				tiles[i][n] = new slidingPuzzleTile(tempMC,bitmaps[i][n],tileID,i,n,borderCol,borderWidth,borderAlpha);
				tiles[i][n].addEventListener("onTileClicked",this);
				tempMC._x = tempMC._width * i;
				tempMC._y = tempMC._height * n;
				tileID++;
				
			}
			
		}
		
		// remove the last tile to create the required empty square
		tiles[tiles.length-1][tiles[tiles.length-1].length-1].targMC.removeMovieClip();
		tiles[tiles.length-1][tiles[tiles.length-1].length-1] = "empty";
		
		//jumble the puzzle
		jumble();
		
	}



The first of these methods instantiates the bitmap generator and calls it's createTiles method with some properties. These are the linkage identifier of your image in the library, and the number of tiles you want to split the image into along the x and y axis. the createTiles method returns a two dimensional array of bitmapData objects for us to turn into tiles, and the createTiles method is ready an waiting to do just that.

In the createTiles method there are two for loops, one inside the other. These loops populate the two dimensional tiles array with instances of the slidingPuzzleTile class by first creating a temporary movieclip reference. This reference is passed to the slidingPuzzleTile constructor, along with a bitmapData object, a unique id number, the tile's initial position in the tiles array (used later), and details of what border to create. An event listener is added to catch the onTileClicked event from the tile, and it's x and y position is set based on it's dimensions and the number of the loop iterations.

Finally, the last instance of the tiles array has it's movie clip removed, and the reference to the tile object is replaced by a string containing "empty". This is the blank square that allows us to move tiles around the puzzle. The jumble method is called to randomise the tiles so the game can begin.

         /*
	* Performs a number of moves to jumble the puzzle
	*/
	private function jumble():Void {
		//hold possible tiles to move
		var possibles:Array = new Array();
		//hold location of empty tile
		var emptyPos:Object = new Object();
		//hold previous tile ID, to prevent back-tracking
		var prevID:Number;
		
		for (var i:Number = initMoves; i > 0; i--) {
			
			possibles = [];
			//find the empty tile
			emptyPos = findEmpty();
			
			//if surrounding tiles exist, add to possibles array
			if (tiles[emptyPos.xI][emptyPos.yI - 1] && tiles[emptyPos.xI][emptyPos.yI - 1].tileID != prevID) {
				possibles.push(tiles[emptyPos.xI][emptyPos.yI - 1]);
				
			}
			if (tiles[emptyPos.xI][emptyPos.yI + 1] && tiles[emptyPos.xI][emptyPos.yI + 1].tileID != prevID) {
				possibles.push(tiles[emptyPos.xI][emptyPos.yI + 1]);
				
			}
			if (tiles[emptyPos.xI - 1][emptyPos.yI] && tiles[emptyPos.xI - 1][emptyPos.yI].tileID != prevID) {
				possibles.push(tiles[emptyPos.xI - 1][emptyPos.yI]);
				
			}
			if (tiles[emptyPos.xI + 1][emptyPos.yI] && tiles[emptyPos.xI + 1][emptyPos.yI].tileID != prevID) {
				possibles.push(tiles[emptyPos.xI + 1][emptyPos.yI]);
				
			}
			
			//select a random array value
			var randNum:Number = Math.floor(Math.random() * possibles.length);
			prevID = possibles[randNum].tileID;
			possibles[randNum].tileClick();
			
		}
		
	}
	
	/*
	* Loop through the tiles array and return the location of
	* the empty tile
	*/
	private function findEmpty():Object {
		
		
		for (var i:Number = 0; i < tilesX; i++) {
			
			for (var n:Number = 0; n < tilesY; n++) {
				
				if (tiles[i][n] == "empty") {
					var tempObj:Object = new Object({ xI:i, yI:n });
					return tempObj;
				}
				
			}
			
		}
		
	}



The jumble method is quite large. The idea here is that for a set number of iterations the code finds where the currently empty space is using the findEmpty method, then it populates the possibles array with up to three surrounding tiles. This number will be less if the space is against a side of the puzzle, and the previously moved tile will always be ignored. Once the possibles array has been populated an entry is selected at random, it's ID is stored to ensure it is ignored in the next iteration, and the tile's tileClick method is called which causes it to move. How it does that is dealt with next:

	/*
	* Respond to onTileClicked event by checking for an available 
	* space and moving if possible.  If puzzle is complete disable 
	* buttons and dispatch complete event.
	*/
	private function onTileClicked(eo:Object):Void {
		
		dispatchEvent({ type:TILECLICK, target:this });
		
		var space:String = canMove(findTile(eo.tile));
		
		if (space != "no") {
			eo.target.moveTile(space);
			//if puzzle is complete
			if(checkPositions()) {
				disableButtons();
				dispatchEvent({ type:COMPLETE, target:this });
			}
			
		}		
		
	}



This method is called by the event listener we set up earlier on the tiles. The event object (eo) contains the ID of tile that was clicked so it can be identified. First though, we dispatch an event to notify any outside observers that a tile has been clicked.

That done a string called space is created and populated by the output of the can move method (see next code block). If the tile is able to move, it is informed of where the vacant space is in relation to itself and it moves. The positions of all the tiles are now checked to see if the puzzle is complete, and if it is the tile buttons are disabled and the puzzle complete event is dispatched.

        /*
	* Loop through the tiles array and return the array location of
	* the desired tile as an object
	*/
	private function findTile(tI:Number):Object {
		
		
		for (var i:Number = 0; i < tilesX; i++) {
			
			for (var n:Number = 0; n < tilesY; n++) {
				
				if (tiles[i][n].tileID == tI) {
					var tempObj:Object = new Object({ xI:i, yI:n });
					return tempObj;
				}
				
			}
			
		}
		
	}
	
	/*
	* Check for an empty space ajoining the selected tile and return the availiable
	* direction, or "no"
	*/
	private function canMove(tIndex:Object):String {
		
		if (tiles[tIndex.xI][tIndex.yI - 1] == "empty") {
			tiles[tIndex.xI][tIndex.yI - 1] = tiles[tIndex.xI][tIndex.yI];
			tiles[tIndex.xI][tIndex.yI] = "empty";
			return "up";
		} else if (tiles[tIndex.xI][tIndex.yI + 1] == "empty") {
			tiles[tIndex.xI][tIndex.yI + 1] = tiles[tIndex.xI][tIndex.yI];
			tiles[tIndex.xI][tIndex.yI] = "empty";
			return "down";
		} else if (tiles[tIndex.xI - 1][tIndex.yI] == "empty") {
			tiles[tIndex.xI - 1][tIndex.yI] = tiles[tIndex.xI][tIndex.yI];
			tiles[tIndex.xI][tIndex.yI] = "empty";
			return "left";
		} else if (tiles[tIndex.xI + 1][tIndex.yI] == "empty") {
			tiles[tIndex.xI + 1][tIndex.yI] = tiles[tIndex.xI][tIndex.yI];
			tiles[tIndex.xI][tIndex.yI] = "empty";
			return "right";
		}
		
		return "no";
		
	}
	
	/*
	* Check if the puzzle is complete 
	*/
	private function checkPositions():Boolean {
		
		//if the bottom right space is empty
		if (tiles[tiles.length-1][tiles[tiles.length-1].length-1] == "empty") {
			
			for (var i:Number = 0; i < tilesX; i++) {
				
				for (var n:Number = 0; n < tilesY; n++) {
					//if the tile's current x position matches it's starting point
					if (tiles[i][n].xIndex != i && i != (tiles.length - 1)) {
						return false;
					}
					//if the tile's current y position matches it's starting point	
					if (tiles[i][n].yIndex != n && n != (tiles[i].length - 1)) {
						return false;
					}				
					
				}
				
			}
			
		} else {			
			return false;			
		}
		
		//all tiles are in the correct place
		return true;
		
	}



These are the three methods that provide the checks to the onTileClicked method. The first is pretty simple, it loops through the two dimenstional tiles array looking for a specific tileID. When found it returns the coordinates if the tile object in the two dimensional array as an object.

The canMove method investigates the array positions on all four sides of the selected tile. If it discovers an empty square it moves the instance of the current tiles to the empty index, and changes it's old index to be "empty". This done, it returns the direction for the tile to move in as a string. If there is no availiable empty space it returns "no".

The last method here is the checkPositions method. It loops through the tiles array, and checks each tile to see if it is occupying the array index that it started from. If all the the tiles are in their original places the puzzle is complete, and checkPositions returns true.

        /*
	* Enable all tile buttons 
	*/
	private function enableButtons():Void {
		
		for (var i:Number = 0; i < tilesX; i++) {
			
			for (var n:Number = 0; n < tilesY; n++) {
				
				tiles[i][n].targMC.enabled = true;
				
			}
			
		}
		
	}
	
	/*
	* Disable all tile buttons 
	*/
	private function disableButtons():Void {
		
		for (var i:Number = 0; i < tilesX; i++) {
			
			for (var n:Number = 0; n < tilesY; n++) {
				
				tiles[i][n].targMC.enabled = false;
				
			}
			
		}
		
	}
	
	/*
	* Restart puzzle 
	*/
	public function resetPuzzle():Void {
		
		jumble();
		enableButtons();
		
	}



The three methods above are all very simple, and the first two are almost identical. enableButtons and disableButtons do exaclty as they say; they loop through the tiles array, and enable or disable each tile respectively. Disable is used when the puzzle is complete, and enable is used in the resetPuzzle method, which jumbles the tiles again and enables the tiles ready to begin again. The resetPuzzle method will be called from outside the class, so it is public.

	/*
	* Component property tags 
	*/
	[Inspectable(type=String)]
	public function set image_linkage(ref:String):Void {
		imageRef = ref;
	}
	
	
	[Inspectable(type=Number)]
	public function set horizontal_tiles(ref:Number):Void {
		tilesX = ref;
	}
	
	
	[Inspectable(type=Number)]
	public function set vertical_tiles(ref:Number):Void {
		tilesY = ref;
	}
	
	[Inspectable(type=Color)]
	public function set tile_border_color(ref:Number):Void {
		borderCol = ref;
	}
	
	[Inspectable(type=Number,defaultValue=1)]
	public function set tile_border_width(ref:Number):Void {
		borderWidth = ref;
	}
	
	[Inspectable(type=Number,defaultValue=100)]
	public function set tile_border_alpha(ref:Number):Void {
		borderAlpha = ref;
	}
	
	[Inspectable(type=Number)]
	public function set moves_to_finish(ref:Number):Void {
		initMoves = ref;
	}
		
}



Finally, the inspectable set methods. These allow the properties to be set in the component or property inspector in flash, making the puzzle really easy to use once it's built. The string and number properties are fairly obvious, but new to me at the time of writing is the Color type. This causes a color palette to appear in the property inspector in place of a text box.

So that's it for the classes. Phew. Save your file in the com folder as slidingPuzzleMain.as, and then lets look at the flash side.


In Flash

The majority of the work is done for us in the classes above, now it's time to take it easy. In this section you are going to need an image. If you don't have one handy, use this one. It's the same one I used while testing this tutorial!

Attached Image

So, create a new AS2 document. The dimensions are not really important, but make sure the stage is at least as big as the image you intend to use. Save the document in your working folder (the one with the com folder in it). Import your chosen image into the library, then right click on it and select "Linkage...". Tick the "Export for Actionscript" box, and change the linkage identifier if you really want to. Click OK.

Next, create an empty movieclip, put it on the stage and give it the instance name "puzzle". This movieclip will represent the top left corner of your puzzle, so position it accordingly. Create a new layer on the timeline, and still on the same frame enter the following code:
stop();

import com.eventBroadCaster;

puzzle.addEventListener("onPuzzleComplete", this);

function onPuzzleComplete():Void {
	nextFrame();
}



This sets up a listener for the onPuzzleComplete event that you're going to recieve, and creates a function that will move the playhead to the next frame when it fires.

Now create another column of frames on the timeline, and a new layer. On frame two, in your new layer, create a text field as big as you like with a jubilant message inside. I went for "SUCCESS!". Make this into a button by selecting it and pressing F8 (next week - egg sucking by thehat), and give it the instance name "again". Then in frame two of your actions layer insert the following:

stop();
again.onRelease = function() {
	puzzle.resetPuzzle();
	prevFrame();
}



This simply starts the puzzle again and hides your happy message.

Finally, go back to the library, right click on your empty movieclip and select "Component Definition...". In the class textbox put "com.slidingPuzzleMain" and select OK. Right click the movieclip again and Select "Linkage...", then tick the "Export for Actionscript" box and in the class textbox put "com.slidingPuzzleMain" and select OK. Now click on the empty movieclip you put on the stage, and in the properties panel select the parameters tab. You should now see the list of options to setup your puzzle game.

Attached Image

Go ahead and fill these in as you like, making sure you get the image_linkage correct (it's the linkage identifier of your image in the library) then CTRL+Enter and try it out!


Wow, so that's it. I hope it all works well for you, and you followed this tutorial easily enough. It's my first one, and all feedback is gratefully recieved. Thanks for reading!

Is This A Good Question/Topic? 2
  • +

Replies To: Sliding Puzzle Game

#2 Public_account  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 37
  • Joined: 16-February 07

Posted 11 June 2008 - 11:23 AM

Hi,

I've tried this tutorial a few times and it works great! The only issue I have is sometimes when I test the movie some of the puzzle pieces stick in place and won't move or some of the pieces will be half off the stag. I have the stage slightly larger that the image I'm using. Anyone know what I'm doing wrong?
Was This Post Helpful? 0
  • +
  • -

#3 nikkisix  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 09-September 08

Posted 09 September 2008 - 08:12 PM

hi ,

i have attempted this tutorial but to no avail!

When i test the flash game i get nothing! no errors, no game, nothing!

i have quadruple checked the linkage of both the empty movie clip and the image, and they are as they should be

is there anything else i should be looking for in order to get this to work?

many thanks!
Was This Post Helpful? 0
  • +
  • -

#4 thehat  Icon User is offline

  • awake ? web();
  • member icon

Reputation: 106
  • View blog
  • Posts: 951
  • Joined: 28-February 08

Posted 10 September 2008 - 04:09 AM

Hi nikkisix,

Could you maybe post your work? No errors and no game doesn't leave a lot to go on!
Was This Post Helpful? 0
  • +
  • -

#5 GreenSpiral  Icon User is offline

  • D.I.C Head

Reputation: 2
  • View blog
  • Posts: 64
  • Joined: 30-December 08

Posted 31 December 2008 - 07:55 AM

Like your picture of shazam. :D
Was This Post Helpful? 0
  • +
  • -

#6 cutey_kira  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 12-January 09

Posted 12 January 2009 - 08:26 PM

Hey, i have just tried to do this tutorial and i cant get it to work!!!

i have attached my file so if anyone can help me please and thanks

Melanie
Was This Post Helpful? 0
  • +
  • -

#7 thehat  Icon User is offline

  • awake ? web();
  • member icon

Reputation: 106
  • View blog
  • Posts: 951
  • Joined: 28-February 08

Posted 13 January 2009 - 11:05 AM

Hi Melanie,

I can't see your attachment. Do you want to try and post it again, or maybe just post the errors you're getting.
Was This Post Helpful? 0
  • +
  • -

#8 cutey_kira  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 12-January 09

Posted 15 January 2009 - 10:16 PM

Hey there are to many errors so i will try and post my work again
this one is a zip folder


and also i have tried to follow another tutorial
http://www.sciencean...ragtutorial.pdf

and i have done all the work but its not working properly.
and this one is a file called reba.fla
if you could help me with either please!!!
Was This Post Helpful? 0
  • +
  • -

#9 kaira_e  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 20-January 09

Posted 20 January 2009 - 01:30 AM

Hey I've got a little problem like some other people already had too.

I noticed that when you copy paste the whole code from here, it has some enters on places where there shouldn't be one (which is the cause of thousand errors)

After I fixed that, I didn't got any more errors, but the puzzle isn't working either.
I set the border width of the tiles to 20 pixels and then found out that, that part does work, cause you'll get to see the borders in the corner if you test movie. I think the problem is something with the image but I'm not sure how and what.
Do you have any idea how to fix it?

Thanks!

This post has been edited by kaira_e: 20 January 2009 - 01:37 AM

Was This Post Helpful? 0
  • +
  • -

#10 thehat  Icon User is offline

  • awake ? web();
  • member icon

Reputation: 106
  • View blog
  • Posts: 951
  • Joined: 28-February 08

Posted 20 January 2009 - 02:26 AM

It sounds like it's failing to load the image from the library. Have you set your image to export, and ensured that you put it's correct linkage identifier into the correct box in the component's properties?

If that doesn't help, put your image and fla in a zip file and attach it to your message for me to take a look.
Was This Post Helpful? 0
  • +
  • -

#11 kaira_e  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 20-January 09

Posted 20 January 2009 - 04:03 AM

Yeah I checked that several times.

I uploaded the zip to mediafire since attaching it took forever. I hope that's okay.
Zipfile

Thanks for helping me out!
Was This Post Helpful? 0
  • +
  • -

#12 thehat  Icon User is offline

  • awake ? web();
  • member icon

Reputation: 106
  • View blog
  • Posts: 951
  • Joined: 28-February 08

Posted 20 January 2009 - 07:45 AM

Well, it seems that this is the fault of my badly written tutorial!

The reason that nothing is appearing is that the calcuations in sildingPuzzleMain's constructor are flawed. They use the width and height of that empty movieclip on the stage, which by it's empty nature has no width or height.

The easy fix for this is to create a rectangle in the movieclip on the stage, with dimensions matching your image. This is hardly an elegant solution though, as it doesn't allow for an obvious extension of allowing different images at runtime.

A more severe fix is as follows:

Fisrt, comment out the two lines in slidingPuzzleMain's constructor that set the tile width and height.
function slidingPuzzleMain() {
		
	//tileW = this._width / tilesX;
	//tileH = this._height / tilesY;
		
	prepareBitmaps();
	createTiles();
		
}



Next, remove the tileW and tileH properties from the call to the bitmapGenerators createTiles method:
bitmaps = bitmapGen.createTiles(imageRef,this._width,this._height,tilesX,tilesY);




Now we need to add some stuff to the bitmapGenerator.

Create some properties to hold the tile width and height. These are public, so that the main class can use them.
public var tileW:Number;  
public var tileH:Number;



Next, we remove the tileW and tileH properties from the createTiles method's declaration, and add the tile size calculation to the createTiles method once the image has been loaded into the bitmapData object..
public function createTiles(clipRef:String,totW:Number,totH:Number,tileX:Number,tileY:Number):Array {
		
	trace("creating bitmaps");
		
	var mainImage:BitmapData = BitmapData.loadBitmap(clipRef);
	
        //new lines!!	
	tileW = mainImage.width / tilesX;
	tileH = mainImage.height / tilesY;



With this done, all that remains is to move through the slidingPuzzleMain class, renaming any remaining references to tileW or tileH to bitmapGen.tileW and bitmapGen.tileH. These should only be found in the createTiles method.

Hopefully that'll fix it for you!
Was This Post Helpful? 1
  • +
  • -

#13 kaira_e  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 20-January 09

Posted 21 January 2009 - 01:37 AM

hey,
I tried the empty square first, but it still didn't work. When I tried the code part, I found that the first 3 things you said needed to be changed, were already like they are supposed to be.
I did add the last one, but I still get the same....
Was This Post Helpful? 0
  • +
  • -

#14 thehat  Icon User is offline

  • awake ? web();
  • member icon

Reputation: 106
  • View blog
  • Posts: 951
  • Joined: 28-February 08

Posted 21 January 2009 - 03:01 AM

Hmm...I guess I must've been using an older version of the code. I'll do the tutorial myself at lunchtime. In the meantime, would you be able to post your class files too?
Was This Post Helpful? 0
  • +
  • -

#15 kaira_e  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 20-January 09

Posted 21 January 2009 - 03:18 AM

Sure, here is the link.
zipfile

This post has been edited by kaira_e: 21 January 2009 - 03:18 AM

Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3