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.

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.

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.

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.

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.

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.

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:

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.

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.

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.

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!

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:

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:

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.

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!

Replies To: Sliding Puzzle Game

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?

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?

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.

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.

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..

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.

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....