Nape 練習

by otherone
参考
http://napephys.com/samples.html#as3-BodyFromGraphic

・クリックで重力を変化させます。
・ドラッグ操作難しいなぁー

♥0 | Line 195 | Modified 2014-03-03 13:42:53 | MIT License
play

Related images

ActionScript3 source code

/**
 * 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;

    }

}

Forked