/**
* Copyright momasahiro321 ( http://wonderfl.net/user/momasahiro321 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/xF3O
*/
package
{
import com.bit101.components.Calendar;
import com.bit101.components.CheckBox;
import com.bit101.components.Label;
import com.bit101.components.NumericStepper;
import com.bit101.components.PushButton;
import com.bit101.components.Window;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
[SWF(frameRate="60")]
public class Main extends Sprite
{
private var window:Window;
private var w:int;
private var h:int;
private var container:Sprite = new Sprite();
private var groups:Array = new Array();
private var completed:Window;
public function Main():void
{
//サイズウィンドウ
addChild(container);
window = new Window(this, 0, 0, "Size");
window.width = 250;
window.x = 108;
window.y = 183;
var widthStepper:NumericStepper = new NumericStepper(window);
var heightStepper:NumericStepper = new NumericStepper(window);
widthStepper.x = 10;
heightStepper.x = 130;
widthStepper.y = heightStepper.y = 30;
widthStepper.minimum = heightStepper.minimum = 2;
widthStepper.value = heightStepper.value = 5;
var label:Label = new Label(window, 105, 30, "×");
var start:PushButton = new PushButton(window, 140, 70, "Start", function(e:MouseEvent):void
{
window.visible = false;
w = widthStepper.value;
h = heightStepper.value;
if (w < 1)
{
w = 2;
}
if (h < 2)
{
h = 2;
}
create();
});
Edge.init();
}
public function piecesHitTest(group:Group, checkFunction:Function):void
{
//パズル同士の当たり判定
loop: for each(var piece:Piece in group.pieces)
{
for each(var otherGroup:Group in groups)
{
if (group.id != otherGroup.id)
{
for each(var otherPiece:Piece in otherGroup.pieces)
{
if (piece.indexX != otherPiece.indexX || piece.indexY != otherPiece.indexY)
{
if (piece.hitTestObject(otherPiece))
{
if (checkFunction(piece, otherPiece, otherGroup))
{
removeGroup(group);
//多重ループを抜ける
break loop;
}
}
}
}
}
}
}
}
//ピースのグループを削除
public function removeGroup(groupA:Group):void
{
for (var i:int = 0; i < groups.length;i++)
{
if (groupA.id == groups[i].id)
{
groups.splice(i, 1);
break;
}
}
if (groups.length == 1)
{
completed.visible = true;
}
}
//ピースを生成
private function create():void
{
var edges:Array = new Array();
for (var hi:int = 0; hi < 2 * h + 1; hi++)
{
var line:Array = new Array();
var wi:int = 0;
var angle:int = 0;
if (hi % 2 == 0)
{
for (wi = 0; wi < w; wi++)
{
if (hi == 0)
{
line.push(new Edge(1, true));
}
else
{
angle = hi % 4 + 1;
if (wi % 2 == 0 || (int)(Math.random() * 3) == 0)
{
angle = 4 - angle;
}
line.push(new Edge(angle , hi == 2 * h));
}
}
}
else
{
for (wi = 0; wi < w + 1; wi++)
{
if (wi == 0)
{
line.push(new Edge(2, true));
}
else
{
angle = wi % 2 * 2;
if (hi % 4 == 1)
{
angle = 2 - angle;
}
line.push(new Edge(angle, wi == w));
}
}
}
edges.push(line);
completed = new Window(this, 183, 223, "Completed!");
completed.width = 100;
completed.height = 20;
completed.visible = false;
}
for (var hj:int = 0; hj < h; hj++)
{
for (var wj:int = 0; wj < w; wj++)
{
var piece:Group = new Group(new Piece(
[edges[2 * hj + 1][wj + 1],
edges[2 * hj][wj],
edges[2 * hj + 1][wj],
edges[2 * hj + 2][wj]], wj, hj));
piece.container = container;
piece.hitTestFunction = piecesHitTest;
piece.x = Math.random() * 100 * w + 50;
piece.y = Math.random() * 100 * h + 50;
container.addChild(piece);
groups.push(piece);
piece.id = groups.length - 1;
}
}
container.scaleX = container.scaleY = 465 / 200 / Math.max(w, h);
container.x = (465 - container.width) / 2;
container.y = (465 - container.height) / 2;
}
}
}
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
import flash.geom.Point;
import flash.utils.ByteArray;
import flash.events.Event;
//ピースのグループ
class Group extends Sprite
{
public var id:int;
public var container:Sprite;
public var pieces:Array = new Array();
public var hitTestFunction:Function;
private var margin:Point = new Point();
private var mousePressing:Boolean = false;
public function Group(piece:Piece):void
{
addPiece(piece);
addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
addEventListener(MouseEvent.MOUSE_UP, mouseUp);
addEventListener(Event.ENTER_FRAME, enterFrame);
}
//上下左右どこにつくか
public function check(pieceA:Piece, pieceB:Piece, groupB:Group):Boolean
{
var pA:Point = pieceA.localToGlobal(new Point(0, 0));
var pB:Point = pieceB.localToGlobal(new Point(0, 0));
var deg:Number = Math.atan2(pA.y - pB.y, pA.x - pB.x) * 180 / Math.PI;
if (45 <= deg && deg < 135)
{
if (pieceA.indexX == pieceB.indexX && pieceA.indexY - 1 == pieceB.indexY)
{
groupB.addGroup(pieceB, this);
return true;
}
}
else if (-45 <= deg && deg < 45)
{
if (pieceA.indexX - 1 == pieceB.indexX && pieceA.indexY == pieceB.indexY)
{
groupB.addGroup(pieceB, this);
return true;
}
}
else if (-135 <= deg && deg < -45)
{
if (pieceA.indexX == pieceB.indexX && pieceA.indexY + 1 == pieceB.indexY)
{
groupB.addGroup(pieceB, this);
return true;
}
}
else
{
if (pieceA.indexX + 1 == pieceB.indexX && pieceA.indexY == pieceB.indexY)
{
groupB.addGroup(pieceB, this);
return true;
}
}
return false;
}
public function addGroup(origon:Piece, group:Group):void
{
for each(var piece:Piece in group.pieces)
{
addPiece(piece);
piece.x = origon.x + (piece.indexX - origon.indexX) * 100;
piece.y = origon.y + (piece.indexY - origon.indexY) * 100;
}
}
public function addPiece(piece:Piece):void
{
addChild(piece);
pieces.push(piece);
}
private function mouseDown(e:Event):void
{
mousePressing = true;
margin.x = mouseX;
margin.y = mouseY;
container.setChildIndex(this, container.numChildren - 1);
}
private function mouseUp(e:Event):void
{
mousePressing = false;
hitTestFunction(this, check);
}
private function enterFrame(e:Event):void
{
if (mousePressing)
{
x = (stage.mouseX - container.x) / container.scaleX - margin.x;
y = (stage.mouseY - container.y) / container.scaleY - margin.y;
}
}
}
//ピース
class Piece extends Sprite
{
public var indexX:int = 0;
public var indexY:int = 0;
public function Piece(edges:Array, ix:int, iy:int):void
{
var points:Array = [];
points = points.concat(edges[0].getData(0));
points = points.concat(edges[1].getData(1));
points = points.concat(edges[2].getData(2));
points = points.concat(edges[3].getData(3));
//拡大、縮小で線の太さを変えない
graphics.lineStyle(1, 0x000000, 1, true, "none", "round", "round");
graphics.beginFill(0xF5F5F5);
graphics.moveTo(points[0].x, points[0].y);
for (var i:int = 1; i < points.length; i++)
{
graphics.lineTo(points[i].x, points[i].y);
}
graphics.endFill();
indexX = ix;
indexY = iy;
}
}
//ピースの端
class Edge
{
private static const HEAD:Array //出っ張りの頂点データ(半分)
= [[new Point(0, 50), new Point( -5, 30), new Point( -5, 20), new Point( -2, 9),
new Point(2, 6), new Point(11, 13), new Point(21, 10), new Point(25, 5)]];
private static const FLAT:Array //出っ張ってない頂点データ
=[[new Point(0, -50), new Point(0, 50)], [new Point(50, 0), new Point( -50, 0)],
[new Point(0, 50), new Point(0, -50)], [new Point( -50, 0), new Point(50, 0)]];
private var data:Array;
public var angle:int;
public static function init():void
{
//対象コピー、回転させた頂点データを追加
for (var i:int = 0; i < 8; i++)
{
HEAD[0].push(new Point(HEAD[0][7 - i].x, -HEAD[0][7 - i].y));
}
for (var xi:int = 1; xi < 4; xi++)
{
HEAD.push([]);
for (var yi:int = 0; yi < 16; yi++)
{
HEAD[xi].push(new Point(HEAD[xi - 1][yi].y, -HEAD[xi - 1][yi].x));
}
}
}
//頂点データから出っ張りの形をランダムに変形する
public function Edge(angle:int, type:Boolean = false)
{
this.angle = angle;
if (type)
{
data = clone(FLAT[angle]);
}
else
{
var randomX:int = Math.random() * 10 - 5;
var randomY:int = Math.random() * 10 - 5;
data = clone(HEAD[angle]);
for (var i:int = 3; i < 13; i++)
{
data[i].x += int(randomX + (Math.random() * 2 -1));
data[i].y += int(randomY + (Math.random() * 2 -1));
}
}
}
public function getData(position:int):Array
{
var re:Array = clone(data);
for (var i:int = 0; i < data.length; i++)
{
switch(position)
{
case 0:
re[i].x += 50;
break;
case 1:
re[i].y -= 50;
break;
case 2:
re[i].x -= 50;
break;
case 3:
re[i].y += 50;
break;
}
}
if (angle != position)
{
re.reverse();
}
return re;
}
//配列のコピーを作成
private static function clone(source:Object):*
{
var ba:ByteArray = new ByteArray();
ba.writeObject(source);
ba.position = 0;
return(ba.readObject());
}
}