JS1K

#2: the original

Source description for demo by Nate Sigrist.

(function() { // Removed after compression var win = window, math = Math, // My shortcut globals: s = math.sqrt, r = math.random, c = document.getElementById("c"), cx = c.getContext("2d"), w = win.innerWidth, h = win.innerHeight, MAX_PARTICLES = 700, // Application globals MAX_VELOCITY = 75/1000, //(px/ms) states = [], time = new Date().getTime(), vv,vx,dt,tt,V,p1, // For compressor tool p2,R,dx,dy,dd,d,dvx,dvy,dvdv,cos1, sin1,dv_para,t,cos2,sin2, v1x_,v1y_,v2x_,v2y_,v1x,v1y,v2x,v2y, mr,v1x_prime,v2x_prime; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Initialization: // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// c.width = w; c.height = h; cx.fillStyle = "rgb(122,0,25)"; for(n=0; n<MAX_PARTICLES; n++) { vx = -MAX_VELOCITY + 2*r()*MAX_VELOCITY; vv = s(MAX_VELOCITY*MAX_VELOCITY - vx*vx); states[n] = { r: 1+r()*10, px: r()*w, py: r()*h, vx: vx, vy: -vv+2*r()*vv }; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // The main loop: // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// window.setInterval(function() { dt = new Date().getTime() - time; time += dt; // Ha-ha! #Desperation [time + dt = time + new time - time = new time] cx.clearRect(0, 0, w, h); for(n=0; n<MAX_PARTICLES; n++) { tt = dt; p1 = states[n]; p1.px += p1.vx*tt; p1.py += p1.vy*tt; // Check boundaries first if(p1.px<p1.r||p1.px>w-p1.r){p1.vx=-p1.vx;p1.px=p1.px<p1.r?p1.r:w-p1.r;} if(p1.py<p1.r||p1.py>h-p1.r){p1.vy=-p1.vy;p1.py=p1.py<p1.r?p1.r:h-p1.r;} // Could it hit another particle? for(m=n+1; m<MAX_PARTICLES; m++) { p2 = states[m]; R = p1.r+p2.r; dx = p2.px-p1.px; dy = p2.py-p1.py; dd = dx*dx+dy*dy; d = s(dd); // Removed a lot of unnecessary checks here to make this smaller but less accurate. if(d<R) { dvx = p2.vx-p1.vx; dvy = p2.vy-p1.vy; dvdv = dvx*dvx+dvy*dvy; cos1 = dx/d; sin1 = dy/d; dv_para = dvx*cos1+dvy*sin1; v1x = p1.vx*cos1+p1.vy*sin1; v1y = p1.vy*cos1-p1.vx*sin1; v2x = p2.vx*cos1+p2.vy*sin1; v2y = p2.vy*cos1-p2.vx*sin1; mr = p2.r/p1.r; V = (v1x+mr*v2x)/(1+mr); v1x_prime = V-s(V*V-((1-mr)*v1x+2*mr*v2x)*v1x/(1+mr)); v2x_prime = v1x/mr+v2x-v1x_prime/mr; p1.vx = v1x_prime*cos1-v1y*sin1; p1.vy = v1y*cos1+v1x_prime*sin1; p2.vx = v2x_prime*cos1-v2y*sin1; p2.vy = v2y*cos1+v2x_prime*sin1; } } // New all time low: draw inside collision method! >ugh< cx.beginPath(); cx.arc(p1.px, p1.py, p1.r, 0, 2*math.PI, true); cx.fill(); } }, 33); })();