RSS

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

Wed, Apr 15, 2009

3D, Flex, Games, Tutorials

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.


 

About the Author


Timo Virtanen - who has written 1 posts on Flash Platform and ActionScript Tutorials.

Timo is a Flash/Flex developer from Finland. He has been around since Flash 5. Currently is work at Talvi Digital. You can visit his web site or blog to see some of his works and experiments.

24 Comments For This Post

  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. Marco Fehlbaum Says:

    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. Marco Fehlbaum Says:

    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. Cubefield Game Says:

    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

6 Trackbacks For This Post

  1. 30 Hand-picked Flash and Essential Actionscript 3.0 Tutorials | Noupe Says:

    [...] – Create a 3D Sliding Puzzle Game in Flex with ActionScript 3.0 and Away3D [...]

  2. Create a 3D Sliding Puzzle Game in Flex with ActionScript 3.0 and Away3D | CgBaran Tuts Says:

    [...] View Tutorial [...]

  3. StefKob Blog | webdesign, seo, dev... | » » Flash AS 3 tutorial… Says:

    [...] – Create a 3D Sliding Puzzle Game in Flex with ActionScript 3.0 and Away3D [...]

  4. 30 Hand-picked Flash and Essential Actionscript 3.0 Tutorials | Webmaster Tips Says:

    [...] – Create a 3D Sliding Puzzle Game in Flex with ActionScript 3.0 and Away3D [...]

  5. " » 10 Tutoriels d’exception pour Flash (AS 3)" by Design Spartan Says:

    [...] 9. Puzzle en 3D [...]

  6. 20 Best Flash Game Tutorials to Create Your Own Flash Game | Dzine Blog Says:

    [...] 1. )3D Slidin Puzzle [...]

Leave a Reply