[运行效果]
[FLASH=550,400,True]upload/SlidingPuzzle.swf[/FLASH]
[主程序类]
package { import com.klstudio.puzzles.slider.PuzzleBoard; import flash.display.Sprite; /** * SlidingPuzzle * @author Kinglong([email protected]) * @since:2010-9-13 */ public class SlidingPuzzle extends Sprite { [Embed(source="image.jpg")] private var embeddedImage : Class; private var _board:PuzzleBoard; public function SlidingPuzzle() { _board = new PuzzleBoard(300,300,4); addChild(_board); _board.createPuzzle(new embeddedImage()); _board.startGame(); } } }
[PuzzleBoard类]
package com.klstudio.puzzles.slider { import flash.geom.Point; import flash.geom.Rectangle; import flash.display.Bitmap; import flash.geom.Matrix; import flash.display.BitmapData; import flash.display.Sprite; /** * PuzzleBoard * @author Kinglong([email protected]) * @since:2010-9-13 */ public class PuzzleBoard extends Sprite { private var _pieces : Array; private var _moving : Boolean; private var _boardWidth : int; private var _boardHeight : int; private var _pieceWidth : Number; private var _pieceHeight : Number; private var _subdivisions : uint; private var _space : uint; private var _padding : uint; public function PuzzleBoard(width : uint,height : uint,subdivisions : uint = 3,padding : uint = 1,space : int = -1) { _pieces = []; _moving = true; _boardWidth = width; _boardHeight = height; _subdivisions = subdivisions = (subdivisions < 3) ? 3 : subdivisions; _space = (space < subdivisions * subdivisions && space > -1) ? space : subdivisions - 1; _padding = padding; _pieceWidth = _boardWidth / subdivisions; _pieceHeight = _boardHeight / subdivisions; } public function get subdivisions() : uint { return _subdivisions; } public function get padding() : uint { return _padding; } private function scaleImage(bitmap : Bitmap) : BitmapData { var bd : BitmapData = new BitmapData(_boardWidth, _boardHeight); var bRate : Number = _boardWidth / _boardHeight; var iRate : Number = bitmap.width / bitmap.height; var matrix : Matrix = new Matrix(); if(bRate < iRate) { matrix.scale(_boardHeight * iRate / bitmap.width, _boardHeight / bitmap.height); } else { matrix.scale(_boardWidth / bitmap.width, _boardWidth / iRate / bitmap.height); } bd.draw(bitmap, matrix, null, null, null, true); return bd; } public function createPuzzle(bitmap : Bitmap) : void { clearBoard(); var bd : BitmapData = scaleImage(bitmap); var pbd : BitmapData; var len : uint = subdivisions * subdivisions; var rect : Rectangle = new Rectangle(0, 0, _pieceWidth, _pieceHeight); var point : Point = new Point(); for(var i : uint = 0;i < len;i++) { if(i == _space) { continue; } rect.x = (i % subdivisions) * _pieceWidth; rect.y = Math.floor(i / subdivisions) * _pieceHeight; pbd = new BitmapData(_pieceWidth, _pieceHeight); pbd.copyPixels(bd, rect, point); var piece : PuzzlePiece = new PuzzlePiece(pbd, new Point(i % subdivisions, Math.floor(i / subdivisions)), padding); piece.addEventListener(PuzzleEvent.CLICK, clickHandler); piece.addEventListener(PuzzleEvent.MOVE, moveHandler); piece.addEventListener(PuzzleEvent.READY, moveHandler); addChild(piece); _pieces.push(piece); } } public function startGame() : void { var count : uint = 0; var piece : PuzzlePiece; var position : int; while (count < 100) { do { piece = _pieces[int(Math.random() * _pieces.length - 1)]; position = checkNeighbours(piece); }while (position == -1); piece.move(position, false); count++; } _moving = false; } private function clickHandler(event : PuzzleEvent) : void { if(_moving) { return; } var position : int = checkNeighbours(event.piece); if(position > -1) { event.piece.move(position); } } private function moveHandler(event : PuzzleEvent) : void { switch(event.type) { case PuzzleEvent.READY: _moving = false; break; case PuzzleEvent.MOVE: _moving = true; break; } } private function clearBoard() : void { if(_pieces.length == 0) { return; } for each(var piece:PuzzlePiece in _pieces) { piece.removeEventListener(PuzzleEvent.CLICK, clickHandler); piece.removeEventListener(PuzzleEvent.READY, moveHandler); piece.removeEventListener(PuzzleEvent.MOVE, moveHandler); removeChild(piece); } _pieces = []; } private function isEmptySpace(x : int,y : int) : Boolean { for each (var piece:PuzzlePiece in _pieces) { if(piece.point.x == x && piece.point.y == y) { return false; } } return true; } private function checkNeighbours(piece : PuzzlePiece) : int { if (piece.point.x > 0 && isEmptySpace(piece.point.x - 1, piece.point.y)) { return PuzzlePiece.LEFT; } if (piece.point.x < subdivisions - 1 && isEmptySpace(piece.point.x + 1, piece.point.y)) { return PuzzlePiece.RIGHT; } if (piece.point.y > 0 && isEmptySpace(piece.point.x, piece.point.y - 1)) { return PuzzlePiece.UP; } if (piece.point.y < subdivisions - 1 && isEmptySpace(piece.point.x, piece.point.y + 1)) { return PuzzlePiece.DOWN; } return -1; } } }
[PuzzleEvent类]
package com.klstudio.puzzles.slider { import flash.events.Event; /** * PuzzleEvent * @author Kinglong([email protected]) * @since:2010-9-13 */ public class PuzzleEvent extends Event { private var _piece : PuzzlePiece; public static const MOVE : String = "MOVE"; public static const READY : String = "READY"; public static const CLICK : String = "CLICK"; public function PuzzleEvent(type : String, piece : PuzzlePiece = null) { super(type); _piece = piece; } public function get piece() : PuzzlePiece { return _piece; } override public function clone() : Event { return new PuzzleEvent(type, piece); } } }
[PuzzlePiece类]
package com.klstudio.puzzles.slider { import flash.filters.GradientBevelFilter; import flash.filters.BitmapFilter; import flash.filters.BitmapFilterType; import flash.filters.BitmapFilterQuality; import flash.events.MouseEvent; import gs.TweenLite; import gs.easing.Circ; import flash.display.Bitmap; import flash.display.Shape; import flash.geom.Point; import flash.display.BitmapData; import flash.display.Sprite; /** * PuzzlePiece * @author Kinglong([email protected]) * @since:2010-9-13 */ public class PuzzlePiece extends Sprite { public static const DOWN : int = 3; public static const LEFT : int = 1; public static const UP : int = 4; public static const RIGHT : int = 2; private var _padding : uint; private var _ease : Function; private var _point : Point; private var _oPoint : Point; private var _bmp : Bitmap; private var _mask : Shape; public function PuzzlePiece(bitmapData : BitmapData,point : Point,padding : uint = 1) { mouseChildren = false; _ease = Circ.easeInOut; _padding = padding; _oPoint = point.clone(); _point = point.clone(); _bmp = new Bitmap(bitmapData); addChild(_bmp); _mask = new Shape(); _mask.graphics.beginFill(0xFF0000); _mask.graphics.drawRoundRect(_padding, _padding, _bmp.width - _padding * 2, _bmp.height - _padding * 2, 8, 8); _mask.graphics.endFill(); addChild(_mask); _bmp.mask = _mask; x = point.x * _bmp.width; y = point.y * _bmp.height; addEventListener(MouseEvent.CLICK, clickHandler); _bmp.filters = [getBitmapFilter()]; } public function move(position : int,tweened : Boolean = true) : void { var params : Object = {ease:_ease, onComplete:tweenCompleteHandler}; var duration : Number = 0.4; switch(position) { case LEFT: updatePoint(point.x - 1, point.y); if(tweened) { params["x"] = point.x * _bmp.width; TweenLite.to(this, duration, params); dispatchEvent(new PuzzleEvent(PuzzleEvent.MOVE)); } else { x = point.x * _bmp.width; } break; case RIGHT: updatePoint(point.x + 1, point.y); if(tweened) { params["x"] = point.x * _bmp.width; TweenLite.to(this, duration, params); dispatchEvent(new PuzzleEvent(PuzzleEvent.MOVE)); } else { x = point.x * _bmp.width; } break; case UP: updatePoint(point.x, point.y - 1); if(tweened) { params["y"] = point.y * _bmp.height; TweenLite.to(this, duration, params); dispatchEvent(new PuzzleEvent(PuzzleEvent.MOVE)); } else { y = point.y * _bmp.height; } break; case DOWN: updatePoint(point.x, point.y + 1); if(tweened) { params["y"] = point.y * _bmp.height; TweenLite.to(this, duration, params); dispatchEvent(new PuzzleEvent(PuzzleEvent.MOVE)); } else { y = point.y * _bmp.height; } break; } } public function get point() : Point { return _point; } public function reset() : void { updatePoint(_oPoint.x, _oPoint.y); x = point.x * _bmp.width; y = point.y * _bmp.height; } private function updatePoint(x : int,y : int) : void { _point.x = x; _point.y = y; if(hasCompleted()) { _bmp.filters = null; }else{ _bmp.filters = [getBitmapFilter()]; } } private function getBitmapFilter() : BitmapFilter { return new GradientBevelFilter(5, 225, [16777215, 13421772, 0], [0.4, 0, 0.4], [0, 128, 255], 8, 8, 2, BitmapFilterQuality.HIGH, BitmapFilterType.INNER, false); } public function hasCompleted() : Boolean { return _point.equals(_oPoint); } private function clickHandler(event : MouseEvent) : void { dispatchEvent(new PuzzleEvent(PuzzleEvent.CLICK, this)); } private function tweenCompleteHandler() : void { dispatchEvent(new PuzzleEvent(PuzzleEvent.READY)); } } }