Create a 3D Sliding Puzzle Game in Flex with ActionScript 3.0 and Away3D


Flash Platform is a great tool to create games, either for internet or mobile content. With the introduction of Flash 3D Engines, the ability and success of creating flash games is even bigger. In this tutorial we are going to build up a simple sliding puzzle. Puzzle images are dynamically loaded and sliced so you can easily use your own images if you like. Learn, try and leave a comment showing your results.



Requirements

View the DemoDownload 3D Sliding Puzzle Game Source Files

Prerequisites

  • You should be familiar with OOP concepts and AS3
  • Basic knowledge about Away3D (primitives, materials, cameras…)

The code (SlidingPuzzle.as)

So let’s see how it is done. First we’ll take a closer look at the main class (SlidingPuzzle.as). To get things working we need to import the proper classes.

package {

	import away3d.cameras.HoverCamera3D;
	import away3d.containers.View3D;

	import com.techlabs.puzzle.ControlPanel;
	import com.techlabs.puzzle.PuzzleBoard;
	import com.techlabs.puzzle.events.PuzzleEvent;
	import com.techlabs.puzzle.helpers.ImageSlicer;

	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;

	import flash.events.Event;
	import flash.net.URLRequest;

Next we initialize the variables.

	public static var subdivisions:int = 4;

Subdivisions determine how the puzzle board and the image itself are divided into smaller pieces. The default value results in 16 pieces.

	public static var padding:int = 2;

Padding defines the gap between puzzle pieces.This gives our game a bit more realistic feel.

	public static var size:int = 500;

Size determines the physical dimensions of the puzzle board. The loaded image doesn’t have to be 500x500px but make sure it is not too small either. Bigger is better :).

Slicing the image

The rest of the main class (SlidingPuzzle.as) deals with setting up the view and initializing the needed objects but let’s take a look what happens inside imageLoadComplete() handler.

private function imageLoadComplete(e:Event):void {
	_image = _loader.content as Bitmap;
	_puzzleImages = _slicer.sliceImage(_image);
	_gameBoard.createPuzzle(_puzzleImages);
	_view.scene.addChild(_gameBoard);
	_controlPanel.setPreview(_image);
}

When the image is loaded we invoke ImageSlicer class’s instance method sliceImage() and pass it the loaded image as a parameter. The sliceImage() function will then slice it accordingly (subdivisions) and return at two dimensional array containing the bitmaps.

public function sliceImage(image:Bitmap):Array {
	var imgW:Number = image.width;
	var imgH:Number = image.height;

	var pieceW:Number = imgW / SlidingPuzzle.cols;
	var pieceH:Number = imgH / SlidingPuzzle.rows;

	var imageArray:Array = new Array();

	var rect:Rectangle;
	var temp:Bitmap;
	var tempdata:BitmapData;

	for(var y:int = 0; y < SlidingPuzzle.rows; y++) {
		imageArray[y] = new Array();
		for(var x:int = 0; x < SlidingPuzzle.cols; x++) {
			tempdata = new BitmapData(pieceW, pieceH, true, 0x00000000);
			rect = new Rectangle(x * pieceW, y * pieceH, pieceW, pieceH);
			tempdata.copyPixels(image.bitmapData, rect, new Point(0, 0));
			temp = new Bitmap(tempdata);

			imageArray[y][x] = temp;
		}
	}

	return imageArray;
}

This two dimensional array is used for creating the board. createPuzzle() function takes the array as a parameter and iterates through it. Notice that the last piece is ignored beacause we need that space to be able to move other pieces. So here is what happens in the for loops.

  1. If we have reached the last piece let’s break out the loop
  2. New PuzzlePiece is created
  3. We add some eventhandlers to be able to interact with the piece
  4. We position the piece

When the loop is finnished the gameboard is centered in the view.

