位置的插值

演示

源代码

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  阅读次数:4564

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号