位置的插值
演示
源代码
window.onload = function () {
var w, h, canvas, ctx, world, circleBody;
init();
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({ gravity:[0,0] });
// 在世界中添加一个圆形
circleShape = new p2.Circle({ radius: 1 });
var velo = [0,0],
pos = [-3,0];
circleBody = new p2.Body({ mass:1, velocity:velo, position:pos });
circleBody.damping = 0;
circleBody.addShape(circleShape);
world.addBody(circleBody);
}
function drawCircles(ctx,circleBody){
ctx.beginPath();
var radius = circleShape.radius;
// 在插值位置绘制圆形
ctx.arc(circleBody.interpolatedPosition[0],
circleBody.interpolatedPosition[1],
radius,0,2*Math.PI);
ctx.stroke();
ctx.beginPath();
// 在固定步长位置绘制圆形
ctx.arc(circleBody.position[0],
circleBody.position[1],
radius,0,2*Math.PI);
ctx.stroke();
}
function render(ctx,circleBody){
ctx.clearRect(0,0,w,h);
ctx.save();
ctx.translate(w/2, h/2);
ctx.scale(50, -50);
drawCircles(ctx,circleBody);
ctx.restore();
}
var lastCallTime = time();
// 动画循环
function animate(t){
t = t || 0;
requestAnimationFrame(animate);
circleBody.velocity[0] = 2*Math.cos(1 * t / 1000 + 3/2*Math.PI);
circleBody.velocity[1] = 2*Math.sin(1 * t / 1000 + 3/2*Math.PI);
// 计算自上次调用step()方法以来流逝的时间
var timeSinceLastCall = time()-lastCallTime;
lastCallTime = time();
// 物理引擎使用的固定时间步长,本例中使用的数值很大,为0.5,这样我们可以清晰地看出与插值的区别
// 注意:对大多数游戏来说,fixedTimeStep=1/60是一个较好的选择
var fixedTimeStep=0.5; // 秒
// 在一次.step()中进行的最大时间步数,本例中取了一个较大的数值10。
// 注意:对大多数游戏来说,maxSubSteps=3是一个较好的选择。
var maxSubSteps=10;
// 调用world的step方法。
// 在这个方法中,只会在固定时间步长内进行位置的积分运算,同时会计算插值后的位置并将它存储在body.interpolatedPosition中。
world.step(fixedTimeStep,timeSinceLastCall,maxSubSteps);
// 同时绘制圆的插值位置和固定步长对应的位置
render(ctx,circleBody);
}
// 获取当前的时间,单位为秒
function time(){
return new Date().getTime() / 1000;
}
}
发布时间:2016/12/11 下午7:29:50 阅读次数:5276
