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.