位置的插值
演示
源代码
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 阅读次数:4351