/**
* Copyright otherone ( http://wonderfl.net/user/otherone )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/zwht
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import nape.constraint.PivotJoint;
import nape.geom.Vec2;
import nape.phys.Body;
import nape.phys.BodyList;
import nape.phys.BodyType;
import nape.shape.Circle;
import nape.shape.Polygon;
import nape.space.Space;
import nape.util.BitmapDebug;
import nape.util.Debug;
/**
* ...
* @author nekome
*/
public class Main2 extends Sprite
{
private var space:Space;// 空間
private var debug:Debug;// デバッグ用
private var gravity:Vec2;
private var reverseNum:int=1;
private var tongari:Bitmap;
private var _imgLoader:Loader;
private var _imgLoaderInfo:LoaderInfo;
public function Main2():void
{
// entry point
imageLoad();
}
private function imageLoad(e:Event = null):void
{
var url:String = "http://works.mztm.jp/moriya/temp/images/tongari.png";
//var url:String = "http://assets.wonderfl.net/images/related_images/9/9b/9b19/9b19a4e0096ca87a11d67620dabd0d50d8b519b6m";
var urlReq:URLRequest = new URLRequest(url);
var context:LoaderContext = new LoaderContext();
context.checkPolicyFile = true;
_imgLoader = new Loader();
_imgLoaderInfo = _imgLoader.contentLoaderInfo;
_imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageloaded);
_imgLoader.load(urlReq, context);
}
private function onImageloaded(e:Event):void
{
var bmd:BitmapData = new BitmapData(_imgLoader.width, _imgLoader.height,true,0x00ffffff);
bmd.draw(_imgLoader);
tongari = new Bitmap(bmd);
init();
}
public function init():void
{
// 空間を作成
gravity = new Vec2(0, 500);// 重力
space = new Space(gravity);
// デバッグ表示を設定
debug = new BitmapDebug(stage.stageWidth, stage.stageHeight, 0xFFFFFF);
addChild(debug.display);
// 空間に地面を配置
var floorBody:Body = new Body(BodyType.STATIC);// Body
var floorShapeTop:Polygon = new Polygon(Polygon.rect(0, -10, stage.width, 10));// 形状
var floorShapeBottom:Polygon = new Polygon(Polygon.rect(0, stage.height - 50, stage.width, 50));// 形状
var floorShapeLeft:Polygon = new Polygon(Polygon.rect(0, 0, 10,stage.height));// 形状
var floorShapeRight:Polygon = new Polygon(Polygon.rect(stage.stageWidth-10, 0, 10,stage.height));// 形状
floorBody.shapes.add(floorShapeTop);// 形状をBodyへ追加
floorBody.shapes.add(floorShapeBottom);// 形状をBodyへ追加
floorBody.shapes.add(floorShapeLeft);// 形状をBodyへ追加
floorBody.shapes.add(floorShapeRight);// 形状をBodyへ追加
space.bodies.add(floorBody);// Bodyを空間へ追加
// 空間にボールを配置
var circleBody:Body = new Body();// Body
var circleShape:Circle = new Circle(50);// 形状
circleShape.material.elasticity = 1;// 弾力
circleShape.material.density = 4;// 密度
circleBody.shapes.add(circleShape);// 形状をBodyへ追加
circleBody.position.setxy(stage.width/2, 0);// 空間内の座標
circleBody.velocity.setxy(0, 100);// 空間内の初速
space.bodies.add(circleBody);// Bodyを空間へ追加
var playerBody:Body = new Body();// Body
var squareShape:Polygon = new Polygon(Polygon.rect(0, 0,100, 100));// 形状
squareShape.material.elasticity = 3;// 弾力
squareShape.material.density = 10;// 密度
playerBody.shapes.add(squareShape);// 形状をBodyへ追加
playerBody.position.setxy(stage.width/2, 0);// 空間内の座標
playerBody.velocity.setxy(0, 100);// 空間内の初速
space.bodies.add(playerBody);// Bodyを空間へ追加
var cogIso:BitmapDataIso = new BitmapDataIso((tongari).bitmapData, 0x80);
var cogBody:Body = IsoBody.run(cogIso, cogIso.bounds);
for (var i:int = 0; i < 2; i++) {
for (var j:int = 0; j < 2; j++) {
var body:Body = cogBody.copy();
body.position.setxy(100 + tongari.width*i, 100+tongari.height*j);
body.space = space;
var graphic:DisplayObject = cogIso.graphic();
//graphic.alpha = 0.6;
addChild(graphic);
body.userData.graphic = graphic;
}
}
// フレーム処理を開始
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(MouseEvent.CLICK, fnClicked);
}
private function fnClicked(e:MouseEvent):void
{
(reverseNum< 0)?(reverseNum=1):(reverseNum=-1);
gravity.set(new Vec2(Math.random() * 1000*reverseNum, Math.random() * 1000*reverseNum));
space.gravity = gravity;
}
// フレーム処理
private function enterFrameHandler(e:Event):void {
// 空間の時間を進めます。
space.step(1 / stage.frameRate);
// デバッグ用の表示
debug.clear();
debug.draw(space);
debug.flush();
for (var i:int = 0; i < space.liveBodies.length; i++) {
var body:Body = space.liveBodies.at(i);
var graphic:DisplayObject = body.userData.graphic;
if (graphic == null) continue;
var graphicOffset:Vec2 = body.userData.graphicOffset;
var position:Vec2 = body.localPointToWorld(graphicOffset);
graphic.x = position.x;
graphic.y = position.y;
graphic.rotation = (body.rotation * 180/Math.PI) % 360;
position.dispose();
}
}
}
}
import nape.geom.AABB;
import nape.geom.GeomPoly;
import nape.geom.GeomPolyList;
import nape.geom.IsoFunction;
import nape.geom.MarchingSquares;
import nape.geom.Vec2;
import nape.phys.Body;
import nape.shape.Polygon;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
class IsoBody {
public static function run(iso:IsoFunction, bounds:AABB, granularity:Vec2=null, quality:int=2, simplification:Number=1.5):Body {
var body:Body = new Body();
if (granularity==null) granularity = Vec2.weak(8, 8);
var polys:GeomPolyList = MarchingSquares.run(iso, bounds, granularity, quality);
for (var i:int = 0; i < polys.length; i++) {
var p:GeomPoly = polys.at(i);
var qolys:GeomPolyList = p.simplify(simplification).convexDecomposition(true);
for (var j:int = 0; j < qolys.length; j++) {
var q:GeomPoly = qolys.at(j);
body.shapes.add(new Polygon(q));
// Recycle GeomPoly and its vertices
q.dispose();
}
// Recycle list nodes
qolys.clear();
// Recycle GeomPoly and its vertices
p.dispose();
}
// Recycle list nodes
polys.clear();
// Align body with its centre of mass.
// Keeping track of our required graphic offset.
var pivot:Vec2 = body.localCOM.mul(-1);
body.translateShapes(pivot);
body.userData.graphicOffset = pivot;
return body;
}
}
class DisplayObjectIso implements IsoFunction {
public var displayObject:DisplayObject;
public var bounds:AABB;
public function DisplayObjectIso(displayObject:DisplayObject):void {
this.displayObject = displayObject;
this.bounds = AABB.fromRect(displayObject.getBounds(displayObject));
}
public function iso(x:Number, y:Number):Number {
// Best we can really do with a generic DisplayObject
// is to return a binary value {-1, 1} depending on
// if the sample point is in or out side.
return (displayObject.hitTestPoint(x, y, true) ? -1.0 : 1.0);
}
}
class BitmapDataIso implements IsoFunction {
public var bitmap:BitmapData;
public var alphaThreshold:Number;
public var bounds:AABB;
public function BitmapDataIso(bitmap:BitmapData, alphaThreshold:Number = 0x80):void {
this.bitmap = bitmap;
this.alphaThreshold = alphaThreshold;
bounds = new AABB(0, 0, bitmap.width, bitmap.height);
}
public function graphic():DisplayObject {
return new Bitmap(bitmap);
}
public function iso(x:Number, y:Number):Number {
// Take 4 nearest pixels to interpolate linearly.
// This gives us a smooth iso-function for which
// we can use a lower quality in MarchingSquares for
// the root finding.
var ix:int = int(x); var iy:int = int(y);
//clamp in-case of numerical inaccuracies
if(ix<0) ix = 0; if(iy<0) iy = 0;
if(ix>=bitmap.width) ix = bitmap.width-1;
if(iy>=bitmap.height) iy = bitmap.height-1;
// iso-function values at each pixel centre.
var a11:Number = alphaThreshold - (bitmap.getPixel32(ix,iy)>>>24);
var a12:Number = alphaThreshold - (bitmap.getPixel32(ix+1,iy)>>>24);
var a21:Number = alphaThreshold - (bitmap.getPixel32(ix,iy+1)>>>24);
var a22:Number = alphaThreshold - (bitmap.getPixel32(ix+1,iy+1)>>>24);
// Bilinear interpolation for sample point (x,y)
var fx:Number = x - ix; var fy:Number = y - iy;
return a11*(1-fx)*(1-fy) + a12*fx*(1-fy) + a21*(1-fx)*fy + a22*fx*fy;
}
}