首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >带有游戏循环的JavaScript平滑动画

带有游戏循环的JavaScript平滑动画
EN

Stack Overflow用户
提问于 2012-08-06 04:29:19
回答 2查看 5.9K关注 0票数 3

我已经简化了我的游戏循环,只需要在屏幕上移动一个盒子,Click Here。由于某种原因,盒子的移动似乎并不顺畅。我做了一个video of it here

游戏循环是这样命名的:

代码语言:javascript
复制
var game = function( ) {
    var now = Date.now( );
    var delta = now - then;

    update( delta / 1000 );
    draw( );

    then = now;
};

setInterval( game, 1000 / 50 );

我尝试将draw调用从主游戏循环中分离出来,并将它们放在requestAnimationFrame中,但问题仍然存在。我看过一堆看起来运行起来很流畅的教程。我甚至尝试过使用fixed time-step game loop,但那只会让我的游戏运行的太快了。

我如何改进上面的逻辑,比如使用requestAnimationFrame并维护update调用的deltaTime

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-08-06 07:10:17

我相信当使用canvas时,你的位置变量应该是整数值,因为它们代表像素,而浮点值是没有意义的。如果您打开控制台并输入sceneManager.currentScene.GameplayLayer.ball.position.x,那么您将返回一个非常长的小数。我认为关于OP的评论表明,有时球移动的速度是2px,而不是1px,这可能是有道理的。当你更新你的位置时,你会得到一个浮点值。

我认为它有时向上舍入到下一个最高像素位置,有时向下舍入。我会试着像这样取地板或天花板:

代码语言:javascript
复制
this.position.x += Math.floor(this.speed * 100 * deltaTime * Math.cos(directionInRadians));
this.position.y += Math.floor(this.speed * 100 * deltaTime * Math.sin(directionInRadians));

我会进行这两个更改,看看它的行为如何。

编辑:因为您编辑了您的问题以简化逻辑。我可以建议一些东西来尝试,那就是使用我创建的这个Clock对象,我一直在使用它。它为我提供了流畅的动画效果,而且非常简单。它是基于clock that Three.JS uses的,所以你可能也想检查一下。即使您想使用自己的代码,您至少可以尝试这个现成的解决方案,看看它是否会给您带来相同的结果。它看起来对我来说很好。此外,您还尝试使用了填充程序,因此游戏函数中的调用应该是requestAnimFrame(game);

代码语言:javascript
复制
var Clock = function () {

    /** Member startTime will remain fixed at its integer
        millisecond value returned by Date.now(). Will always
        be equal to the time the clock was started */
    this.startTime = Date.now();

    /** Member ms is updated by tick() to a integer value reprsenting 
        the number of milliseconds between the epoch (January 1, 1970)
        and the current date and time of the system. */
    this.ms = this.startTime;
    this.last = this.startTime;  /** millis at last call to tick() */
    this.time = 0;               /** ms in floating point seconds not millis */

    /** Member dt is updated by tick() to an integer value representing
        the number of milliseconds since the last call to tick(). */
    this.dt = 0;
    this.delta = 0; /** dt in floating point seconds not millis */

    /** Member fps is updated by tick() to a floating point value representing
        frames per second, updated and averaged approximately once per second */
    this.fps = 0.0;

    /** Member frameCount is updated to an integer value representing the
        total number of calls to tick() since the clock was created. */
    this.frameCount = 0;

    /** The frameCounter member is a flag you can turn off if you don't need to
        calculate the frameCount or do the average FPS calculation every second */
    this.frameCounter = true;

    /** Private globals needed to calculcate/average fps over eachs second */
    var timeToUpdate = 0;
    var framesToUpdate = 0;

    /************************************************************************************
        The tick() method updates ALL the Clock members, which should only
        be read from and never written to manually. It is recommended that
        tick() is called from a callback loop using requestAnimationFrame

        Learn more: http://paulirish.com/2011/requestanimationframe-for-smart-animating/
    *************************************************************************************/
    this.tick = function () {
        /** This is a new frame with it's very own unique number */

        if (this.frameCounter) this.frameCount++;

        /** Set the private currentTime variable */
        this.ms = Date.now();

        /** Update time delta and immediately set last time to
            be as accurate as possible in our timings. */
        this.dt = this.ms - this.last;
        this.last = this.ms;

        /** Calculate floating-point delta and increment time member */
        this.delta = 0.001 * this.dt;
        this.time += this.delta;

        /** Calculate private temp variables for fps calculation */
        if (this.frameCounter) {
            timeToUpdate += this.dt;
            framesToUpdate++;
            if (timeToUpdate > 1000) {
                this.fps = Math.round((framesToUpdate * 1000) / timeToUpdate);
                framesToUpdate = 0;
                timeToUpdate = 0;
            }
        }
    }
}

如果你使用这个对象,那么你需要做的就是在你的初始化函数中创建一个新的时钟对象,比如clock = new Clock();。然后在每个动画调用中调用clock.tick()。然后您可以访问成员clock.deltaclock.time,这将为您提供以秒为单位的浮点值形式的增量和时间。clock.dtclock.ms将以毫秒为单位提供与integer相同的值。您还可以使用clock.fps访问fps或通过设置clock.frameCounter = false禁用它。

票数 4
EN

Stack Overflow用户

发布于 2012-10-09 08:05:16

使用three.js时钟平滑了我的动画。我强烈推荐它。里面还有很多其他的好代码。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11819825

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档