forked from: flash on 2010-6-24

by mtok forked from flash on 2010-6-24 (diff: 112)
...
@author Motoki Matsumoto
♥0 | Line 396 | Modified 2010-06-25 08:28:29 | MIT License
play

ActionScript3 source code

/**
 * Copyright mtok ( http://wonderfl.net/user/mtok )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/idAK
 */

package  
{
    import flash.display.Sprite;
    import flash.events.Event;
    /**
     * ...
     * @author Motoki Matsumoto
     */
    public class FoceFieldTest2 extends Sprite
    {
        
        public function FoceFieldTest2() 
        {
            addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }
        
        private function addedToStageHandler(e:Event):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
            initialize();
        }
        
        private function initialize():void
        {
            addChild( new ForceFieldDemo());
        }
        
    }
}

import Box2D.Collision.b2AABB;
import Box2D.Collision.b2ContactPoint;
import Box2D.Collision.Shapes.b2CircleDef;
import Box2D.Common.Math.b2Vec2;
import Box2D.Common.Math.b2XForm;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2DebugDraw;
import Box2D.Dynamics.b2World;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.utils.Dictionary;
class ForceFieldDemo extends Sprite {
    private var _cellSize:Number;
    private var _grid:Grid;
    private var _mpos:Point;
    private var _debug:Sprite;
    private var _box2d:Box2DSys;
    private var _v0:b2Vec2 = new b2Vec2(0, 0);
    public function ForceFieldDemo()
    {
        super();
        addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        addEventListener(Event.ENTER_FRAME, enterFrameHnalder);
    }
    
    private function enterFrameHnalder(e:Event):void 
    {
        _box2d.update();
        _update();
        _redraw();
    }
    
    private function _update():void
    {
        _grid.cells.forEach(updateCell, null);
    }    
    
    private function updateCell(c:Cell, i:int, ary:Vector.<Cell>):void
    {
        var p:Point = c.data[1];
        p.x *= 0.98;
        p.y *= 0.98;
    }
    private function _redraw():void
    {
        _grid.forEach(redrawCells, null);
    }
    
    private function redrawCells(cell:Cell, r:int, c:int, g:Grid):void
    {
        var s:Square = cell.data[0];
        var p:Point = cell.data[1];
        s.color = getColor(p.x, p.y);
    }
    private function getColor(a:Number, b:Number):uint
    {
        //trace(a, b);
        var n:Number = 1;
        var offset:Number = n * 127;
        var _a:int = Math.round (( a + offset) / n);
        var _b:int = Math.round (( b + offset) / n);
        //trace(_a, _b);
        if (_a < 0) {
            _a = 0;
        }
        if (_a > 255) {
            _a = 255;
        }
        if (_b < 0) {
            _b = 0;
        }
        if (_b > 255) {
            _b < 255;
        }
        
        return _a << 16 | _b;
    }
    
    private function addedToStageHandler(e:Event):void 
    {
        removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        initialize();
    }
    
    private function initialize():void
    {
        var bg:Sprite = Square.createSquare(stage.stageWidth, 0xffffff);
        addChild(bg);
        
        addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
        
        _mpos = new Point();
        
        _cellSize = 25;
        var r:int = Math.ceil( stage.stageWidth / _cellSize);
        var c:int = Math.ceil( stage.stageHeight / _cellSize);
        _grid = new Grid(r, c);
        
        var s:Sprite;
        for (var i:int = 0; i < r * c; i++) {
            var cell:Cell = _grid.cells[i];
            addChild(s = Square.createSquare(_cellSize) );
            s.x = (i % r) * _cellSize;
            s.y = Math.floor(i / r) * _cellSize;
            cell.data = [s, new Point(0,0)];
        }
        
        _box2d = new Box2DSys();
        _box2d.onUpdate = onUpdate;
        _debug = new Sprite();
        addChild(_debug);
        _box2d.setDebugSprite(_debug);
    }
    
