SDL游戏教程第五课 动画

翻译声明:
    本系列教程来自
Dev Hub,一切解释权归原作者。我只是出自个人爱好,才翻译了本系列教程。因为本人也是个初学者,而且英语水平有限,错误难免,望各路高手指正。

本课原文地址:http://www.sdltutorials.com/sdl-animation/

上节课我们试着完成了一个井字游戏。但愿你们都能成功运行。如不然,也没什么好烦的,你最终会进入状态的。

本节课我们就开始着手SDL动画。和往常一样,我们还是建立在最近一次SDL课程的基础之上(但是不包括那个井字游戏了)。那么我们就开始吧。

我们将创建一个新的类来处理动画,然后下节课我们还会新建一个处理实体的类。请记住,这两样东西是要区分开来的,尽管我也知道他们可以是同一个类,可我不想那么做。所有,还是请保留你的异议吧。

创建两个新的文件(我想你已经发现一种模式了,但愿如此),分别是CAnimation.h和CAnimation.cpp。最后,我们的CEntity类将要继承这个类,但是现在我们要通过稍后创建的一个对象来测试一下。开始之前,添加带有CApp.h的包含指令(就在#include "CEvent.h"之前就行)。

#include "CAnimation.h"

现在打开CAnimation.h,开始写代码。添加下面的基类结构到你的文件。
  1. #ifndef _CANIMATION_H_
  2. #define _CANIMATION_H_
  3. #include <SDL.h>
  4. class CAnimation {
  5.     private:
  6.         int CurrentFrame;
  7.         int     FrameInc;
  8.     private:
  9.         int     FrameRate; //Milliseconds
  10.         long    OldTime;
  11.     public:
  12.         int MaxFrames;
  13.         bool    Oscillate;
  14.     public:
  15.         CAnimation();
  16.         void OnAnimate();
  17.     public:
  18.         void SetFrameRate(int Rate);
  19.         void SetCurrentFrame(int Frame);
  20.         int GetCurrentFrame();
  21. };
  22. #endif
现在,打开CAnimation.cpp,添加如下代码:
  1. #include "CAnimation.h"
  2. CAnimation::CAnimation() {
  3.     CurrentFrame    = 0;
  4.     MaxFrames       = 0;
  5.     FrameInc        = 1;
  6.     FrameRate       = 100; //Milliseconds
  7.     OldTime         = 0;
  8.     Oscillate       = false;
  9. }
  10. void CAnimation::OnAnimate() {
  11.     if(OldTime + FrameRate > SDL_GetTicks()) {
  12.         return;
  13.     }
  14.     OldTime = SDL_GetTicks();
  15.     CurrentFrame += FrameInc;
  16.     if(Oscillate) {
  17.         if(FrameInc > 0) {
  18.             if(CurrentFrame >= MaxFrames - 1) {
  19.                 FrameInc = -FrameInc;
  20.             }
  21.         }else{
  22.             if(CurrentFrame <= 0) {
  23.                 FrameInc = -FrameInc;
  24.             }
  25.         }
  26.     }else{
  27.         if(CurrentFrame >= MaxFrames - 1) {
  28.             CurrentFrame = 0;
  29.         }
  30.     }
  31. }
  32. void CAnimation::SetFrameRate(int Rate) {
  33.     FrameRate = Rate;
  34. }
  35. void CAnimation::SetCurrentFrame(int Frame) {
  36.     if(Frame < 0 || Frame >= MaxFrames) return;
  37.     CurrentFrame = Frame;
  38. }
  39. int CAnimation::GetCurrentFrame() {
  40.     return CurrentFrame;
  41. }
现在需要对这个类做点解释了。动画的当前帧是动画里我们要处理的一个基本元素。取得例子下面的这幅Yoshi的图像(我们会在本课后面用到它)。你会发现一幅图像里有八个Yoshi帧。自顶向下,美珍都有一个标记0,1,2。



还记得我们第二节课创建的那个绘制部分图像的那个函数吗?那么,如果我们把那个函数和动画里的帧结合起来,就是这样!

所以我想让你看的第一个变量就是CurrentFrame。这就是我们要想屏幕绘制动画的当前帧。不管它是什么值,它决定了我们要向屏幕要绘制表面的哪一部分。因此,当我们调用绘制函数时,我们就应该这样做:

CSurface::OnDraw(Surf_Display, Surf_Image, 0, 0, 0, Anim_Yoshi.GetCurrentFrame() * 64, 64, 64);

因为你的Yoshi的确是64*64像素的,这里的宽度和高度是我们感兴趣的,同样我们对帧也感兴趣。看看下面图示的图像:



当CurrentFrame增1,我们跳到64像素(Yoshi帧的高度),然后绘制那一帧。

类中的MaxFrames,是我们需要知道的这个动画一共有多少帧。最后一个我们要知道的重要部分是每秒绘制多少帧,或说,动画要以多快的速率显示。使用OnAnimate函数里的下面一段代码来决定我们的这个问题。

if(OldTime + FrameRate > SDL_GetTicks()) {
    return;
}

 
通过以毫秒计的旧有时间加上我们需求的帧率,我们可以把它和SDL库的运行时间(译注:即从SDL库初始化开始算起)做个对比。比如,我们才刚开始游戏。SDL_GetTicks就是0,OldTime也是0。我们要求的帧率是1帧/秒。那么,FrameRate = 1000(ms)。因此,0+1000比0大吧?没错,于是我们就跳过这个函数然后等待。一旦0+100比SDL_GetTicks小了,那就意味着1秒已经过去了。于是我们增加帧,然后重置OldTime为当前时间,然后重新开始。

下一个有趣的地方是Osillate和FrameInc。添加这些并不是我想要迷惑人,而是我感觉这对后面的东西是很必要的。如果Oscillate标志为真,动画就会增加帧,然后递减帧。如果我们有一个10帧的动画,那么就会像这样:

 0 1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1 2 …

你看,它递增到了9,然后递减又回到了0,如此循环往复。这有一些很有趣的应用,但我们将会在其他课程中探讨。那么,它到底怎么运行?看看OnAnimate函数。

void CAnimation::OnAnimate() {
    if(OldTime + FrameRate > SDL_GetTicks()) {
        return;
    }

    OldTime = SDL_GetTicks();

    CurrentFrame += FrameInc;

    if(Oscillate) {
        if(FrameInc > 0) {
            if(CurrentFrame >= MaxFrames - 1) {
                FrameInc = -FrameInc;
            }
        }else{
            if(CurrentFrame <= 0) {
                FrameInc = -FrameInc;
            }
        }
    }else{
        if(CurrentFrame >= MaxFrames - 1) {
            CurrentFrame = 0;
        }
    }
}

错误修正:如果把“CurrentFrame += FrameInc; ”放到if语句的后面,会导致一个错误,它应该被放到if语句的前面。如果动画遇到MaxFrames=0的话,它依然会把CurrentFrame递增 到1。多谢Alexander Mangel帮忙发现了这个bug!

我们已经知道了OldTime等的用法,但然后呢?现在,看看Oscillate的if语句相应的else语句。你会发现我们仅仅检查了CurrentFrame是否越界超过最大帧数。如是,就重置为0。确实很简单。然后在下面,在此块外面,我们递增到下一帧。

现在,最迷惑人的部分是这个Oscillate的if语句。在此增加了FremeInc变量。基本上FrameInc就是根据我们如何递增或递减帧,而被设置为1或-1.记住,来回摆动导致帧从0到9然后回到0。当FrameInc大于0时,我们就递增帧,否则,我们就递减帧。最里面的if语句就是,当我们到达0或最大帧的时候取反FrameInc。

现在一切搞定,就让我们使用一下这个类。在CApp.h里,创建一个新的CAnimation对象:

CAnimation      Anim_Yoshi;

现在,我们设置MaxFrames,然后把它添加到CApp_OnInit:

Anim_Yoshi.MaxFrames = 8;

如果你想看看来回摆动的动画,设置如下:

Anim_Yoshi.Oscillate = true;

Okay,现在来创建我们的动画循环,向CApp_OnLoop添加如下:

Anim_Yoshi.OnAnimate();

现在,最后一件事,在CApp_OnRender添加如下,来制作实际的动画:

CSurface::OnDraw(Surf_Display, Surf_Test, 290, 220, 0, Anim_Yoshi.GetCurrentFrame() * 64, 64, 64);

现在试着编译一下吧,看看你的小恐龙在集训呢!一定要用Yoshi的图像来替换掉myimage.bmp。

SDL 动画 —— 课程文件:

Win32: Zip, Rar
Linux: Tar
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android SDL(Simple DirectMedia Layer)是一个用于开发跨平台多媒体应用程序的库。它提供了对音频、视频、输入设备和图形的抽象,使开发者能够更方便地创建游戏和其他多媒体应用。 以下是一个简单的Android SDL开发教程的步骤: 1. 配置开发环境:首先,你需要安装Android Studio,并确保已经配置好了Java开发环境和Android SDK。 2. 创建新项目:在Android Studio中创建一个新的Android项目。 3. 导入SDL库:下载SDL库的最新版本,并将其导入到你的Android项目中。可以将SDL库作为一个模块导入,或者将其源代码直接复制到你的项目中。 4. 配置SDL库:在你的项目中,找到SDL库的配置文件(通常是一个名为"Android.mk"的文件),根据你的项目需求进行配置。这包括指定编译选项、链接库和其他依赖项。 5. 创建SDL活动:在你的Android项目中创建一个新的活动(Activity),该活动将作为SDL应用程序的入口点。在活动中,你需要初始化SDL库并处理与SDL相关的事件。 6. 处理输入和绘制:使用SDL提供的函数来处理用户输入和绘制图形。你可以使用SDL提供的函数来处理键盘、触摸屏和其他输入设备,并使用SDL提供的函数来绘制图形和动画。 7. 构建和运行:完成代码编写后,使用Android Studio构建你的应用程序,并在模拟器或真机上运行。 这只是一个简单的Android SDL开发教程的概述,实际开发中可能会涉及更多的细节和技术。你可以参考SDL官方文档和其他相关资源来深入学习和了解Android SDL开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值