65.9K
CodeProject 正在变化。 阅读更多。
Home

构建 XNA 灵活动画类

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2014 年 8 月 20 日

CPOL

2分钟阅读

viewsIcon

12426

带有自动动画和灵活精灵加载的 Silverlight 和 XNA 动画类。

引言

即使 XNA 是一个很棒的框架,它也没有自己的动画类。因此,即使你想创建一个简单的动画,也必须自己完成所有操作,在某些情况下这是一种优势,但对于简单的 2D 动画来说却很麻烦。本文档帮助用户创建一个可以摆脱通常需要关注的控制的类。

背景

我不会分别介绍 Silverlight 和 XNA。读者需要了解 XNA 和 Silverlight 的基本知识,主要是 XNA。主要目的是解释如何创建一个动画类,该类可以帮助你进一步开发。在创建 XNA 应用程序和 Windows Phone Silverlight 和 XNA 应用程序之间存在一些差异。由于 Silverlight 应用程序是基于事件的,因此大多数方法参数将是事件参数,但除此之外,主要思想是相同的。

使用代码

首先,我们需要创建 Windows Phone 游戏库 (4.0)。由于我们只会将其用于 xna 类,因此我们需要使用这种类型的项目。

Create Windows Phone library

 

正如我提到的,它将在 xna 类中使用,因此我们需要保持 XNA 方法命名,因此我们需要三个方法

public virtual void Draw(SpriteBatch spriteBatch)

public virtual void Load(ContentManager contentManager, GraphicsDevice graphicDevice)

public virtual void Update(double gameTime)

创建此类时,需要知道每行和每列的精灵数量以及精灵名称。

public Animated2dSpriteBase(int spritesPerWidth, int spritesPerHeight, string spriteName)
{
    this.m_spriteName = spriteName;
    this.m_framesCountPerHeight = spritesPerHeight;
    this.m_framesCountPerWidth = spritesPerWidth;
    this.m_totalFramesCount = spritesPerHeight * spritesPerWidth;
    this.m_currentFrameNo = 1;
    this.IntervalTime = INTERVALTIME;
    this.m_timer = 0;
    this.X = 0;
    this.Y = 0;
    this.Animate = true;
}

加载某些参数时,它们已经在 xna silverlight 应用程序类中声明。内容管理器来自 silverlight 应用程序,例如 (Application.Current as App).Content 和 graphicDevice SharedGraphicsDeviceManager.Current.GraphicsDevice

public virtual void Load(ContentManager contentManager, GraphicsDevice graphicDevice)
{
    m_spriteSheet = contentManager.Load<Texture2D>(m_spriteName);
    m_spriteWindowWidth = m_spriteSheet.Width / m_framesCountPerWidth;
    m_spriteWindowHeight = m_spriteSheet.Height / m_framesCountPerHeight;
    m_spriteOutputRectangle = new Rectangle(0, 0, m_spriteWindowWidth, m_spriteWindowHeight);
}

这里,通过构造函数传递的精灵名称从参数 contentManager 加载。

使用 Sprite bach 与典型的 XNA 游戏类中的用法相同。这里每次只绘制带有正确帧的输出。

public virtual void Draw(SpriteBatch spriteBatch)
{
            spriteBatch.Draw(m_spriteSheet, new Rectangle(X, Y, m_spriteWindowWidth, m_spriteWindowHeight), m_spriteOutputRectangle, Color.White);
}

由于 silverlight xna 类只有 GameTimerEventArgs,它只包含 TimeSpan 类, 我们只能获取传递到 Update 方法的经过时间。

public virtual void Update(double gameTime)
{
   if (gameTime > m_timer && Animate)
   {
     m_timer = gameTime + m_intervalSec;
     m_currentFrameNo++;
     if (m_currentFrameNo > m_totalFramesCount)
        m_currentFrameNo = 1;
      CalculateOutRectanglePosition();
   }
}

这里,如果传递了默认时间 (m_timer) 并且 Animation 布尔标志为 true,我们会更新当前帧号并重新计算输出矩形位置。Animate 标志是属性类型,因此可以在任何时候关闭动画,并且当前帧将输出到屏幕上。

CalculateOutRectanglePosition 的主要目的是使用当前帧号找到输出矩形位置。

private void CalculateOutRectanglePosition()
{
  rowNumber = m_currentFrameNo > m_framesCountPerWidth ? 1 : (m_currentFrameNo - 1) / m_framesCountPerWidth;
  rowNumber++;

  if (m_currentFrameNo <= m_framesCountPerWidth)
  {
    m_spriteOutputRectangle.X = (m_currentFrameNo - 1) * m_spriteWindowWidth;
  }
  else
  {
    if (m_currentFrameNo % m_framesCountPerWidth == 0)
    {
       m_spriteOutputRectangle.X = (m_currentFrameNo - 1) % m_framesCountPerWidth * m_spriteWindowWidth;
    }
    else
    {
      m_spriteOutputRectangle.X = ((m_currentFrameNo % m_framesCountPerWidth)  - 1) * m_spriteWindowWidth;
    }
     m_spriteOutputRectangle.Y = (rowNumber - 1) * m_spriteWindowHeight;
 }

我们已经知道当前是哪一帧,因此可以计算输出矩形位置。假设我们的精灵表如下所示,并且当前帧是 5,那么我们需要找出行号和列号。然后它们将是 2 和 2。计算出这些数字后,很容易计算输出矩形位置。只需将它们乘以行号减 1,因为起始位置从 0 开始。

spriteSheetExample

m_spriteOutputRectangle 是绘制到屏幕上的 Rectangle,因此我们仅在需要时重新绘制其位置。提醒一下,当前帧显示当前屏幕上的动画帧。

 

© . All rights reserved.