LOG

連結バネ2

前回のものは座標を固定していたが、今回は一定の距離を保つようにする。
結果

let stats    = new Stats();
let width    = 600;
let height   = 400;
let mousePos = new PIXI.Point(width / 2,height / 2);
let canvas   = document.getElementById('my-canvas');
let renderer = new PIXI.autoDetectRenderer(
    width,
    height,
    {
        'view'      : canvas,
        'antialias' : true
    }
);
let stage = new PIXI.Container();
renderer.backgroundColor = 0xFFFFFF;

let dotList = [];
let dotNum  = 8;
let dotDist = 10;

// =============================================================================
// move event
// =============================================================================
let onMove = (e)=>{
    mousePos.x = e.offsetX;
    mousePos.y = e.offsetY;
}

// =============================================================================
// animation
// =============================================================================
let count = 0;
let animate = ()=>{
    stats.begin();
    requestAnimationFrame(animate);

    let dot     = null;
    let dx      = null;
    let dy      = null;
    let angle   = null;
    let dest    = null;
    let targetX = null;
    let targetY = null;

    for(let i = 0; i < dotList.length; i++){
        dot = dotList[i];
        dest = {};
        if(i === 0){
            dest.x = mousePos.x;
            dest.y = mousePos.y;
        }else{
            dest.x = dotList[i-1].x;
            dest.y = dotList[i-1].y;
        }
        dx       = dot.x - dest.x;
        dy       = dot.y - dest.y;
        angle    = Math.atan2(dy,dx);

        targetX = dest.x + Math.cos(angle) * dot.dist;
        targetY = dest.y + Math.sin(angle) * dot.dist;

        dot.vx   += (targetX - dot.x) * dot.spring;
        dot.vy   += (targetY - dot.y) * dot.spring;
        dot.vx   *= dot.friction;
        dot.vy   *= dot.friction;
        dot.x    += dot.vx;
        dot.y    += dot.vy;
        dot.clear();
        dot.beginFill(0x000000);
        dot.drawCircle(0,0,4);
        if(i !== 0){
            dot.lineStyle(1,0x000000,1);
            dot.moveTo(0,0);
            dot.lineTo(dest.x - dot.x,dest.y -  dot.y);
        }
        dot.endFill();

    }
    count++;

    renderer.render(stage);
    stats.end();
}

// =============================================================================
// init
// =============================================================================
$(()=>{
    stats.showPanel(0);
    document.body.appendChild(stats.dom);

    let dot = null;
    for(let i = 0; i < dotNum; i++){
        dot          = new PIXI.Graphics();
        dot.vx       = 0;
        dot.vy       = 0;
        dot.x        = 0;
        dot.y        = 0;
        dot.spring   = 0.05;
        dot.friction = 0.8;
        dot.dist   = i === 0 ? 0 : dotDist;
        dotList[i] = dot;
        stage.addChild(dot);
    }

    animate();
    canvas.addEventListener('mousemove',onMove,false);
});