public function createPuzzle(images:Array):void {
	clearBoard();

	var pieceCount:int = 0;
	var lastPiece:int = SlidingPuzzle.subdivisions * SlidingPuzzle.subdivisions;

	for(var yp:int = 0; yp < SlidingPuzzle.subdivisions; yp++) {
		for(var xp:int = 0; xp < SlidingPuzzle.subdivisions; xp++) {
			if (++pieceCount == lastPiece)
				break;

			var image:Bitmap = images[yp][xp];
			var piece:PuzzlePiece = new PuzzlePiece(image, {width:_pieceWidth, height:_pieceHeight, segmentsH:3, segmentsW:3});
			piece.addEventListener(PuzzleEvent.CLICK, clickHandler);

			piece.addEventListener(PuzzleEvent.MOVE, moveHandler);
			piece.addEventListener(PuzzleEvent.READY, moveHandler);

			piece.x = xp * _pieceWidth + xp * _padding;
			piece.z = -(yp * _pieceHeight + yp * _padding);

			addChild(piece);
			_pieces.push(piece);
		}
	}
	centerBoard();
}

Interaction

Well it just wouldn’t be a game without interaction. When user clicks a piece we first check if it is moving already. If it’s not moving we check its neighbours. If one of it’s neighbours is the empty place we move the piece there. checkNeighbours() function returns the direction where to move the piece or -1 if a valid move is not possible.

private function clickHandler(e:PuzzleEvent):void {
	if (_moving)
		return ;
	var direction:int = checkNeighbours(e.piece);
	if (direction > 0) {
		e.piece.move(direction);
	}
}

private function checkNeighbours(piece:PuzzlePiece):int {
	var empty:Boolean;

	// LEFT
	if (piece.x > 0) {
		empty = isEmptySpace(piece.x - _pieceWidth - _padding, piece.z);
		if (empty)
			return PuzzlePiece.LEFT;
	}

	// RIGHT
	if (piece.x < _boardWidth - _pieceWidth - _padding) {
		empty = isEmptySpace(piece.x + _pieceWidth + _padding, piece.z);
		if (empty)
			return PuzzlePiece.RIGHT;
	}

	// DOWN
	if (piece.z < 0) {
		empty = isEmptySpace(piece.x, piece.z + _pieceHeight + _padding);
		if (empty)
			return PuzzlePiece.UP;
	}

	// UP
	if (piece.z > -_boardHeight + _pieceHeight + _padding) {
		empty = isEmptySpace(piece.x, piece.z - _pieceHeight - _padding);
		if (empty)
			return PuzzlePiece.DOWN;
	}

	return -1;
}

private function isEmptySpace(xp:int, zp:int):Boolean {
	for each(var p:PuzzlePiece in _pieces) {
		if (p.x == xp) {
			if (p.z == zp) {
				return false;
			}
		}
	}
	return true;
}

And “Game Over”, we have finished our puzzle game. Now it’s time to you test and create your own puzzle games. Leave a comment with your experiments. We are always seeking for the results of our tuts.



Did you enjoy this article?
Share the love
Get free updates and win TTL prizes

Other Posts You Might Like

