Collision

A sweet Collision Simulation in ChelseaJS. Basic Kinematics is used to model such Simulations.

Code

            
    elem=document.querySelector(".example-container");
    setCanvas(elem);
    arr=[];

    //making sure there is no overlap in circles at start

    sprngcolors=['#697C35','#F0D604','#FDBB0A','#FC9253','#FB8060','#EF4D40','#FD7A82','#EA9EC5','#AB6CBB','#6B56BC','#246CC3','#74A3E5']

    overlap=false;
    n_circles=12;
    for(i=0;i<n_circles;i++){
        x=random(70,WIDTH-70);
        y=random(70,HEIGHT-70);
        r=random(30,50);
        for(j=0;j<arr.length;j++){
            if(dist(x,y,arr[j].x,arr[j].y)<r+arr[j].r){
                i--;
                overlap=true;
                break;
            }
            else{
                overlap=false;
            }
        }

        if(!overlap){
        arr.push({
            x:x,
            y:y,
            r:r,
            vx:Math.random()*2-1,
            vy:Math.random()*2-1,
            c:sprngcolors[randomInt(0,sprngcolors.length-1)]
        }
        )};
    }

    function draw(){
        clearCanvas()
        for(i=0;i<n_circles;i++){
            new circle(arr[i].x,arr[i].y,arr[i].r,arr[i].c,1,'#222',0.5);
            arr[i].x+=arr[i].vx;
            arr[i].y+=arr[i].vy;
            collision_wall(arr[i]);
        }
        collision_circles(arr);
        
        requestAnimationFrame(draw);
    }
    
    draw();

    function collision_circles(pos_arr){
        for(i=0;i<pos_arr.length;i++){
            for(j=i+1;j<pos_arr.length;j++){
                if(dist(pos_arr[i].x,pos_arr[i].y,pos_arr[j].x,pos_arr[j].y)<pos_arr[i].r+pos_arr[j].r){
                    phi= Math.atan2(pos_arr[j].y-pos_arr[i].y,pos_arr[j].x-pos_arr[i].x);
                    theta1=Math.atan2(pos_arr[i].vy,pos_arr[i].vx);
                    theta2=Math.atan2(pos_arr[j].vy,pos_arr[j].vx);
                    m1=pos_arr[i].r*pos_arr[i].r;
                    m2=pos_arr[j].r*pos_arr[j].r;
                    v1=sqrt(pos_arr[i].vx*pos_arr[i].vx+pos_arr[i].vy*pos_arr[i].vy);
                    v2=sqrt(pos_arr[j].vx*pos_arr[j].vx+pos_arr[j].vy*pos_arr[j].vy);
                    vn1=v1*cos(phi-theta1);
                    vn2=v2*cos(phi-theta2);
                    vt1=v1*sin(phi-theta1);
                    vt2=v2*sin(phi-theta2);

                    vf1=vn1*(m1-m2)/(m1+m2)+vn2*(2*m2)/(m1+m2);
                    vf2=vn2*(m2-m1)/(m1+m2)+vn1*(2*m1)/(m1+m2);

                    pos_arr[i].vx=vf1*cos(phi)+vt1*sin(phi);
                    pos_arr[i].vy=vf1*sin(phi)-vt1*cos(phi);
                    pos_arr[j].vx=vf2*cos(phi)+vt2*sin(phi);
                    pos_arr[j].vy=vf2*sin(phi)-vt2*cos(phi);



                }
            }
        }
    }
    function collision_wall(pos){
        if(pos.x-pos.r<0){
            pos.vx*=-1;
        }
        if(pos.x+pos.r>WIDTH){
            pos.vx*=-1;
        }
        if(pos.y-pos.r<0){
            pos.vy*=-1;
        }
        if(pos.y+pos.r>HEIGHT){
            pos.vy*=-1;
        }
    }