Windows Phone开发如何播放游戏精灵动画?

《Windows Phone开发实战体验(应用+游戏)》详细介绍及源代码下载:

http://www.devdiv.com/%E3%80%8AWindows_Phone%E5%BC%80%E5%8F%91%E5%AE%9E%E6%88%98%E4%BD%93%E9%AA%8C_%E5%BA%94%E7%94%A8_%E6%B8%B8%E6%88%8F_%E3%80%8B%E5%BC%80%E5%94%AE-thread-123714-1-1.html

18.1 播放游戏精灵动画

在第16章中介绍了如何用SpriteBatch显示2D纹理。其中的Sprite(精灵),在游戏编程里指一个对象的原型,例如一个战士、一个怪物等。精灵不可能不做动作,就拿简单的走动来说,手脚一定是会动的,那么如何在屏幕上真实地呈现各种动作呢?在2D游戏编程里,通常把人物的动作分解为一帧帧图片,通过连续播放产生动画的效果,与早期的二维动画片制作原理一样。

1)单次播放动画

图18-1是一个小兵的行走动画,可以看到由12张图片组成,那么如何能将这些图片连续地循环播放呢?

图18-1 小兵行走动画分解图

一提到循环,很容易想到for循环。把这12张图片放到一个Texture2D[ ] 数组里,通过for循环实现动画效果代码如下:

for(int i=0;i<SoldierTextures.Count;i++) //伪代码

{

  spriteBatch.Draw(SoldierTextures[i]);

}

2)循环播放动画

用for循环播放动画只能播放一遍,如何才能循环播放呢?可以用之前提到的XNA里的Update函数实现。它可以按固定的时间间隔反复执行,可以把这个函数看做一个特殊的for循环。

使用Update函数实现动画循环播放还需要借助一个全局计数器FrameCount,代码如下:

int FrameCount=0;

void Update() //在Update函数里改变计数器

{

FrameCount++;

if(FrameCount>SoilderTextures.Length-1)//如果播完最后一帧

{

FrameCount=0; //就回到第一帧

}

}

void Draw() //Draw函数里绘制出纹理

{

spriteBatch.Draw(SoilderTextures[FrameCount]);

}

3)编程提示

以上代码都是伪代码,是为了便于大家理解,实际编程中的代码比这里要复杂些。

① 在GameMainScreen类添加构造函数:

       Texture2D[] soilderTextures;

       public GameMainScreen()

       {

          soilderTextures=new Texture2D[12];//初始化小兵纹理数组

      

       }

② 把12张小兵跑动图片放到Content项目下的Enemy/Run文件夹中,如果18-2所示。

图18-2 图片存放位置

③ 用for循环加载这12张图片,代码如下:

  public override voidLoadContent()

  {

    base.LoadContent();

    playerTexture = ScreenManager.Game.Content.Load<Texture2D>("Player/1");

     for(int i = 0; i < 12;i++ )

     {

 soilderTextures[i]=ScreenManager.Game.Content.Load<Texture2D>("Enemy/Run/"+(i+1));

     }

  }

④ 在Draw里绘制出当前帧,代码如下:

  public override voidDraw(GameTime gameTime)

  {

    ScreenManager.SpriteBatch.Begin();

    ScreenManager.SpriteBatch.Draw(soilderTextures[FrameCount], newVector2(100, 200), Color.White);

    ScreenManager.SpriteBatch.End();

       

  }

⑤ 在Update里更新当前帧的位置,依次向后播放,代码如下:

  public override voidUpdate(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)

  {

     base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);

      floatelapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

     FrameCount++;

      if(FrameCount > soilderTextures.Length - 1)//如果播完最后一帧

      {

          FrameCount = 0; //就回到第一帧

      }

  }

在模拟器中的最后运行效果如图18-3所示。

图18-3 运行效果

4)动画频率调整

在模拟器里执行上面写好的代码,可以发现能够循环播放动画了,不过出现了新问题:小兵的跑动频率太快,像超人一样在飞速奔跑。

之所以会出现这种情况,是因为人物动画帧播放的时间间隔其实是远长于Update函数执行的时间间隔的,例如人物动画是1秒播放一帧,而Update函数是1/30秒(0.03333秒)播放一帧。那么如何处理这个问题呢?

回到前面的代码,其实只要控制“FrameCount++”语句执行的时间间隔就可以了。为此需要用到另外一个计数器updateCount,代码如下:

updateCount++;

if(updateCount>TimeSpan)  //伪代码,TimeSpan为时间间隔

{

FrameCount++;

updateCount=0;

}

通过修改TimeSpan的值就能控制FrameCount++执行的时间间隔了。假如TimeSpan=30, 那么Update函数要执行30次,FrameCount++才执行一次。也就说FrameCount++执行的时间间隔为 30*0.033333秒=1秒。

经过反复调整,我们发现TimeSpan=2时,小兵的动作最协调,代码如下:

       int updateCount=0,timeSpan=2;

       public override void Update(GameTimegameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)

       {

           base.Update(gameTime,otherScreenHasFocus, coveredByOtherScreen);

           float elapsedTime =(float)gameTime.ElapsedGameTime.TotalSeconds;

           updateCount++;

           if (updateCount > timeSpan)  // timeSpan为时间间隔

           {

               FrameCount++;

               updateCount = 0;

           }

           if (FrameCount >soilderTextures.Length - 1)//如果播完最后一帧

           {

               FrameCount = 0; //就回到第一帧

           }

       }

运行该段代码,发现精灵动画能够自如地播放了。不过这个小兵精灵并不能前后移动,仍然无法满足游戏需要。这个问题留待下一节解决。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值