【问题标题】:C++ / SDL animation speedC++ / SDL 动画速度
【发布时间】:2011-09-15 16:31:46
【问题描述】:

所以我正在开发一款游戏,遵循在线教程。目前我在系统中内置了一些 FPS,以及一个使用这样的精灵片段的简单动画:

if( frameCount > 12 )
        frameCount = 0;

    //hero frames   
    SDL_Rect clip[ 13 ];

    clip[ 0 ].x = 0;
    clip[ 0 ].y = 0;
    clip[ 0 ].w = 44;
    clip[ 0 ].h = 39;

    clip[ 1 ].x = 51;
    clip[ 1 ].y = 0;
    clip[ 1 ].w = 44;
    clip[ 1 ].h = 39;

    clip[ 2 ].x = 102;
    clip[ 2 ].y = 0;
    clip[ 2 ].w = 44;
    clip[ 2 ].h = 39;
    ...
    ...
    SDL_BlitSurface( hero, &clip[ frameCount ], destination, &offset );
    frameCount++;

现在它工作得很好,while 循环的每次迭代都会导致它播放动画中的下一帧(顺便说一下,这个动画是角色类的一部分)。

我面临的问题是动画的速度。它发生在游戏当前的 FPS 为 60。我希望能够单独控制播放器动画的速度,以便将其减慢到合理的速度。

有人对我该如何做这件事有任何建议吗?

注意:总共有 13 帧。

【问题讨论】:

    标签: c++ animation sdl frame-rate


    【解决方案1】:

    您已将刷新率 (60 fps) 与动画率分开。在我看来,最好的解决方案是将动画速率与实时时钟联系起来。在 SDL 中,您可以使用 SDL_Ticks() 函数执行此操作,您可以使用该函数以毫秒为单位测量时间。

    作为一个例子,考虑这个例子(不是工作代码,只是一个草图):

    void init() {
        animationRate = 12;
        animationLength = 13;
        startTime = SDL_Ticks();
    }
    
    void drawSprite() {
        int frameToDraw = ((SDL_Ticks() - startTime) * animationRate / 1000) % animationLength;
        SDL_BlitSurface( hero, &clip[ frameToDraw ], destination, &offset );
    }
    

    如果不清楚,frameToDraw 变量是通过计算动画开始播放后经过的时间来计算的。将其乘以动画速率,就可以得到以动画速率经过的绝对帧数。然后,您应用模运算符将此数字减少到动画长度的范围内,从而为您提供当时需要绘制的帧。

    如果您的刷新率低于动画率,您的精灵将跳过帧以跟上请求的动画率。如果刷新率较快,则会重复绘制同一帧,直到显示下一帧的时间到来。

    我希望这会有所帮助。

    【讨论】:

    【解决方案2】:

    米格尔写的东西很棒。您可以使用的另一种方法是,使用计时器,将其设置为以特定频率触发,并在该频率下增加您的精灵索引。

    请注意,您应该始终将渲染和逻辑分开。

    【讨论】:

    • 我同意,这个解决方案也可以,但是如果您的显示速率低于动画速率,它将使用更多 CPU,因为您仍将全速更新动画状态。
    • 我同意你的方法更快。然而,这种方法更通用一些。例如,如果您想在一段时间内跳过精灵更改或做其他事情,那么您的公式就会变得复杂。
    • 我在解决方案中处理精灵变化的方法是让每个角色跟踪其状态。游戏逻辑触发状态改变,状态改变意味着动画可以停止,或者改变到不同的帧集等。每个精灵都知道它可能的状态是什么。实际上,这真的很容易。
    猜你喜欢
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    相关资源
    最近更新 更多