XNA入门教程----(三) 简单的动画

 

继续我们的XNA之旅...

上周,我们简单的介绍了XNA的相关控制器,并且实现了鼠标和键盘对屏幕内的某个Sprite(精灵)进行简单的位置控制.

但是,美中不足的,我们并没有实现Sprite人物的移动动作,即Animation.

现在,我们继续上周所讲的, 实现简单的动画.

 

关于Animation 

 对动画有所了解的朋友对于逐帧动画一定不会陌生.其以最简单的形式,将各动画元件相邻单位时间的动作位置记录在每个帧里.这样,当我们

一帧帧播放时,由于视觉暂留现象,我们便能看到相对"运动"的动画了.我们通常看到的GIF动画,就是基于这个原理的.

 回来说们的游戏,由于在一般游戏内Sprite的"动作"都是有限可枚举得,我们便同样可以用类似的方案来记录Sprite的所有动作. 

 

我们现在尝试用上面的GIF来实现我们的移动动画.

由于原生的XNA不支持直接从GIF动画中读取各帧图象,即不能直接从Content中Load到GIf动画或其相关帧图像 

虽然从技术上而言,由于有很多开源项目支持如何读取或生成GIF(有兴趣的朋友可以看看这里),我们完全可以通过之自己加载Gif动画的某帧来实现游戏动画。

但这里,我们老老实实的将各帧拆开,得到以下的图像。

 

这样,我们只要通过加载不同的同一图像的不同位置,便可实现人物的”运动“了 。

 

加载动画 

我们回到这个系列的第一篇 

在sprite的Draw时候,我们提供以下重载参数

 

 其中我们就可以通过设置sourceRectangle的值来显示texture2D的一部分了。

 

经过计算,我们得知每个单独人物的尺寸为60X110

这样,我们便用以下方法来动态显示不同“帧”的人物动画了

代码
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->          protected   override   void  Update(GameTime gameTime)
        {
            KeyboardState state 
=  Keyboard.GetState();
            
if  (state.IsKeyDown(Keys.Up))
            {
                
this .Position.Y  -=   10 ;
            }
            
if  (state.IsKeyDown(Keys.Down))
            {
                
this .Position.Y  += 10 ;
            }
            
if  (state.IsKeyDown(Keys.Left))
            {
                
this .Position.X  -=   10 ;
            }
            
if  (state.IsKeyDown(Keys.Right))
            {
                
this .Position.X  +=   10 ;
            }
            MouseState state1 
=  Mouse.GetState();
            
if  (state1.LeftButton  ==  ButtonState.Pressed)
            {
                IPathFinder pathFinder 
=   new  PathFinderFast(m_matrix);
                pathFinder.Formula 
=  HeuristicFormula.Manhattan;
                pathFinder.SearchLimit 
=   2000 ;
                m_path 
=  pathFinder.FindPath( new  Vector2(( int ) this .Position.X, ( int ) this .Position.Y),  new  Vector2(state1.X , state1.Y ));
            }
            
if  ( this .m_path  !=   null   &&   this .m_path.Count()  !=   0 )
            {
                
int  index  =   this .m_path.Count()  -   1 ;
                
this .Position  =   new  Vector2( this .m_path[index].X,  this .m_path[index].Y);
                
this .m_path.RemoveAt(index);
                
return ;
            }
             m_frameIndex  =  m_frameIndex  +   1   >   5   ?   0  : m_frameIndex  +   1 ;
            
base .Update(gameTime);
        }
        
protected   override   void  Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
          
   this .spriteBatch.Draw( this .img,  new  Vector2( this .Position.X,  this .Position.Y),  new  Rectangle(m_frameIndex  *  m_frameSize.X,  0 , m_frameSize.X, m_frameSize.Y), Color.White,  0 , Vector2.Zero, 1f, SpriteEffects.None,  0 );
            spriteBatch.End();
            
base .Draw(gameTime);
        }

 其中,m_frameSize 便是我们每个单独动作的尺寸   Point m_frameSize = new Point(60, 110);

编译后,我们 便能看到“动”的人物了。

 

调节动画的“速度” 

我们很快发现,用这个方法显示的逐帧动画很暴走。即动画帧变化速度太快了。

这其实是由于我们的动画变帧逻辑在Update方法中,而通常,update的调用是基于游戏内置循环的,即根据XNA的默认刷新率---60fps(Frame/Second)。 

如果直接用默认速度的帧循环速度,一则CPU使用率太高,二则也没有这个必要。这里,我们决心“降低”帧数。

我们知道,在XNA中,我们可以通过gameTime.ElapsedGameTime得到自从上次循环结束后到现在的时间。

因此,我们可以将我们的Update方法改成如下结构

代码
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->    protected   override   void  Update(GameTime gameTime)
        {
            timeSinceLastFrame 
+=  gameTime.ElapsedGameTime.Milliseconds;
            
if  (timeSinceLastFrame  >  millisecondsPerFrame)
            {
                timeSinceLastFrame 
-=  millisecondsPerFrame;
                
// TODO
            }
        }

 

 其中,int millisecondsPerFrame = 50;就是我们设定的阀值。

经过以上修改,我们就会发现帧速明显下降,当然,CPU使用率也下去了。 

 

一些细节 

或许大家发现,人物不动时还在原地跑步,只需我们加上类似下文逻辑即可。 

代码
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->   if  (isActive)
                {
                    m_frameIndex 
=  m_frameIndex  +   1   >   5   ?   0  : m_frameIndex  +   1 ;
                }
                
else
                {
                    m_frameIndex 
=   0 ;
                }

 

总结 

本文主要简单介绍了逐帧动画及其在XNA中的实现。并且引入了帧速的控制。相信各位看完本文,便会对XNA的简单2D动画有了一个全面的了解。 

本例源代码

To Be Continue....

转自 http://www.cnblogs.com/edwin1986/archive/2010/01/26/1656659.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值