36 Responses to “Create a 3D Sliding Puzzle Game in Flex with ActionScript 3.0 and Away3D”

  1. samBrown says:

    very cool tutorial, nice work

  2. CgBaran Tuts says:

    Nice tutorial thanks

  3. CgBaran Tuts says:

    Great tutorial thanks

  4. aliaskajan says:

    very nice tutorial thank you :)

  5. action script newbie says:

    freakin AWESOME!!!!

  6. Hazem says:

    hi very nice one but there is aproblem when i but the subdevision = 3

  7. Nick I. says:

    Sorry for being a newbie. I think I got all the packages etc in place, but how do I execute this when done?

    SlidingPuzzle();

    ?

    Thanks for the help.

    - n

  8. nirav says:

    hi

    it is very nice.

    i am not know flex.

    can i more slice of picture.

    and show how many move done by user.

    thanks

  9. Steven says:

    Can I use this on my website?

  10. Steven says:

    Can I use this on my website…is that ok?

  11. chantith says:

    Hi, It’s good for me to learn how to make my own Game through your lesson. Thank you so much.

  12. Timo,
    Thank you for the excellent example of using the 3D library in AS3.

    I did notice a “bug” in the shuffle routine that I was hoping you could help solve. The variable: SUBDIVISIONS which controls the number of board pieces, works properly with any dimension 2×2, 3×3, 4×4, …(slicer function), but the shuffle function ONLY works for values of 2, 4, 5, and 10. Any other values cause the pieces to stack on top of each other,forcing one to reset the board.
    Could you please take a look at the logic and explain why it’s failing and post a quick update?
    Thanks again,
    -Marco (Dallas, TX)

  13. I think that I answered my own question. It seems that the puzzle board size must be an EXACT integer multiple of the variable “subdivisions” or the error that I described in my previous post will occur. When I created a 300×300 image, I could slice it as a 2×2, 3×3, 4×4, 5×5, 6×6, but it would fail again at 7 due to the remainder. So it seems the “bug” was just a missing comment in the documentation.
    Thanks again for a great tutorial!

  14. This is a great post and its very creative indeed but if only you people would properly give cubefield a shot. Its a great game. Very addicitve and very entertaining to all age groups.

  15. Nat says:

    Howdy…

    Great work, Hazam is right though.. when you use subdivisions that are a multiple of 3, it doesn’t scramble properly…let me know if you have any idea why this is…trying to figure it out myself..

  16. gepenk says:

    how to change button name flash puzzle & flex puzzle???

  17. Paul says:

    I tried to compile (created an empty SlidingPuzzle.fla file in same src folder) using CS4 but got this error

    PuzzeBoad.as, line 13
    1017: The definition of base class ObjectContainer3D was not found.

  18. Sharedtut says:

    Great job, thank you for sharing.

  19. rohit says:

    the excellent example of using the 3D library in AS2.

  20. rohit says:

    this game of using the 3D library in AS2.

  21. Max says:

    Heya cool tutorial! qustion, do you know how I can make a simple slider puzzle with the coding in the main flash file (no .as files)?
    I want to make a small 4×4 puzzle but cant seem to find any tutorials on it thats in AS3.

    Thanks!

  22. Max says:

    P.S. I meant to say a 2D puzzle.

  23. CGG says:

    I really like the dynamic slicing code. Thanks for posting!

  24. mhamad says:

    hi guys please anyone can help me how i can modify this to put my image and why it is giving me eroor when i download the source to my pc.thank u all

  25. Chris says:

    impressive tutorial!
    Have you considered adding some live ActionScript class diagrams to your code? Please check my address and think about.

  26. siraj says:

    Hi

    Its nice tutorial…
    I need to know when user completed the level and then popup will appear its show you completed the level…

    kind regards
    sirajudeen

  27. Umang says:

    pls provide me objectContainer3D class.

  28. You’re posting great,even so the latter paragraph I get a little bit to don’t understand, can you please deliver an explain?

  29. Vikram Raman says:

    hi. I had go through this tutorial, its really nice. I have a problem, when i make 6 * 6 puzzle.The shuffle is not working properly.Can u tell me whats the problem and how to solve it….

  30. Tungak says:

    I have converted it to the flash IDE and now I’m wondering how to make a “game over” after you have finished the puzzle. Not sure where to check for in terms of initial arrays, all i get is $: y:0 x:45 z:34 (whereas “$:” is the object name). any ideas?

    • RyanKAlexander says:

      I converted to the flash IDE also, and now I need to add some sort of puzzle completion event   – “game over”/”you win”.  Have you had any luck with that part?

  31. RyanKAlexander says:

    Tungak,  how did you port this to Flash Pro?

  32. RyanKAlexander says:

    Anyone alive in here?

  33. RyanKAlexander says:

    Wow, I just discovered that works just fine locally, but the puzzle does not show up in browsers.  Any ideas why this is?

Leave a Reply

TTL VIP
Become a TTL VIP Member & Get Notified of The Best Changes in Technology, Plus Win Prizes in Our VIP Only Contests...

Tech News Tech Tutorials Smartphone News Tablet News Gaming News Free Software Infographics Contact