2009年4月29日水曜日

[Flex][AIR]15パズルVer.0.1


Flex Builder3でFlexとかActionScriptの勉強をしているわけですが、
15パズルを作りたくなったので作ってみました。
最低限の機能はできたのでVer.0.1としてあげます。

制作にあたっては、こちらの記事こちらの本を参考にさせてもらいました。

ドラッグ&ドロップで自動的に画像を16分割します。
画像ファイルそのままの大きさで16分割するので大きい画像はパズルに向かないかも。
今後そういうとこを直して機能を追加していこうと思ってます。

ソースコードは↓
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" nativeDragEnter="onDragEnter(event);" nativeDragDrop="onDragDrop(event);" width="500" height="400" viewSourceURL="srcview/index.html">
<mx:MenuBar labelField="@label" itemClick="useFile(event)" width="100%" id="myMenu">
<mx:dataProvider>
<mx:XMLList>
<Menu label="操作">
<MenuItem label="スタート" />
</Menu>
</mx:XMLList>
</mx:dataProvider>
</mx:MenuBar>
<mx:Image id="myImage" width="100%" height="100%" />
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.MenuEvent;

// 画像のロード判定用
private var loadEnd:Boolean = false;
private var file_ary:Array;
// 1ピースの幅
private var pieceWidth:Number;
// 1ピースの高さ
private var pieceHeight:Number;
// 空ピースの番号
private var empty:int;
// 完成確認用配列
private var order:Array = new Array();

// メニュー用の関数
private function useFile(e:MenuEvent):void {
if(e.label == "スタート") {
shuffle();
}
}

// ドラッグ&ドロップでロード
private function onDragEnter(event:NativeDragEvent):void {
trace("entered");
var cb:Clipboard = event.clipboard;
if(cb.hasFormat(ClipboardFormats.FILE_LIST_FORMAT)) {
// ドロップを許可
NativeDragManager.acceptDragDrop(this);
}
}

private function onDragDrop(event:NativeDragEvent):void {
if(loadEnd) {
for(var i:uint = 0; i <= 15; i++) {
myImage.removeChild(myImage.getChildByName(String(i)));
}
}

var cb:Clipboard = event.clipboard;
file_ary = cb.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
trace("ファイル名:" + File(file_ary[0]).name);

LoaderRequest();
}

private function LoaderRequest():void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, LoadCompleted);
var request:URLRequest = new URLRequest(File(file_ary[0]).url);
loader.load(request);
}

private function LoadCompleted(event:Event):void {
// 画像はBitmapでロード
var bitmapImage:Bitmap = Bitmap(event.target.loader.content);

empty = 15;
pieceWidth = bitmapImage.width / 4;
pieceHeight = bitmapImage.height / 4;

//ピース並べ
for(var i:uint = 0; i < 15; i++) {
// ピースと同じ大きさのビットマップをつくる
var newPieceBitmap:Bitmap = new Bitmap(new BitmapData(pieceWidth, pieceHeight));
// ロードした画像から新しく作ったビットマップにコピー
newPieceBitmap.bitmapData.copyPixels(bitmapImage.bitmapData, new Rectangle((i % 4) * pieceWidth, Math.floor(i / 4) * pieceHeight, pieceWidth, pieceHeight), new Point(0, 0));

// ピースの描画
var newPiece:Sprite = new Sprite();
newPiece.addChild(newPieceBitmap);
newPiece.width = pieceWidth;
newPiece.height = pieceHeight;
newPiece.x = (i % 4) * (pieceWidth + 5) + 20;
newPiece.y = Math.floor(i / 4) * (pieceHeight + 5) + 30;
newPiece.name = String(i);
newPiece.addEventListener(MouseEvent.CLICK, click);
myImage.addChild(newPiece);
}
// 空ピースは白い長方形
var emptyPieace:Sprite = new Sprite();
emptyPieace.graphics.beginFill(0xffffff);
emptyPieace.x = 3 * (pieceWidth + 5) + 20;
emptyPieace.y = Math.floor(3) * (pieceHeight + 5) + 30;
emptyPieace.graphics.drawRect(0, 0, pieceWidth, pieceHeight);
emptyPieace.graphics.endFill();
emptyPieace.name = String(15);
myImage.addChild(emptyPieace);

// 完成判定のためIndexをセット
for(var j:uint = 0; j <= 15; j++) {
myImage.setChildIndex(myImage.getChildByName(String(j)), j);
}

// ピクチャの大きさに合わせてウィンドウの大きさを変更
nativeWindow.width = bitmapImage.width + 60;
nativeWindow.height = bitmapImage.height + 105;
loadEnd = true;
}