    private function mouseMoveHandler(e:MouseEvent):void 
    {
        var mx:Number = Math.floor(mouseX / _cellSize);
        var my:Number = Math.floor(mouseY / _cellSize);
        var cell:Cell = _grid.getCellAt(mx, my);
        
        
        var dx:Number = mouseX - _mpos.x;
        var dy:Number = mouseY - _mpos.y;

        propagation(cell, 1, dx, dy, 3);
        
        _mpos.x = mouseX;
        _mpos.y = mouseY;
    }
    private function propagation(cell:Cell, gain:Number, dx:Number, dy:Number, depth:int):void 
    {
        var dic:Dictionary = new Dictionary(true);
        _propagation(cell, gain, dx, dy, depth, dic);

        var c:Cell;

        --depth;
    }
    private function _propagation(cell:Cell, gain:Number, dx:Number, dy:Number, depth:int, dic:Dictionary):void 
    {
        dic[cell] = true;
        
        var p:Point = cell.data[1];
        p.x += dx * gain;
        p.y += dy * gain;

        depth--;
        if (depth < 0) {
            return;
        }
        var c:Cell;
        var len:int = cell.neighbors.length;
        for (var i:int = 0; i < len; i++) {
            if ( (c = cell.neighbors[i]) != null) {
                if (dic[c]) {

                }else {
                    dic[c] = true;
                    _propagation(c, gain * 0.8, dx, dy, depth, dic);
                }
            }
        }
    }
    public function onUpdate(body:b2Body):void {
        var xf:b2XForm = body.GetXForm();
        if ( xf.position.x > 0 && xf.position.x < 400) {
            if (xf.position.y > 0 && xf.position.y < 400) {
                var px:int = Math.floor( xf.position.x / _cellSize);
                var py:int = Math.floor( xf.position.y / _cellSize);
                var cell:Cell = _grid.getCellAt(px, py);
                var p:Point = cell.data[1];
                body.ApplyForce( new b2Vec2(p.x * 1000, p.y * 1000), _v0);
            }
        }
        
    }
}
import flash.utils.getTimer;
class Box2DSys {
    private var _world:b2World;
    private var _t:int;
    private var _N:int = 30;
    private var _v0:b2Vec2 = new b2Vec2(0, 0);
    public var onUpdate:Function;
    public function Box2DSys()
    {
        _world = createWorld();
        _buildScene(_world);
        _t = getTimer();
    }
    public function  setDebugSprite(sprite:Sprite):void 
    {
        var dd:b2DebugDraw = new b2DebugDraw();
        dd.m_sprite = sprite;
        dd.m_drawFlags = b2DebugDraw.e_shapeBit;
        _world.SetDebugDraw(dd);
    }
    private function createWorld():b2World
    {
        var aabb:b2AABB = new b2AABB();
        aabb.lowerBound.Set( -10000, -10000);
        aabb.upperBound.Set(10000, 10000);
        var g:b2Vec2 = new b2Vec2(0, 10);
        var w:b2World = new b2World(aabb, g, true);
        return w;
    }
    private function _buildScene(world:b2World):void 
    {
        var sdef:b2CircleDef = new b2CircleDef();
        sdef.friction = 0;
        sdef.density = 1;
        sdef.restitution = 1;
        sdef.radius = 20;

        var bd:b2BodyDef = new b2BodyDef();
        
        var b:b2Body;
        
        for (var i:int = 0; i < _N; i++) {
            b = _world.CreateBody(bd);
            
            b.CreateShape(sdef);
            b.SetMassFromShapes();
            b.SetXForm(new b2Vec2(Math.random() * 490, -980 * Math.random() + 490), 0);
        }
    }
    
    public function update():void 
    {
        var b:b2Body;
        var xf:b2XForm;
        var t:int;
        t = getTimer();
        var dt:Number = (t - _t) / 1000;
        _t = t;

        b = _world.GetBodyList();
        if (b == null) return;
        do {
            xf = b.GetXForm();
            
            if(onUpdate != null) onUpdate.call(null, b);
            
            if ( xf.position.y > 500) {
                b.SetXForm(new b2Vec2(Math.random() * 490, -490 * Math.random()), 0);
                b.SetLinearVelocity(_v0);
            }
        }while (b = b.GetNext());

        _world.Step(dt, 4);
        
    }
}
class Square extends Sprite {
    private var _color:uint;
    private var _size:Number;
    public function Square()
    {
        super();
        if (stage) {
            initialize();
        }else {
            addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }
    }
    
