鼠标关节
演示
源代码
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 阅读次数:5279
