LOG

原生動物

結果

環境
babel6.5.1 preset2015
PIXI.js3.0.9
!function(window,app){

let $win   = $(window);

class Flagellum{
    // ===========================================================================
    // インスタンス
    // ===========================================================================
    constructor(w,h,numNodes,parent){
        let _ = this;
        let muscleRangeArr = [
            0.15,
            0.2,
            0.1
        ];
        let muscleFreqArr = [
            0.08,
            0.06,
            0.1
        ];
        _.muscleRange = muscleRangeArr[Math.round(Math.random() * 2)];
        _.muscleFreq  = muscleFreqArr[Math.round(Math.random() * 2)];
        // _.muscleRange = 0.15; // 筋肉の移動幅
        // _.muscleFreq  = 0.08; // 筋肉の周波数 (角度の移動量)
        _.spinePos    = [];   // 脊髄
        _.spine       = [];
        _.w           = w;
        _.h           = h;
        _.numNodes    = numNodes;
        _.theta       = null;
        // _.velocity    = Math.random() * (5 - 1) + 1;
        _.thetaVel    = null;
        _.count       = null;
        _.spaceX      = w / numNodes + 1;
        _.spaceY      = h / 2;
        _.parent      = parent;
        _.skin        = new PIXI.Container();
        _.skin.x      = Math.random() * $win.width();
        _.skin.y      = Math.random() * $win.height();

        // _.theta    = Math.PI;
        _.theta    = Math.random() * Math.PI;
        _.count    = 0;
        // _.thetaVel = 0;

        // 脊髄の設定
        for(let i = 0,l = numNodes; i<l; i++){
            let x = _.spaceX * i;
            let y = _.spaceY;
            _.spinePos[i] = new Float32Array([0,0]);
            _.spinePos[i][0] = x;
            _.spinePos[i][1] = y;

            _.spine[i] = new PIXI.Graphics();
            _.spine[i].beginFill(0x000000).drawCircle(0,0,2);
            _.spine[i].x = x;
            _.spine[i].y = y;
            _.skin.addChild(_.spine[i]);
        }

        parent.addChild(_.skin);
    }
    // ===========================================================================
    // 泳ぐ
    // ===========================================================================
    swim(){
        let _ = this;
        _.spinePos[0][0] = Math.cos(_.theta);
        _.spinePos[0][1] = Math.sin(_.theta);
        _.count += _.muscleFreq;
        // PIの振り幅を絞る。
        let thetaMuscle = _.muscleRange * Math.sin(_.count);
        _.thetaVel = thetaMuscle;

        // 1つ目の脊髄cosかsin
        _.spinePos[1][0] = -_.spaceX * Math.cos(_.theta + thetaMuscle ) + _.spinePos[0][0];
        _.spinePos[1][1] = -_.spaceX * Math.sin(_.theta + thetaMuscle ) + _.spinePos[0][1];

        for(let i = 2, l = _.numNodes; i<l; i++){
            let x = _.spinePos[i][0] - _.spinePos[i-2][0];
            let y = _.spinePos[i][1] - _.spinePos[i-2][1];
            let r = Math.sqrt( x * x + y * y );
            if(r > 0){
                _.spinePos[i][0] = _.spinePos[i - 1][0] + (x * _.spaceX) / r;
                _.spinePos[i][1] = _.spinePos[i - 1][1] + (y * _.spaceX) / r;
            }
        }

        for(let i = 0, l = _.numNodes; i<l; i++){
            _.spine[i].x = _.spinePos[i][0];
            _.spine[i].y = _.spinePos[i][1];
        }

    }
}

app.class['Flagellum'] = Flagellum;

}(window,window.app);

ほぼ引用:dasl-/my-life-aquatic: my life aquatic

移動はこんな感じ

event.addEventListener('animate',function(){
    for(let i =0; i<fNum; i++){
        let x      = f[i].skin.x;
        let y      = f[i].skin.y;
        let addRad = f[i].thetaVel;
        if(Math.random() * 100 < 0.5){
            f[i].theta += h.random(-0.5,0.5);
        }
        let addX   = Math.cos(f[i].theta + addRad) * (f[i].muscleRange);
        let addY   = Math.sin(f[i].theta + addRad) * (f[i].muscleRange);
        x += addX;
        y += addY;
        f[i].skin.x = x;
        f[i].skin.y = y;
        f[i].swim();
    }
    renderer.render(stage);
});