    private function initialize():void
    {
        addEventListener(Event.RENDER, renderHandler);
        _redraw();
    }
    
    private function addedToStageHandler(e:Event):void 
    {
        removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        initialize();
    }
    public static function createSquare(size:Number, color:uint = 0):Square
    {
        var s:Square = new Square();
        s._size = size;
        s._color = color;
        return s;    
    }
    private function renderHandler(e:Event):void 
    {
        _redraw();
    }
    
    public function get color():uint { return _color; }    
    public function set color(value:uint):void 
    {
        _color = value;
        stage.invalidate();
    }
        
    public function get size():Number { return _size; }
    public function set size(value:Number):void 
    {
        _size = value;
        stage.invalidate();
    }
    private function _redraw():void
    {
        graphics.clear();
        graphics.beginFill(_color);
        graphics.drawRect(0, 0, _size, _size);
        graphics.endFill();
    }

}
class Grid {
    private var _cells:Vector.<Cell>;
    private var _rows:int;
    private var _cols:int;
    public var _dictionary:Dictionary;
    /**
     * 
     * @param    rows
     * @param    cols
     */
    public function Grid(rows:int, cols:int) {
        _rows = rows;
        _cols = cols;
        _cells = new Vector.<Cell>(_rows * _cols);
        _dictionary = new Dictionary(true);
        
        var i:int, j:int;
        for (i = 0; i < _rows * _cols; i++) {
            _cells[i] = new Cell();
            _cells[i].grid = this;
        }
        
        var c:Cell;
        c = _cells[0];
        for (j = 1; j < _rows; j++) {
            c.right = _cells[j];
            c = _cells[j];
        }
        for (i = 1; i < _cols; i++) {
            c = _cells[i * _rows];
            c.upper = _cells[( i - 1) * _rows];
            for ( j = 1; j < _rows; j++) {
                c.right = _cells[i * _rows + j];
                c = c.right;
                c.upper = _cells[(i - 1) * _rows + j];
            }
        }
    }
    public function forEach(f:Function, thisObj:*):void 
    {
        for (var i:int = 0; i < _cols; i++) {
            for (var j:int = 0; j < _rows; j++) {
                var c:Cell = _cells[_rows * i + j];
                f.call(thisObj, c, j, i, this);
            }
        }
    }
    public function getCellAt(row:int, col:int):Cell 
    {
        //note not check index
        return _cells[col*_rows + row];
    }
    public function getCell(obj:*):Cell
    {
        //data から該当するcellを取得
        return _dictionary[obj];
    }
    public function get rows():int { return _rows; }
    public function get cols():int { return _cols; }
    public function get cells():Vector.<Cell> { return _cells; }
}
class Cell {
    
    private var _data:*;
    private var _neighbors:Vector.<Cell>;
    private var _grid:Grid;
    
    public function Cell()
    {
        _neighbors = new Vector.<Cell>(4);
    }
    public function get upper():Cell { return _neighbors[0]; }
    public function set upper(value:Cell):void 
    {
        _neighbors[0] = value;
        value._neighbors[2] = this;
    }

    public function get right():Cell { return _neighbors[1]; }
    public function set right(value:Cell):void 
    {
        _neighbors[1] = value;
        value._neighbors[3] = this;
    }

    public function get under():Cell { return _neighbors[2]; }
    public function set under(value:Cell):void 
    {
        _neighbors[2] = value;
        value._neighbors[0] = this;
    }

    public function get left():Cell { return _neighbors[3]; }
    public function set left(value:Cell):void 
    {
        _neighbors[3] = value;
        value._neighbors[2] = this;
    }
    
    public function get data():* { return _data; }
    public function set data(value:*):void 
    {
        _data = value;
        _grid._dictionary[value] = this;
    }
    
    public function get grid():Grid { return _grid; }
    public function set grid(value:Grid):void 
    {
        _grid = value;
    }
    
    public function get neighbors():Vector.<Cell> { return _neighbors; }
    public function set neighbors(value:Vector.<Cell>):void 
    {
        _neighbors = value;
    }
}