In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: 粒子あやつる forked from: 流体パーティクル

--------------------------------------------------------------------------------//

http://wonderfl.net/code/23f89f2a5e8d9df21c8a72210c2a22c9c7490600
via StreamLine
http://gofar2.iobb.net/~htaka/wordpress/archives/953

フォースマップをマウスドラッグでいじります。
粒子はマウスから発生して、フォースマップに従って流れていきます。
スペースキーを押すと粒子表示/フォースマップ編集が切り替わります。
フォースマップ編集時には前に描いたフォースマップはリセットされます。
--------------------------------------------------------------------------------//
// forked from HaraMakoto's 粒子あやつる forked from: 流体パーティクル
package
{
//--------------------------------------------------------------------------------//
//    forked from 流体パーティクル
//    http://wonderfl.net/code/23f89f2a5e8d9df21c8a72210c2a22c9c7490600
//    via StreamLine
//    http://gofar2.iobb.net/~htaka/wordpress/archives/953
//
//    フォースマップをマウスドラッグでいじります。
//    粒子はマウスから発生して、フォースマップに従って流れていきます。
//    スペースキーを押すと粒子表示/フォースマップ編集が切り替わります。
//    フォースマップ編集時には前に描いたフォースマップはリセットされます。
//--------------------------------------------------------------------------------//
    
    import frocessing.display.F5MovieClip2DBmp;
    [SWF(width="465", height="465", frameRate="30")]
    public class ForceMap2 extends F5MovieClip2DBmp
    {
        private var vectorF:VectorField;
        private var strokeColor:Number;
        private var numOfLine:int = 100;
        private var myParticle:Array;
        private var drawflg:int = 0;
        
        public function ForceMap2()
        {
            super();
        }
        
        public function setup():void {
            size(465,465);
            background(0);
            vectorF = new VectorField(this,width/20,height/20,0.1,54655465);
            
            strokeColor = color(150,255,255,20);
            var i:int;
            myParticle = [];
            for(i=0;i < numOfLine;i++){
              myParticle[i] = new Particle(mouseX,mouseY,0,0,this,vectorF);
            }
            
        }
        
        public function keyPressed():void {
            switch(keyCode){
                  case 32:
                   if(drawflg==0) {
                       drawflg=1;
                       vectorF.resetVector();
                   } else {
                       drawflg=0;
                   }
                   break;
              }
        }
        
        public function draw():void {
            
            fill(0, 0, 0, 1);
            noStroke();
              rect(0, 0, width, height);
            if(drawflg==0) {
                  noFill();
                var i:int;
                for(i=0;i<numOfLine;i++) {
                    myParticle[i].draw();
                }
                noStroke();
            } else {
                vectorF.drawVector()
            }
        }
    }
}

class VectorField {
    private var numOfCellX:int;
    private var numOfCellY:int;
    private var cellWidth:Number, cellHeight:Number;
    public var cells:Array;
    private var rootMC:F5MovieClip2DBmp;
    private var mox:Number, moy:Number;
    
    public function VectorField(_root:F5MovieClip2DBmp, _numOfCellX:int, _numOfCellY:int, noiseFactor:Number, seed:int) {
        rootMC = _root;
        numOfCellX = _numOfCellX;
        numOfCellY = _numOfCellY;
        cellWidth = rootMC.width / numOfCellX;
        cellHeight = rootMC.height / numOfCellY;
        
        mox = rootMC.mouseX;
        moy = rootMC.mouseY;
        var offsetAX:Number = rootMC.mouseX;
        var offsetAY:Number = rootMC.mouseY;
        var offsetBX:Number = (Math.random()*rootMC.width)-rootMC.width/2;
        var offsetBY:Number = (Math.random()*rootMC.height)-rootMC.height/2;
        
        var i:int;
        var j:int;
        cells = [];
        for(i=0;i<numOfCellX+1; i++) {
            cells[i]=[];
        }
        for(j=0;j<numOfCellY+1;j++) {
            for(i=0;i<numOfCellX+1; i++) {
                cells[i][j] = new Cell(i,j,
                    rootMC.noise((i + offsetAX) *noiseFactor, (j+offsetAY) * noiseFactor) - 0.5,
                    rootMC.noise((i+offsetBX) *noiseFactor, (j+offsetBY) * noiseFactor ) - 0.5,
                    cellWidth, cellHeight);
            }
        }
        
        var gridData:Cell;
        //隣接するグリッドをセットしていく。
        for(j=0;j<numOfCellY+1;j++) {
            for(i=0;i<numOfCellX+1; i++) {
                gridData = cells[i][j];
                if (j > 0) {
                    var up:Cell = cells[i][j - 1];//上
                    gridData.up = up;
                    up.low = gridData;//下
                }
                if (i > 0) {
                    var left:Cell = cells[i - 1][j];//左
                    gridData.left = left;
                    left.right = gridData;//右
                }
                if (j > 0 && i > 0) {
                    var upperLeft:Cell = cells[i - 1][j - 1];
                    gridData.upperLeft = upperLeft;
                    upperLeft.lowerRight = gridData;
                }
                if (j > 0 && i < numOfCellX - 1) {
                    var upperRight:Cell = cells[i + 1][j - 1];
                    gridData.upperRight = upperRight;
                    upperRight.lowerLeft = gridData;
                }
            }
        }
        
        
    }
    
