如何使用 Windows Mobile 7 实现 SpriteSheet (Atlas)?
1 回答
移动设备面临的挑战之一是如何在应用程序的生命周期内加载许多图像并仍然从移动设备获得良好的性能。以下是关于如何在 windows mobile 7 中使用 Sprite Sheet 的简短说明。什么是 Sprite Sheet,我们为什么需要它?
当我们创建应用程序或游戏时,通常我们需要呈现许多图像。在代码中分别调用每个图像会在应用程序的生命周期内为我们创建巨大的开销性能。当涉及到硬件资源有限的移动设备时,有效地使用这些精灵(图像)以获得良好的性能非常重要。那么 spritesheet 如何帮助我们呢?Sprite Sheet 是包含许多小精灵(图像)的大图像文件,因此我们只使用一个图像文件,而不是使用许多图像!我们的代码调用它一次,并且由于图像有序地存储在该图像文件上,它还节省了不必要的未使用空间,从而在加载时减少了内存。下面是关于如何使用 Windows Mobile 7 进行操作的说明。我对 Microsoft 发布的原始 KB 进行了一些修改。
- 从http://create.msdn.com/en-US/education/catalog/sample/sprite_sheet下载代码
- 提取它。
- 要在您自己的游戏中重用此代码,请将 SpriteSheetPipeline 和 SpriteSheetRuntime 项目添加到您的解决方案中。
A. 使管道项目可用于构建您的内容
- 右键单击内容 | 内容项目中的参考项目。
- 单击添加参考。
- 单击项目选项卡,然后选择 SpriteSheetPipeline 项目。
B. 使 SpriteSheet 类可用于您的游戏
- 右键单击主游戏项目中的 References 项。
- 单击添加参考。
- 单击 Projects 选项卡,然后选择 SpriteSheetRuntime 项目
现在要实际使用我们导入的代码,我们首先将创建一个新的 xml 文件并放在内容目录中,XML 的格式应该是这样的:
<?xml version="1.0" encoding="utf-8" ?>
<XnaContent>
<Asset Type ="System.String[]">
<Item>L01_480_0.png</Item>
<Item>L01_480_1.png</Item>
<Item>L01_480_2.png</Item>
<Item>L01_480_3.png</Item>
<Item>L01_480_4.png</Item>
<Item>L01_480_5.png</Item>
<Item>L01_480_6.png</Item>
<Item>L01_480_7.png</Item>
<Item>L01_480_8.png</Item>
<Item>L01_480_9.png</Item>
<Item>L01_480_10.png</Item>
<Item>L01_480_11.png</Item>
<Item>L01_480_12.png</Item>
</Asset>
</XnaContent>
如您所见,此 xml 包含我们将创建 SpriteSheet(atlas) 的图像的名称,无需通过 Visual Studio 将这些精灵图像添加到您的项目中,只需将图像复制到物理内容目录,当然要求您通过 Visual Studio 将 XML 文件添加到 Content 文件夹项目中(这不是主要项目,因此请注意) 现在要实际使用 XML 文件,您需要做一些事情。我们需要设置xml文件的属性。Content Importer 将是 XML Content - XNA Framework Content Processor 将是SpriteSheetProcessor 设置好属性后,我们可以实际调用文件。首先我们将告诉我们的代码使用 SpriteSheetRuntime
所以我们将添加
using SpriteSheetRuntime;
我们将声明新的 spritebatch 和 spritesheet 对象
namespace SpriteSheetGame
{
/// This is the main type for your game
public class Game: Microsoft.Xna.Framework.Game
{
/* Handles the configuration and management of the graphics device.*/
GraphicsDeviceManager graphics;
/* Enables a group of sprites to be
drawn using the same settings */
SpriteBatch spriteBatch;
/* A sprite sheet contains many individual sprite images, packed into different
areas of a single larger texture, along with information describing where in
that texture each sprite is located */
SpriteSheet spriteSheet;
}
在加载内容中,我们将执行以下操作:
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
spriteSheet = Content.Load<SpriteSheet>("SpriteSheet");
}
在这种情况下,XML 文件将是 SpriteSheet.xml,就像上面的例子一样。现在我们需要通过动画或一次显示所有精灵来显示精灵。所以我们将使用以下 spriteBatch.Draw,但在此之前我们将启动 spriteBatch
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
如果您查看类(SpriteBatch),您会发现很少有选项可以在屏幕上绘制,您可以选择最适合您的:
public void Draw(Texture2D texture, Vector2 position, Color color);
public void Draw(Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color);
public void Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color);
public void Draw(Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth);
public void Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth);
public void Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth);
所以最终我们可以这样写:
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
// Draw an animating effect, by rapidly cycling
// through 13 slightly different sprite images.
const int animationFramesPerSecond = 2;
const int animationFrameCount = 13;
// Look up the index of the first sprite.
int index = spriteSheet.GetIndex("L01_480_0");
// Modify the index to select the current frame of the animation.
index += (int)(time * animationFramesPerSecond) % animationFrameCount;
// Draw the current sprite.
spriteBatch.Draw(spriteSheet.Texture, new Rectangle(0, 0, 100, 100),
spriteSheet.SourceRectangle(index), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}