Circles bouncing around and colliding. Click and drag to attract them to your mouse. Learn how it was coded at http://www.youtube.com/watch?v=yF0T7lviBnY
var w=c.width=window.innerWidth;var h=c.height=window.innerHeight;(function(){var o=0.1,b=0.99,j=0.005,g=[],f=20,n=1,k,l=Math.random,m=Math;for(var e=0;e<f;e++){g.push({x:l()*w,y:l()*h,vx:0,vy:0,r:10+l()*15})}setInterval(function(){var t,s,u,r,q;for(t=0;t<f;t++){u=g[t];u.x+=u.vx;u.y+=u.vy;u.vy+=o;u.vy*=b;u.vx*=b;if(u.y+u.r>h){u.y=h-u.r;u.vy=-m.abs(u.vy)}if(u.x+u.r>w){u.x=w-u.r;u.vx=-m.abs(u.vx)}if(u.y-u.r<0){u.y=u.r;u.vy=m.abs(u.vy)}if(u.x-u.r<0){u.x=u.r;u.vx=m.abs(u.vx)}for(s=t+1;s<f;s++){var p=g[s];r=p.x-u.x,q=p.y-u.y,d=m.sqrt(r*r+q*q),ux=r/d,uy=q/d;if(d<u.r+p.r){u.vx-=ux*n;u.vy-=uy*n;p.vx+=ux*n;p.vy+=uy*n}}a.beginPath();a.arc(u.x,u.y,u.r,0,2*m.PI);a.closePath();a.fillStyle="black";a.fill()}a.fillStyle="rgba(255,255,255,0.05)";a.fillRect(0,0,w,h);if(k){for(t=0;t<f;t++){u=g[t];r=k.pageX-u.x;q=k.pageY-u.y;u.vx+=r*j;u.vy+=q*j}}},20);c.addEventListener("mousedown",function(i){k=i});c.addEventListener("mousemove",function(i){if(k){k=i}});c.addEventListener("mouseup",function(i){k=null});a.fillRect(0,0,w,h)})();
dmFyIHc9Yy53aWR0aD13aW5kb3cuaW5uZXJXaWR0aDt2YXIgaD1jLmhlaWdodD13aW5kb3cuaW5uZXJIZWlnaHQ7KGZ1bmN0aW9uKCl7dmFyIG89MC4xLGI9MC45OSxqPTAuMDA1LGc9W10sZj0yMCxuPTEsayxsPU1hdGgucmFuZG9tLG09TWF0aDtmb3IodmFyIGU9MDtlPGY7ZSsrKXtnLnB1c2goe3g6bCgpKncseTpsKCkqaCx2eDowLHZ5OjAscjoxMCtsKCkqMTV9KX1zZXRJbnRlcnZhbChmdW5jdGlvbigpe3ZhciB0LHMsdSxyLHE7Zm9yKHQ9MDt0PGY7dCsrKXt1PWdbdF07dS54Kz11LnZ4O3UueSs9dS52eTt1LnZ5Kz1vO3UudnkqPWI7dS52eCo9YjtpZih1LnkrdS5yPmgpe3UueT1oLXUucjt1LnZ5PS1tLmFicyh1LnZ5KX1pZih1LngrdS5yPncpe3UueD13LXUucjt1LnZ4PS1tLmFicyh1LnZ4KX1pZih1LnktdS5yPDApe3UueT11LnI7dS52eT1tLmFicyh1LnZ5KX1pZih1LngtdS5yPDApe3UueD11LnI7dS52eD1tLmFicyh1LnZ4KX1mb3Iocz10KzE7czxmO3MrKyl7dmFyIHA9Z1tzXTtyPXAueC11LngscT1wLnktdS55LGQ9bS5zcXJ0KHIqcitxKnEpLHV4PXIvZCx1eT1xL2Q7aWYoZDx1LnIrcC5yKXt1LnZ4LT11eCpuO3UudnktPXV5Km47cC52eCs9dXgqbjtwLnZ5Kz11eSpufX1hLmJlZ2luUGF0aCgpO2EuYXJjKHUueCx1LnksdS5yLDAsMiptLlBJKTthLmNsb3NlUGF0aCgpO2EuZmlsbFN0eWxlPSJibGFjayI7YS5maWxsKCl9YS5maWxsU3R5bGU9InJnYmEoMjU1LDI1NSwyNTUsMC4wNSkiO2EuZmlsbFJlY3QoMCwwLHcsaCk7aWYoayl7Zm9yKHQ9MDt0PGY7dCsrKXt1PWdbdF07cj1rLnBhZ2VYLXUueDtxPWsucGFnZVktdS55O3UudngrPXIqajt1LnZ5Kz1xKmp9fX0sMjApO2MuYWRkRXZlbnRMaXN0ZW5lcigibW91c2Vkb3duIixmdW5jdGlvbihpKXtrPWl9KTtjLmFkZEV2ZW50TGlzdGVuZXIoIm1vdXNlbW92ZSIsZnVuY3Rpb24oaSl7aWYoayl7az1pfX0pO2MuYWRkRXZlbnRMaXN0ZW5lcigibW91c2V1cCIsZnVuY3Rpb24oaSl7az1udWxsfSk7YS5maWxsUmVjdCgwLDAsdyxoKX0pKCk7
var w = c.width = window.innerWidth;
var h = c.height = window.innerHeight;
(function(){
var gravity = 0.1,
dampening = 0.99,
pullStrength = 0.005,
circles = [ ],
numCircles = 20,
repulsion = 1, mouse,
rand = Math.random,
math = Math;
// Initialize the array of circle objects
for(var i = 0; i < numCircles; i++){
circles.push({
x: rand() * w,
y: rand() * h,
// (vx, vy) = Velocity vector
vx: 0,
vy: 0,
r: 10 + rand() * 15
});
}
// This function is called 60 times each second
setInterval(function(){
var i, j, circle, dx, dy;
for(i = 0; i < numCircles; i++){
circle = circles[i];
// Increment location by velocity
circle.x += circle.vx;
circle.y += circle.vy;
// Increment Gravity
circle.vy += gravity;
// Slow it down
circle.vy *= dampening;
circle.vx *= dampening;
// bottom
if(circle.y + circle.r > h){
circle.y = h - circle.r;
circle.vy = -math.abs(circle.vy);
}
// right
if(circle.x + circle.r > w){
circle.x = w - circle.r;
circle.vx = -math.abs(circle.vx);
}
// top
if(circle.y - circle.r < 0){
circle.y = circle.r;
circle.vy = math.abs(circle.vy);
}
// left
if(circle.x - circle.r < 0){
circle.x = circle.r;
circle.vx = math.abs(circle.vx);
}
// Collision for all pairs
for(j = i+1; j < numCircles; j++){
var b = circles[j];
// (dx, dy) distcirclence in x circlend y
dx = b.x - circle.x,
dy = b.y - circle.y,
// d = distcirclence from `circle` to `b`
d = math.sqrt(dx*dx + dy*dy),
// (ux, uy) = unit vector
// in the circle -> b direction
ux = dx / d,
uy = dy / d;
// If the bcirclells circlere on top of one circlenother,
if(d < circle.r + b.r){
// then execute circle repulsive force to
// push them circlepcirclert, which resembles collision.
circle.vx -= ux * repulsion;
circle.vy -= uy * repulsion;
b.vx += ux * repulsion;
b.vy += uy * repulsion;
}
}
// Draw each circle
a.beginPath();
a.arc(circle.x, circle.y, circle.r,
0, 2*math.PI);
a.closePath();
a.fillStyle = 'black';
a.fill();
}
// Fill a semi-transparent white rectangle
// for the ghosting trail effect.
a.fillStyle = 'rgba(255,255,255,0.05)';
a.fillRect(0, 0, w, h);
if(mouse){
for(i = 0; i < numCircles; i++){
circle = circles[i];
dx = mouse.pageX - circle.x;
dy = mouse.pageY - circle.y;
circle.vx += dx * pullStrength;
circle.vy += dy * pullStrength;
}
}
},20);
c.addEventListener('mousedown', function(e){mouse = e;});
c.addEventListener('mousemove', function(e){
if(mouse)
mouse = e;
});
c.addEventListener('mouseup', function(e){
mouse = null;
});
a.fillRect(0, 0, w, h);
})();