(function (w, d) { var trueName = 'COLLIDE_O_SCOPE'; w[trueName] = {}; var $ = w[trueName]; $.d = d; $.w = w; $.s = {}; $.f = function() { return { behavior : function() { // an array to hold all circles $.v = []; // initial make and draw for (var i = 0; i < $.a.count; i++) { $.f.makeCircle(i); } // we'll try for 30 frames per second setInterval(trueName + ".f.draw()", 33); }, makeCircle : function(i, x, y) { // each circle has its own object member of the master $.v array $.v[i] = {}; // initial X location if (!x) { // random $.v[i].x = $.f.getRnd($.a.width); } else { // this circle was added by viewer click $.v[i].x = x; } // initial X vector, 1 to 6 pixels per turn $.v[i].dx = $.f.getRnd(6, 1); // initial Y location if (!y) { // random $.v[i].y = $.f.getRnd($.a.height); } else { // this circle was added by viewer click $.v[i].y = y; } // initial Y vector, 1 to 6 pixels per turn $.v[i].dy = $.f.getRnd(6, 1); // number of rings in this circle var n = $.f.getRnd($.a.addSize, $.a.baseSize); // array to hold rings $.v[i].c = []; for (var j = 0; j < n; j++) { // object to hold colors for each ring $.v[i].c[j] = {}; // red $.v[i].c[j].r = $.f.getRnd($.a.maxColor); // green $.v[i].c[j].g = $.f.getRnd($.a.maxColor); // blue $.v[i].c[j].b = $.f.getRnd($.a.maxColor); } }, getRnd: function(r, m) { // no range? use 1 if (!r) { r = 1; } // no minimum? use 0 if (!m) { m = 0; } // return a random number between 0 and the specified range, plus the minimum, rounded down return Math.floor(Math.random() * r) + m; }, draw: function() { // set our background color $.c.fillStyle = 'rgba(' + $.a.backgroundRed + ',' + $.a.backgroundGreen + ',' + $.a.backgroundBlue + ',' + $.a.backgroundAlpha + ')'; // draw our background $.c.fillRect(0,0,$.a.width,$.a.height); // get length of circle array var n = $.v.length; // draw visible circles for (var i = $.a.firstCirc; i < n; i++) { var g = $.a.grid * 5; var ix = parseInt($.v[i].x / g, 10); var iy = parseInt($.v[i].y / g, 10); // skanky punk-rock collision detection for (var j = $.a.firstCirc; j < n; j++) { if (i !== j) { var jx = parseInt($.v[j].x / g, 10); var jy = parseInt($.v[j].y / g, 10); // are both numbers within g pixels of each other? if (ix === jx && iy === jy) { // change directions $.v[i].dx = $.f.getRnd(6, 1); $.v[i].dy = $.f.getRnd(6, 1); $.v[j].dx = $.f.getRnd(6, 1); $.v[j].dy = $.f.getRnd(6, 1); } } } // offscreen? wrap around $.v[i].x = ($.v[i].x + $.v[i].dx) % $.a.width; $.v[i].y = ($.v[i].y + $.v[i].dy) % $.a.height; // draw all rings in this circle for (var k = 1; k < $.v[i].c.length; k++) { $.f.drawRings({ "x":$.v[i].x, "y":$.v[i].y, "z":(k * ($.a.grid/2) - 5), "r":$.v[i].c[k].r, "g":$.v[i].c[k].g, "b":$.v[i].c[k].b, "a":$.a.ringAlpha }); } } }, drawRings : function(c) { $.c.fillStyle = 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + c.a + ')'; // draw all eight possible reflections of this circle $.f.circ(c.x, c.y, c.z); $.f.circ($.a.width - c.x, c.y, c.z); $.f.circ(c.x, $.a.height - c.y, c.z); $.f.circ($.a.width - c.x, $.a.height - c.y, c.z); $.f.circ(c.y, c.x, c.z); $.f.circ($.a.width - c.y, c.x, c.z); $.f.circ(c.y, $.a.height - c.x, c.z); $.f.circ($.a.width - c.y, $.a.height - c.x, c.z); }, circ : function(x, y, r) { $.c.beginPath(); // 0 = start, $.a.p = 2 x pi, for full circle $.c.arc(x, y, r, 0, $.a.p, true); $.c.closePath(); $.c.fill(); }, up : function(v) { var e = v || window.event; var t = $.v.length; // starting X and Y are where you clicked $.f.makeCircle(t, e.clientX - $.x, e.clientY - $.y); // keep the number of circles on the screen constant $.a.firstCirc++; }, houseKeep: function(){ // arg store $.a = {}; // were any args sent from the script? // load some defaults var defaults = { "p":Math.PI * 2, "height":300, "width":300, "count":20, "addSize":5, "baseSize":4, "grid":14, "maxColor":256, "backgroundRed":0, "backgroundGreen":0, "backgroundBlue":0, "backgroundAlpha":1, "ringAlpha":".1" }; for (var d in defaults) { if ($.a[d] === undefined) { $.a[d] = defaults[d]; } } // initially we draw all the circles $.a.firstCirc = 0; // make our canvas var c = $.d.getElementsByTagName("CANVAS")[0]; c.id = trueName; c.height = $.a.height; c.width = $.a.width; $.f.getCanvasPosition(c); $.c = c.getContext('2d'); // if the viewer clicks, do something c.onmouseup = $.f.up; $.f.behavior(); }, getCanvasPosition : function(p) { $.x = 0; $.y = 0; do { $.x += p.offsetLeft; $.y += p.offsetTop; p = p.offsetParent; } while (p.offsetParent); }, init : function(thisScript) { $.f.houseKeep(); $.s.main = $.d.getElementById('main'); var s = document.getElementsByTagName('SCRIPT')[0].textContent; $.s.main.textContent = s; } }; }(); var thisScript = /collide.js$/; if(typeof w.addEventListener !== 'undefined') { w.addEventListener('load', function() { $.f.init(thisScript); }, false); } else if(typeof w.attachEvent !== 'undefined') { w.attachEvent('onload', function() { $.f.init(thisScript); }); } })(window, document);

~kentbrew: collider