鼠标关节
演示
源代码
window.onload = function () { var canvas, ctx, w, h, world, boxBody, planeBody, mouseConstraint, mouseBody; var scaleX = 50, scaleY = -50; init(); requestAnimationFrame(animate); function init() { // 初始化画布 canvas = document.getElementById("renderCanvas"); w = canvas.width; h = canvas.height; ctx = canvas.getContext("2d"); ctx.lineWidth = 0.05; // 初始化物理引擎 world = new p2.World(); // 添加一个盒子 boxShape = new p2.Box({ width: 2, height: 1 }); boxBody = new p2.Body({ mass: 1, position: [0, 3], angularVelocity: 1 }); boxBody.addShape(boxShape); world.addBody(boxBody); // 添加一个平面 planeShape = new p2.Plane(); planeBody = new p2.Body(); planeBody.addShape(planeShape); world.addBody(planeBody); // 添加一个用于光标的body mouseBody = new p2.Body(); world.addBody(mouseBody); canvas.addEventListener('mousedown', function (event) { // 将光标在画布中的坐标转换为物理系统的坐标 var position = getPhysicsCoord(event); // 检测光标是否位于盒子的内部 var hitBodies = world.hitTest(position, [boxBody]); if (hitBodies.length) { // 将光标bodt移动到光标所在的位置 mouseBody.position[0] = position[0]; mouseBody.position[1] = position[1]; // 添加一个关节约束(RevoluteConstraint) // 这个约束可以让body绕一个点旋转 mouseConstraint = new p2.RevoluteConstraint(mouseBody, boxBody, { worldPivot: position, collideConnected: false }); world.addConstraint(mouseConstraint); } }); // 在光标移动时,使光标body与光标位置保持同步 canvas.addEventListener('mousemove', function (event) { var position = getPhysicsCoord(event); mouseBody.position[0] = position[0]; mouseBody.position[1] = position[1]; }); // 释放鼠标,则移除这个关节约束 canvas.addEventListener('mouseup', function (event) { world.removeConstraint(mouseConstraint); mouseConstraint = null; }); } // 将画布坐标转换为物理引擎的坐标 function getPhysicsCoord(mouseEvent) { var rect = canvas.getBoundingClientRect(); var x = mouseEvent.clientX - rect.left; var y = mouseEvent.clientY - rect.top; x = (x - w / 2) / scaleX; y = (y - h / 2) / scaleY; return [x, y]; } function drawbox() { ctx.beginPath(); var x = boxBody.interpolatedPosition[0], y = boxBody.interpolatedPosition[1]; ctx.save(); ctx.translate(x, y); // 平移盒子 ctx.rotate(boxBody.interpolatedAngle); // 旋转盒子 ctx.rect(-boxShape.width / 2, -boxShape.height / 2, boxShape.width, boxShape.height); ctx.stroke(); ctx.restore(); } function drawPlane() { var y = planeBody.interpolatedPosition[1]; ctx.moveTo(-w, y); ctx.lineTo(w, y); ctx.stroke(); } function render() { ctx.clearRect(0, 0, w, h); // 放大画布50倍,并将画布原点移动到画布中心,并使y轴向上 ctx.save(); ctx.translate(w / 2, h / 2); ctx.scale(scaleX, scaleY); // 绘制盒子和平面 drawbox(); drawPlane(); ctx.restore(); } var lastTime, timeStep = 1 / 60, maxSubSteps = 5; // 动画循环 function animate(time) { requestAnimationFrame(animate); var dt = lastTime ? (time - lastTime) / 1000 : 0; dt = Math.min(1 / 10, dt); lastTime = time; // 进行物理模拟运算 world.step(timeStep, dt, maxSubSteps); // 绘制场景 render(); } }
发布时间:2016/12/25 下午9:00:22 阅读次数:4346