    public function getCell(_posX:Number,_posY:Number):Cell {
        return cells[int(_posX/cellWidth)][int(_posY/cellHeight)];
    }
    public function getVecX(_posX:Number,_posY:Number):Number {
        return cells[int(_posX/cellWidth)][int(_posY/cellHeight)].getVecX;
    }
    public function getVecY(_posX:Number,_posY:Number):Number {
        return cells[int(_posX/cellWidth)][int(_posY/cellHeight)].getVecY;
    }
    
    public function drawGrid():void {
        rootMC.noSmooth();
        rootMC.stroke(128,128);
        var i:int;
        for(i=0;i<numOfCellX;i++) {
            rootMC.line(cellWidth*i,0,cellWidth*i,rootMC.height);
        }
        for(i=0;i<numOfCellY;i++) {
            rootMC.line(0,cellHeight*i,rootMC.width,cellHeight*i);
        }
    }
    
    public function resetVector():void {
        var i:int,j:int;
        for(j=0;j<numOfCellY+1;j++) {
            for(i=0;i<numOfCellX+1; i++) {
                cells[i][j].resetVec();
            }
        }
    }
    public function drawVector():void {
        var drawVectorLength:Number = (cellWidth+cellHeight)/2*10;
        var mnx:Number = rootMC.mouseX;
        var mny:Number = rootMC.mouseY;
        
        rootMC.stroke(0xFFFFFF);
        var i:int,j:int;
        for(j=0;j<numOfCellY+1;j++) {
            for(i=0;i<numOfCellX+1; i++) {
                if(rootMC.isMousePressed){
                    cells[i][j].CulcMouseVec(mnx, mny, mnx-mox, mny-moy);
                    cells[i][j].updatePressure();
                }
                rootMC.line(cellWidth*i+cellWidth/2, cellHeight*j+cellHeight/2,cellWidth*i+cellWidth/2+cells[i][j].getVecX*drawVectorLength, cellHeight*j+cellHeight/2+cells[i][j].getVecY*drawVectorLength);
            }
        }
        for(j=0;j<numOfCellY+1;j++) {
            for(i=0;i<numOfCellX+1; i++) {
                if(rootMC.isMousePressed)
                    cells[i][j].apdateVelocity();
            }
        }
        mox = rootMC.mouseX;
        moy = rootMC.mouseY;
    }
}

    import frocessing.display.F5MovieClip2DBmp;
    import frocessing.math.Random;
    import flash.geom.Rectangle;
    
class BaseGridData {
    
    public var posX:int = 0;
    public var posY:int = 0;
    
    public var x:int = 0;
    public var y:int = 0;
    
    public var vecX:Number = 0;
    public var vecY:Number = 0;
    
    public var pressure:Number = 0;
    
    public var color:Number = 0;
    public var rgb:uint;
    public var rectangle:Rectangle;
}
class NullGridData extends BaseGridData {}
class Cell extends BaseGridData {
    private var cellWidth:Number, cellHeight:Number;
    public function Cell(_posX:int, _posY:int, _vecX:Number, _vecY:Number, _cW:Number, _cH:Number) {
        posX = _posX;
        posY  =_posY;
        vecX = _vecX;
        vecY = _vecY;
        cellWidth = _cW;
        cellHeight = _cH;
        x = posX * cellWidth;
        y = posY * cellHeight;
        rectangle = new Rectangle(x, y, cellWidth, cellHeight);
    }
    
    //すべてのグリッドが8方向に隣接したグリッドを持つわけではないので、
    //空のデータをセットしておく。
    public var upperLeft:BaseGridData = new NullGridData();//左上
    public var up:BaseGridData = new NullGridData();//上
    public var upperRight:BaseGridData = new NullGridData();//右上
    public var left:BaseGridData = new NullGridData();//左
    public var right:BaseGridData = new NullGridData();//右
    public var lowerLeft:BaseGridData = new NullGridData();//左下
    public var low:BaseGridData = new NullGridData();//下
    public var lowerRight:BaseGridData = new NullGridData();//右下    
    
