Skip to content

Instantly share code, notes, and snippets.

@clehner
Created June 23, 2010 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save clehner/449426 to your computer and use it in GitHub Desktop.
Save clehner/449426 to your computer and use it in GitHub Desktop.
<head>
<title>swarm!</title>
<script type="text/javascript" language=JavaScript src="buzzWorker.js"></script>
<style>
.thing {
position:absolute;
}
.dying {
color:#ff0000;
font-weight:bold;
}
</style>
</head>
<body>
<script>
///////////////////////////////////////////////////
// Thing object
///////////////////////////////////////////////////
var things = [], thingMap = {}, elemMap = {};
var Thing = function(left, top, id) {
this.id = id;
this.minDx = -3; this.maxDx = 3;
this.minDy = -3; this.maxDy = 3;
this.x = this.xOld = left;
this.y = this.yOld = top;
this.pxTravelled = 0;
elemMap[id] = createThingElem(left, top);
}
Thing.prototype.start = function() {
var thisElem = elemMap[this.id];
var thing = this;
var move = function() {
thing.x = bounded(thing.x + scaledRandomInt(thing.minDx,thing.maxDx),200,600);
thing.y = bounded(thing.y + scaledRandomInt(thing.minDy,thing.maxDy),100,500);
if (!thing.dead) {
setTimeout(move, 1);
}
thisElem.style.left = thing.x;
thisElem.style.top = thing.y;
};
move();
}
var createThingElem = function(left, top) {
var elem = document.createElement("DIV");
elem.innerHTML = "%";
elem.className = "thing";
document.body.appendChild(elem);
elem.style.left = this.x;
elem.style.top = this.y;
return elem;
}
////////////////////////////////////////////////
// utils
////////////////////////////////////////////////
var toArray = function(arr) {
return Array.prototype.slice.call(arr);
}
var removeFromArray = function(arr, val) {
for (var i=0; i<arr.length; i++) {
if (arr[i] === val) {
arr.splice(i, 1);
}
}
}
Function.prototype.curry = function() {
if (arguments.length<1) {
return this; //nothing to curry with - return function
}
var __method = this;
var args = toArray(arguments);
return function() {
return __method.apply(this, args.concat(toArray(arguments)));
}
}
var scaledRandomInt = function(min, max) {
return Math.round(min + Math.random()*(max-min));
}
var bounded = function(value, lo, hi) {
return Math.max(Math.min(value,hi),lo);
}
///////////////////////////////////////////
// response to worker
//////////////////////////////////////////
var updateThing = function(updateData) {
updateThis = thingMap[updateData.id];
updateElem = elemMap[updateData.id];
delete updateData.id;
if (updateData.kill) {
removeFromArray(things, updateThis); //biggest drag on browser performance
updateElem.className += " dying";
window.setTimeout(function() {updateElem.style.display = "none"; updateThis.dead = true}, 150);
if (!things.length) {
window.setTimeout(clearIntervals,50);
alert("the end");
}
return;
}
for (var prop in updateData) {
updateThis[prop] = updateData[prop];
}
if (updateThis.symbol) {
updateElem.innerHTML = updateThis.symbol;
}
}
///////////////////////////////////////////
// worker
//////////////////////////////////////////
var worker = new Worker("buzzWorker.js");
worker.onmessage = function(e){
updateThing(e.data);
}
var invokeWorker = function(action) {
worker.postMessage({
'action': action,
'things': things
});
}
var intervals = [];
intervals[0] = window.setInterval(invokeWorker.curry('updatePaths'),1000);
intervals[1] = window.setInterval(invokeWorker.curry('makeHighestSleepy'),1000),
intervals[2] = window.setInterval(invokeWorker.curry('makeLowestBuzzy'),1000);
intervals[3] = window.setInterval(invokeWorker.curry('killSlowest'),1000);
var clearIntervals = function() {
for (var i=0;i<intervals.length;i++) {
window.clearInterval(intervals[i]);
}
}
///////////////////////////////////////////////////
// init
///////////////////////////////////////////////////
var init = function(numberOfThings) {
var i = -1;
while (i++ < numberOfThings) {
things[i] = new Thing(400, 300, i);
things[i].start();
thingMap[things[i].id] = things[i];
}
};
init(100);
</script>
</body>
var things;
var updates;
var getDistance = function(x1,x2,y1,y2) {
return Math.sqrt(Math.pow(Math.abs(x1-x2),2) + Math.pow(Math.abs(y1-y2),2));
}
var actions = {
makeHighestSleepy: function(){
var highest = things.sort(function(a, b){
return a.y - b.y
});
updates = {};
updates.id = highest[0].id;
updates.minDy = -2;
updates.maxDy = 3;
updates.symbol = 'z';
postMessage(updates);
},
makeLowestBuzzy: function(){
var lowest = things.sort(function(a, b){
return b.y - a.y
});
updates = {};
updates.id = lowest[0].id;
updates.minDy = -3;
updates.maxDy = 2;
updates.symbol = '*';
postMessage(updates);
},
killSlowest: function(){
var slowest = things.sort(function(a, b){
return a.pxTravelled - b.pxTravelled
});
updates = {};
updates.id = slowest[0].id;
updates.kill = true;
postMessage(updates);
},
updatePaths: function(){
for (var i = things.length-1; i; i--) {
var t = things[i];
t.pxTravelled += getDistance(t.xOld, t.x, t.yOld, t.y);
t.xOld = t.x; t.yOld = t.y;
}
}
}
onmessage = function(e){
things = e.data.things;
actions[e.data.action]();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment