an experiment I wanted to try to see if i could get the physics to work faster if i used a webworker.. while it works it's not best.
A Pen by Darby Rathbone on CodePen.
<script type="text/js-worker"> | |
</script> | |
<textarea rows="20" cols="100" id='workersrc'>onmessage = function (e) { | |
if(e.data == "draw") w.getPoints(); | |
var d = JSON.parse(e.data); | |
if(JSON.parse(e.data).action == "add") w.addBall(parseFloat(d.x), parseFloat(d.y), 0, 0, parseFloat(d.r)) | |
}; | |
Number.prototype.add = function (b) { | |
return this + b | |
}; | |
Number.prototype.sub = function (b) { | |
return this - b | |
}; | |
Number.prototype.mult = function (b) { | |
return this * b | |
}; | |
Number.prototype.div = function (b) { | |
return this / b | |
}; | |
Array.prototype.add = function (b) { | |
return this.map(function (e, i, a) { | |
return e + b[i] | |
}) | |
}; | |
Array.prototype.sub = function (b) { | |
return this.map(function (e, i, a) { | |
return e - b[i] | |
}) | |
}; | |
Array.prototype.sqrt = function () { | |
return this.map(function (e, i, a) { | |
return Math.sqrt(e) | |
}) | |
}; | |
Array.prototype.mult = function (b) { | |
if(b.length) return this.map(function (e, i, a) { | |
return e * b[i] | |
}); | |
return this.map(function (e, i, a) { | |
return e * b | |
}) | |
}; | |
Array.prototype.div = function (b) { | |
if(b.length) return this.map(function (e, i, a) { | |
return e / b[i] | |
}); | |
return this.map(function (e, i, a) { | |
return e / b | |
}) | |
}; | |
var temp = 4; | |
var lerp = function (d, a, b) { | |
return((a.sub(b)).mult(d)).add(b) | |
}; | |
var Vertex = (function () { | |
function Vertex() { | |
this.arg = []; | |
Array.prototype.push.apply(this.arg, arguments); | |
return this.arg | |
} | |
Vertex.prototype.lerpTo = function (d, a) { | |
return new Vertex(lerp(d, a.x, this.x), lerp(d, a.y, this.y)) | |
}; | |
Array.prototype.mag = function () { | |
return Math.sqrt((this[0]) * (this[0]) + (this[1]) * (this[1])) | |
}; | |
Array.prototype.norm = function () { | |
return this.div(Math.sqrt((this[0]) * (this[0]) + (this[1]) * (this[1]))) | |
}; | |
Array.prototype.dist = function (a) { | |
return Math.sqrt((this[0] - a[0]) * (this[0] - a[0]) + (this[1] - a[1]) * (this[1] - a[1])) | |
}; | |
Array.prototype.midpoint = function (a) { | |
return new Vertex((this[0] + a[0]) / 2.0, (this[1] + a[1]) / 2.0) | |
}; | |
return Vertex | |
})(); | |
var Ball = (function () { | |
function Ball(a, b, c) { | |
this.pos = a; | |
this.velocity = b; | |
this.radius = c; | |
return this | |
} | |
Ball.prototype.step = function (a, b, c) { | |
this.pos = this.pos.add(this.velocity); | |
var d = false; | |
var e = 0; | |
if(this.pos[0] < b[0]) { | |
this.velocity[0] -= this.pos.sub(b)[0]*2 ; | |
e = Math.abs(this.pos.sub(b)[0]); | |
this.pos[0] = b[0] | |
} | |
if(this.pos[0] > c[0]) { | |
this.velocity[0] -= this.pos.sub(c)[0]*2 ; | |
d = true; | |
e = Math.abs(this.pos.sub(c)[0]); | |
this.pos[0] = c[0] | |
} | |
if(this.pos[1] < b[1]) { | |
this.velocity[1] -= this.pos.sub(b)[1] *2; | |
d = true; | |
e = Math.abs(this.pos.sub(b)[1]); | |
this.pos[1] = b[1] | |
} | |
if(this.pos[1] > c[1]) { | |
this.velocity[1] -= this.pos.sub(c)[1] *2; | |
d = true; | |
e = Math.abs(this.pos.sub(c)[1]); | |
this.pos[1] = c[1] | |
} | |
if(!d) { | |
this.velocity = this.velocity.add(a) | |
} | |
if(d) { | |
this.velocity = this.velocity.mult(0.7) | |
} | |
}; | |
Ball.prototype.toString = function () { | |
return JSON.stringify({ | |
'radius': this.radius, | |
'pos': [this.pos[0].toFixed(2), this.pos[1].toFixed(2)] | |
}) | |
}; | |
return Ball | |
})(); | |
var World = (function () { | |
function World(a, b, c) { | |
this.acceleration = a; | |
this.min = b; | |
this.max = c; | |
this.balls = [] | |
} | |
World.prototype.addBall = function (x, y, a, b, r) { | |
this.balls.push(new Ball(new Vertex(x, y), new Vertex(a, b), r)) | |
}; | |
World.prototype.step = function () { | |
var b = this.acceleration, | |
min = this.min, | |
max = this.max, | |
balls = this.balls; | |
balls.forEach(function (e, i, a) { | |
e.step(b, min, max) | |
}); | |
balls.forEach(function (e, i, a) { | |
balls.map(movecollisionsapart, balls[i]) | |
}) | |
}; | |
World.prototype.draw = function () { | |
this.balls.forEach(function (e) { | |
context.beginPath(); | |
context.arc(e.pos[0], e.pos[1] , e.radius, 0, Math.PI * 2, true); | |
context.stroke() | |
}) | |
}; | |
World.prototype.getPoints = function () { | |
var a = ""; | |
a = this.balls.join(','); | |
a = "[" + a + "]"; | |
postMessage(a) | |
}; | |
return World | |
})(); | |
var w = new World(new Vertex(0, 1), new Vertex(10, 10), new Vertex(450, 450)); | |
for(var i = 0; i < 500; i++) { | |
w.addBall(450 * Math.random(), 450 * Math.random(), 0, 0, 4) | |
} | |
w.timer = setInterval(function () { | |
w.step() | |
}); | |
function movecollisionsapart(e) { | |
if(this !== e && e) { | |
var a = this.pos.dist(e.pos); | |
if(a < ((this.radius + e.radius))) { | |
var b = this.pos.sub(e.pos); | |
var d = b.norm().mult( ((this.radius + e.radius) - a)); | |
e.velocity = e.velocity.sub(d); | |
e.pos = e.pos.sub(d); | |
this.velocity = this.velocity.add(d); | |
this.pos = this.pos.add(d); | |
return e | |
} | |
} | |
} | |
</textarea><button id="reloader" >load</button> |
var canvas = document.createElement('canvas'); | |
canvas.width = 500; | |
canvas.height = 500; | |
canvas.style.border = "inset"; | |
document.body.appendChild(canvas); | |
var context = canvas.getContext('2d'); | |
window.requestAnimFrame = (function () { | |
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) { | |
window.setTimeout(callback, 1000 / 60); | |
}; | |
})(); | |
var blob; | |
document.getElementById('reloader').onclick = function () { | |
if (document.worker) | |
document.worker.terminate(); | |
// usage: | |
// instead of setInterval(render, 16) .... | |
blob = new Blob(Array.prototype.map.call(document.querySelectorAll("script[type=\"text\/js-worker\"]"), function (oScript) { | |
document.querySelectorAll("script[type=\"text\/js-worker\"]").textContent = document.getElementById('workersrc').value; | |
return document.getElementById('workersrc').value; | |
}), { | |
type: "text/javascript" | |
}); | |
document.worker = new Worker(window.URL.createObjectURL(blob)); | |
document.worker.onmessage = function (datae) { | |
context.clearRect(0, 0, 500, 500); | |
//console.log(datae.data); | |
var data = JSON.parse(datae.data); | |
data.forEach(function (e) { | |
context.beginPath(); | |
context.arc(e.pos[0], e.pos[1], e.radius, 0, 2 * Math.PI, false); | |
context.closePath(); | |
context.stroke(); | |
}); | |
}; | |
var action = "draw"; | |
document.worker.postMessage(action); | |
(function animloop() { | |
setTimeout(animloop, 1000 / 30); | |
repeater(); | |
})(); | |
function repeater() { | |
var action = "draw"; | |
document.worker.postMessage(action); | |
} | |
}; | |
canvas.onclick = function (e) { | |
var action = new Object(); | |
action.action = "add"; | |
action.x = e.pageX - canvas.offsetLeft; | |
action.y = e.pageY - canvas.offsetTop; | |
action.r = 5; | |
document.worker.postMessage(JSON.stringify(action)); | |
}; |
an experiment I wanted to try to see if i could get the physics to work faster if i used a webworker.. while it works it's not best.
A Pen by Darby Rathbone on CodePen.