    public function get getVecX():Number {
        return vecX;
    }
    public function get getVecY():Number {
        return vecY;
    }
    
    public function resetVec():void {
        vecX = 0;
        vecY = 0;
    }
    public function CulcMouseVec(mx:Number, my:Number, mvx:Number, mvy:Number):void {
        var dx:Number = mx - posX*cellWidth;
        var dy:Number = my - posY*cellHeight;
        var distance:Number = Math.sqrt(dx*dx+dy*dy);
        var penSize:Number = 40;
        
        if(distance<penSize) {
            if(distance<4) {
                distance=penSize;
            }
            
            var power:Number = 0.005*penSize/distance;
            vecX += mvx * power;
            vecY += mvy * power;
        }
    }
    
    public function updatePressure():void {
        var pressureX:Number = (
              upperLeft.vecX * 0.5 //左上
            + left.vecX       //左
            + lowerLeft.vecX * 0.5 //左下
            - upperRight.vecX * 0.5 //右上
            - right.vecX       //右
            - lowerRight.vecX * 0.5 //右下
        );
        var pressureY:Number = (
              upperLeft.vecY * 0.5 //左上
            + up.vecY       //上
            + upperRight.vecY * 0.5 //右上
            - lowerLeft.vecY * 0.5 //左下
            - low.vecY       //下
            - lowerRight.vecY * 0.5 //右下
        );
        pressure = (pressureX + pressureY) * 0.25;
    }
    
    public function apdateVelocity():void {
            vecX += (
                  upperLeft.pressure * 0.5 //左上
                + left.pressure       //左
                + lowerLeft.pressure * 0.5 //左下
                - upperRight.pressure * 0.5 //右上
                - right.pressure       //右
                - lowerRight.pressure * 0.5 //右下
            ) * 0.25;
            
            vecY += (
                  upperLeft.pressure * 0.5 //左上
                + up.pressure       //上
                + upperRight.pressure * 0.5 //右上
                - lowerLeft.pressure * 0.5 //左下
                - low.pressure       //下
                - lowerRight.pressure * 0.5 //右下
            ) * 0.25;
            
            vecX *= 0.99;
            vecY *= 0.99;
        }
}


class Particle {
    public var posX:Number, posY:Number, oldPosX:Number, oldPosY:Number;
    public var velocityX:Number, velocityY:Number;
    public var noLineflg:Boolean = false;
    private var root:F5MovieClip2DBmp;
    private var vectorF:VectorField;
    private var resolution:int = 10;
    
    public function Particle(_px:Number,_py:Number,_velx:Number, _vely:Number, rMC:F5MovieClip2DBmp,vec:VectorField) {
        root = rMC;
        posX = _px;
        posY = _py;
        oldPosX = _px;
        oldPosY = _py;
        velocityX = _velx;
        velocityY = _vely;
        vectorF = vec;
        noLineflg = false;
    }
    
    public function draw():void {
        update();
        if(noLineflg) {
            oldPosX = posX;
            oldPosY = posY;
            noLineflg = false;
        } else {
            root.stroke(0xFFFFFF);
            root.moveTo(posX, posY);
            root.lineTo(oldPosX, oldPosY);
            oldPosX = posX;
            oldPosY = posY;
        }
    }
    public function update():void {
        if( (posX<0)||(posY<0)||(posX>root.width)||(posY>root.height) ) {
            clear();
        } else {
            var absvX:Number = velocityX; //絶対値
            absvX = absvX < 0 ? -absvX : absvX;
            var absvY:Number = velocityY; //絶対値 
            absvY = absvY < 0 ? -absvY : absvY;
            
            if(absvX<0.01&&absvY<0.01) {
                clear();
                return;
            }
            var _cell:Cell = vectorF.getCell(posX, posY);
            var ax:Number = (posX % resolution) / resolution;
            var ay:Number = (posY % resolution) / resolution;
            velocityX += (1 - ax) * _cell.vecX * 0.5;
            velocityY += (1 - ay) * _cell.vecY * 0.5;
            
            velocityX += ax * _cell.right.vecX * 0.5;
            velocityY += ax * _cell.right.vecY * 0.5;
            
            velocityX += ay * _cell.low.vecX * 5;
            velocityY += ay * _cell.low.vecY * 5;
            
            velocityX += vectorF.getVecX(posX,posY);
            velocityY += vectorF.getVecY(posX,posY);
            posX += velocityX*5;
            posY += velocityY*5;
            
            velocityX *= 0.6;
            velocityY *= 0.6;
        }
    }
    
    private function clear():void {
        posX = root.mouseX;
        posY = root.mouseY;
        velocityX = Math.random() * 10 - 5;
        velocityY = Math.random() * 10 - 5;
        noLineflg = true;
    }
    
}