UNPKG

p2s

Version:

A JavaScript 2D physics engine.

195 lines (156 loc) 4.46 kB
<!DOCTYPE html> <html lang="en"> <head> <title>p2.js worker example</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> </head> <body> <!-- The canvas, where we draw stuff --> <canvas width="600" height="400" id="myCanvas"></canvas> <!-- Worker script, will be run in separate thread --> <script id="worker1" type="javascript/worker"> var world, timeStep = 1/60, array = null, N = 20; self.onmessage = function(e) { if (!world) { // Load p2.js library importScripts(e.data.p2Url); N = e.data.N; // Create a world world = new p2.World({ gravity: [0, -5] }); // Ground plane var planeShape = new p2.Plane(); var groundBody = new p2.Body({ mass: 0 }); groundBody.addShape(planeShape); world.addBody(groundBody); // Create N boxes for(var i=0; i!==N; i++){ var boxBody = new p2.Body({ mass: 1, position: [Math.random()-0.5, e.data.boxHeight * i + 0.5,Math.random()-0.5] }); var boxShape = new p2.Box({ width: e.data.boxWidth, height: e.data.boxHeight }); boxBody.addShape(boxShape); world.addBody(boxBody); } setInterval(function(){ // Step the world world.step(timeStep); if(array){ for(var i=0; i!==world.bodies.length; i++){ var b = world.bodies[i]; array[3*i + 0] = b.position[0]; array[3*i + 1] = b.position[1]; array[3*i + 2] = b.angle; } // Send data back to the main thread self.postMessage(array, [array.buffer]); array = null; } }, timeStep * 1000); } else { // We got a new buffer array = e.data; } }; </script> <!-- Main thread script --> <script> // Parameters var dt = 1/60, N = 100, boxWidth = 0.5, boxHeight = 0.5, zoom = 20, array = null, worker, canvas, ctx; initWorker(); init(); animate(); function initWorker(){ // Data array. Contains all our data we need for rendering: a 2D position and an angle per body. // It will be sent back and forth from the main thread and the worker thread. When // it's sent from the worker, it's filled with position data of all bodies. array = new Float32Array(N * 3); // Create a blob for the inline worker code var blob = new Blob([document.querySelector('#worker1').textContent],{type:'text/javascript'}); var url = window.URL.createObjectURL(blob); // Create worker worker = new Worker(url); worker.postMessage = worker.webkitPostMessage || worker.postMessage; worker.onmessage = function(e) { // When we get a message from the worker, store it array = e.data; } // Start the worker by sending an initial message worker.postMessage({ N : N, dt : dt, boxWidth: boxWidth, boxHeight: boxHeight, p2Url : document.location.href.replace(/\/[^/]*$/,"/") + "../../build/p2.js", }); sendBuffer(); } function init(){ // Init canvas canvas = document.getElementById("myCanvas"); w = canvas.width; h = canvas.height; ctx = canvas.getContext("2d"); ctx.lineWidth = 0.05; } function drawBodies(){ // Draw all bodies. Skip the first one, it's the ground plane for(var i=1; i < N; i++){ ctx.beginPath(); var x = array[i * 3 + 0], y = array[i * 3 + 1], angle = array[i * 3 + 2]; ctx.save(); ctx.translate(x, y); // Translate to the center of the box ctx.rotate(angle); // Rotate to the box body frame ctx.rect(-boxWidth/2, -boxHeight/2, boxWidth, boxHeight); ctx.stroke(); ctx.restore(); } } function render(){ // Clear the canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // Transform the canvas // Note that we need to flip the y axis since Canvas pixel coordinates // goes from top to bottom, while physics does the opposite. ctx.save(); ctx.translate(canvas.width / 2, canvas.height / 2); // Translate to the center ctx.scale(zoom, -zoom); // Zoom in and flip y axis // Draw all bodies drawBodies(); // Restore transform ctx.restore(); } function sendBuffer(){ worker.postMessage(array, [array.buffer]); array = null; } // Animation loop function animate(){ requestAnimationFrame(animate); // Render scene if(array){ render(); sendBuffer(); } } </script> </body> </html>