package {
import flash.display.*;
import flash.events.*;
import flash.net.URLRequest;
import flash.geom.*;
import flash.utils.Timer;
public class JigsawPuzzle extends MovieClip {
// 小块数量
const numPiecesHoriz:int = 8;
const numPiecesVert:int = 6;
// 小块尺寸
var pieceWidth:Number;
var pieceHeight:Number;
// 游戏小块储存对象
var puzzleObjects:Array;
// 两类sprite
var selectedPieces:Sprite;//储存被拖拽的所有小块
var otherPieces:Sprite;//没被拖拽所有小块
// 被拖拽的小块
var beingDragged:Array = new Array();
// 导入图像 设置sprite
public function startJigsawPuzzle() {
// 导入图像
loadBitmap("jigsawimage.jpg");
// 设置两个 sprites
otherPieces = new Sprite();
selectedPieces = new Sprite();
addChild(otherPieces);
addChild(selectedPieces); // 放在顶部
}
// 从外部获得位图
public function loadBitmap(bitmapFile:String) {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadingDone);
var request:URLRequest = new URLRequest(bitmapFile);
loader.load(request);
}
// 位图导入完成 切成小块
private function loadingDone(event:Event):void {
// 创建新的的图像来放置位图
var image:Bitmap = Bitmap(event.target.loader.content);
pieceWidth = Math.floor((image.width/numPiecesHoriz)/10)*10;
pieceHeight = Math.floor((image.height/numPiecesVert)/10)*10;
// 将导入的位图放入image类中
var bitmapData:BitmapData = image.bitmapData;
// 切割成拼图小块
makePuzzlePieces(bitmapData);
// 设置移动和鼠标事件
addEventListener(Event.ENTER_FRAME,movePieces);
stage.addEventListener(MouseEvent.MOUSE_UP,liftMouseUp);
}
// 将位图切成小片
private function makePuzzlePieces(bitmapData:BitmapData) {
puzzleObjects = new Array();
for(var x:uint=0;x<numPiecesHoriz;x++) {
for (var y:uint=0;y<numPiecesVert;y++) {
// 创建新的小块bitmap和sprite
var newPuzzlePieceBitmap:Bitmap = new Bitmap(new BitmapData(pieceWidth,pieceHeight));
newPuzzlePieceBitmap.bitmapData.copyPixels(bitmapData,new Rectangle(x*pieceWidth,y*pieceHeight,pieceWidth,pieceHeight),new Point(0,0));
var newPuzzlePiece:Sprite = new Sprite();
newPuzzlePiece.addChild(newPuzzlePieceBitmap);
// 放置在底部的sprite中(没被拖拽)
otherPieces.addChild(newPuzzlePiece);
// 创建对象 储存在数组中
var newPuzzleObject:Object = new Object();
newPuzzleObject.loc = new Point(x,y); // 拼图中的位置
newPuzzleObject.dragOffset = null; // 光标偏移量
newPuzzleObject.piece = newPuzzlePiece;
newPuzzlePiece.addEventListener(MouseEvent.MOUSE_DOWN,clickPuzzlePiece);
puzzleObjects.push(newPuzzleObject);
}
}
// 随机放置拼图小块
shufflePieces();
}
// 小块的随机位置
public function shufflePieces() {
// 选取随机的x和y
for(var i in puzzleObjects) {
puzzleObjects[i].piece.x = Math.random()*400+50;
puzzleObjects[i].piece.y = Math.random()*250+50;
}
// 将所有小块约束在10*10的小格内
lockPiecesToGrid();
}
public function clickPuzzlePiece(event:MouseEvent) {
// 单击位置
var clickLoc:Point = new Point(event.stageX, event.stageY);
beingDragged = new Array();
//找到点击的小块
for(var i in puzzleObjects) {
if (puzzleObjects[i].piece == event.currentTarget) { // this is it
// 添加到拖拽数组
beingDragged.push(puzzleObjects[i]);
// 得到偏移值 (单击位置与小块的距离)
puzzleObjects[i].dragOffset = new Point(clickLoc.x - puzzleObjects[i].piece.x, clickLoc.y - puzzleObjects[i].piece.y);
// 底部移动到顶部
selectedPieces.addChild(puzzleObjects[i].piece);
// 找到和当前小块锁定的小块
findLockedPieces(i,clickLoc);
break;
}
}
}
// 根据鼠标位置移动所有选择的小块
public function movePieces(event:Event) {
for (var i in beingDragged) {
beingDragged[i].piece.x = mouseX - beingDragged[i].dragOffset.x;
beingDragged[i].piece.y = mouseY - beingDragged[i].dragOffset.y;
}
}
// 找出一起移动的小块
public function findLockedPieces(clickedPiece:uint, clickLoc:Point) {
// 创建一个数组,保存所有小块对象(除了被单击的小块),以距离排序
var sortedObjects:Array = new Array();
for (var i in puzzleObjects) {
if (i == clickedPiece) continue;
sortedObjects.push({dist: Point.distance(puzzleObjects[clickedPiece].loc,puzzleObjects[i].loc), num: i});
}
sortedObjects.sortOn("dist",Array.DESCENDING);
// 直到发现所有的小块连接上循环中止
do {
//发现连接就设置为ture,若遍历所有未连接的小块,却没有发现连接,则说明我们已经找到了连接的小块,否则继续循环。
var oneLinkFound:Boolean = false;
// 查看所有的小块 从最近的开始
for(i=sortedObjects.length-1;i>=0;i--) {
var n:uint = sortedObjects[i].num; //实际的小块编号
// 得到与被单击小块之间的相对位置
var diffX:int = puzzleObjects[n].loc.x - puzzleObjects[clickedPiece].loc.x;
var diffY:int = puzzleObjects[n].loc.y - puzzleObjects[clickedPiece].loc.y;
// 查看该对象是否放置正确以连接在被单击的小块上
if (puzzleObjects[n].piece.x == (puzzleObjects[clickedPiece].piece.x + pieceWidth*diffX)) {
if (puzzleObjects[n].piece.y == (puzzleObjects[clickedPiece].piece.y + pieceHeight*diffY)) {
//查看当前对象是否与被选择的对象相邻
if (isConnected(puzzleObjects[n])) {
// 添加进选择列表,并设置偏移量
beingDragged.push(puzzleObjects[n]);
puzzleObjects[n].dragOffset = new Point(clickLoc.x - puzzleObjects[n].piece.x, clickLoc.y - puzzleObjects[n].piece.y);
// 移动到顶部的 sprite
selectedPieces.addChild(puzzleObjects[n].piece);
// 发现连接,从数组中移除
oneLinkFound = true;
sortedObjects.splice(i,1);
}
}
}
}
} while (oneLinkFound);
}
// 得到一个小块,并判断是否与已选择的小块相邻
public function isConnected(newPuzzleObject:Object):Boolean {
for(var i in beingDragged) {
var horizDist:int = Math.abs(newPuzzleObject.loc.x - beingDragged[i].loc.x);
var vertDist:int = Math.abs(newPuzzleObject.loc.y - beingDragged[i].loc.y);
if ((horizDist == 1) && (vertDist == 0)) return true;
if ((horizDist == 0) && (vertDist == 1)) return true;
}
return false;
}
// 舞台发出鼠标释放事件,拖拽结束
public function liftMouseUp(event:MouseEvent) {
// 约束所有的小块
lockPiecesToGrid();
// 将小块移回到底部
for(var i in beingDragged) {
otherPieces.addChild(beingDragged[i].piece);
}
// 清除拖拽的数组
beingDragged = new Array();
// 判断游戏是否结束
if (puzzleTogether()) {
cleanUpJigsaw();
gotoAndStop("gameover");
}
}
// 将所有的拼图放置在最接近的10*10的位置上
public function lockPiecesToGrid() {
for(var i in puzzleObjects) {
puzzleObjects[i].piece.x = 10*Math.round(puzzleObjects[i].piece.x/10);
puzzleObjects[i].piece.y = 10*Math.round(puzzleObjects[i].piece.y/10);
}
}
public function puzzleTogether():Boolean {
for(var i:uint=1;i<puzzleObjects.length;i++) {
// 得到与第一个对象相邻的相对距离
var diffX:int = puzzleObjects[i].loc.x - puzzleObjects[0].loc.x;
var diffY:int = puzzleObjects[i].loc.y - puzzleObjects[0].loc.y;
// 查看该对象是否放置正确以与第一个对象链接
if (puzzleObjects[i].piece.x != (puzzleObjects[0].piece.x + pieceWidth*diffX)) return false;
if (puzzleObjects[i].piece.y != (puzzleObjects[0].piece.y + pieceHeight*diffY)) return false
}
return true;
}
public function cleanUpJigsaw() {
removeChild(selectedPieces);
removeChild(otherPieces);
selectedPieces = null;
otherPieces = null;
puzzleObjects = null;
beingDragged = null;
removeEventListener(Event.ENTER_FRAME,movePieces);
stage.removeEventListener(MouseEvent.MOUSE_UP,liftMouseUp);
}
}
}