// ランダムシャッフル
private function shuffle():void {
var count:uint = 10000;
var imgNum:uint;

for(var i:uint = 0; i < count; i++) {
imgNum = Math.floor(Math.random() * 15);
if(checkMove(imgNum)) {
pieceMove(imgNum);
}
}
}

// ピースクリック時の処理
private function click(event:MouseEvent):void {
//ピースの番号
var pieaceNumber:int = event.currentTarget.name;
trace("click:" + pieaceNumber);
if(checkMove(pieaceNumber)) {
pieceMove(pieaceNumber);
}
}

// ピースが動かせるかチェック
private function checkMove(pieaceNumber:int):Boolean {
var result:Boolean = false;

if((pieaceNumber == (empty - 4)) || (pieaceNumber == (empty + 4)))
result = true;
else if(((pieaceNumber % 4) != 0) && ((pieaceNumber - 1) == empty))
result = true;
else if(((pieaceNumber % 4) != 3) && ((pieaceNumber + 1) == empty))
result = true;

return result;
}

// ピース移動
private function pieceMove(pieaceNumber:int):void {
var oldEmpty:int = empty;
empty = pieaceNumber;
myImage.getChildByName(String(oldEmpty)).x = (pieceWidth + 5) * (pieaceNumber % 4) + 20;
myImage.getChildByName(String(oldEmpty)).y = (pieceHeight + 5) * Math.floor(pieaceNumber / 4) + 30;
myImage.getChildByName(String(oldEmpty)).name = String(pieaceNumber);
myImage.getChildByName(String(pieaceNumber)).x = (pieceWidth + 5) * (oldEmpty % 4) + 20;
myImage.getChildByName(String(pieaceNumber)).y = (pieceHeight + 5) * Math.floor(oldEmpty / 4) + 30;
myImage.getChildByName(String(pieaceNumber)).name = String(oldEmpty);
indexExchange(pieaceNumber);
}

// Index交換用関数
private function indexExchange(index:int):void {
var indexTemp:int;

indexTemp = myImage.getChildIndex(myImage.getChildByName(String(index)));
myImage.setChildIndex(myImage.getChildAt(myImage.getChildIndex(myImage.getChildByName(String(index)))), myImage.getChildIndex(myImage.getChildByName(String(empty))));
myImage.setChildIndex(myImage.getChildAt(myImage.getChildIndex(myImage.getChildByName(String(empty)))), indexTemp);

// ピース合わせ確認
checkComplete(); }

// 完成判定関数
private function checkComplete():void {
var complete:Boolean = true;
for(var i:uint = 0; i < 15; i++) {
if(!(i == myImage.getChildIndex(myImage.getChildByName(String(i))))) {
// 不一致があった場合
complete = false;
}
}
// 全て一致した場合
if(complete) {
trace("Complete!");
var alert:Alert = Alert.show("complete");
alert.isPopUp = false;
alert.cacheAsBitmap = true;
}
}
]]>
</mx:Script>
</mx:WindowedApplication>
AIRファイルのダウンロード

---------------------------------
2009/9/4 追記

AIRファイルのダウンロードは、Ver.0.1を間違えて消してしまったためVer.0.15のみです。
上のリンクからたどるか、こちらからDLできます。

0 件のコメント:

コメントを投稿