问答与练习参考答案
第1章:XNA 4.0有哪些新特性?
问答答案
1. 在XNA 4.0中对XNA文件夹结构进行了什么重大改变?
解决方案中的Content节点,之前是您的游戏项目的子文件夹,而现在它在解决方案中拥有自己的项目。它使您可以轻松的通过多平台项目共享内容。
2. XNA 4.0支持什么游戏平台?
XNA 4.0支持在Windows、Xbox 360与Windows Phone 7系列上的开发。
3. XNA 4.0中Reach和HiDef标准有什么不同?
HiDef是设计用于高功率的一线硬件的,而Reach是设计用来支持更广阔范围的硬件设备。Reach标准提供一个有限的图形特征集合并且它是HiDef的子集。
第2章:入门指南
问答答案
1. XNA Game Studio 4.0 允许您为哪些平台开发游戏?
XNA 4.0 支持Windows Vista、Windows 7、Xbox 360和Windows Phone 7平台的开发。
2. 哪些版本的Visual Studio支持XNA Game Studio 4.0?
Visual Studio 2010 标准版(Standard Edition)或更高级版本(安装了C#语言支持)以及Visual C# 2010 Express Edition
第3章:与精灵同乐
问答答案
1. XNA的游戏循环有哪些步骤?
XNA的游戏循环只由两种方法组成:Update和Draw。
2. 如果想要加载一个Texture2D对象,您需要在哪个方法中做这件事?
LoadContent。
3. 要把XNA游戏的帧率改为20fps,您应该使用什么样的代码?
下面两行代码中的任意一行都可以:
TargetElapsedTime = TimeSpan.FromMilliseconds(50);
TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 50);
4. 在加载一个Texture2D对象时,您应该向Content.Load传递什么参数?
您想要加载的纹理图像(texture image)的资源名(asset name)。在解决方案资源管理器中通过查看属性您可以找到一个图像的资源名。
5. 真还是假:如果您添加到项目中的文件不能被内容管道解析,它将会在编译期告诉您。
正确。内容管道对所有内容(纹理、模型、声音等等)进行编译,然后将结果以兼容XNA格式的对象输出。如果编译过程失败的话,输出的结果就是一个编译错误。
6. 您绘制一个精灵,并且想让背景透明,需要哪些步骤?
在XNA中有两种方法绘制透明图像。第一种方法有两个要求。首先,您的图像文件本身的背景要是透明的,如果不是的话需要用一个图像编辑器将它的背景编辑为透明。其次SpriteBlendMode.AlphaBlend必须被使用了(如果SpriteBatch.Begin中没有指定参数,默认使用SpriteBlendMode.AlphaBlend)。第二种方法就是保证图像文件的透明部分是实心红紫色(255, 0, 255)。
7. 您有两个精灵(A和B),当它们重合时您希望A总是在B之上绘制,您应该怎么做?
有两种解决方法:使用SpriteSortMode.FrontToBack,您可以把A的层深度设置成比B的大(A和B的层深度值都应该在0到1之间);或者,使用SpriteSortMode.BackToFront,然后您把A的层深度值设置成比B的小。
8. 在循环遍历一个精灵位图的时候,您需要追踪哪些变量?
要绘制的当前帧,每个独立帧的大小以及您的精灵位图的行数和列数。
练习答案
在本章中,您开发了一个两个XNA LOGO在屏幕上移动并在边缘之间反弹的例子。现在把本章末尾的动画动画例子改写成和它一样的移动和反弹方式——不过这一次要让动画精灵同时沿着X轴和Y轴移动,并且在屏幕的四个边缘之间反弹。
这个练习比较简单,就是将本章的两个例子综合一下。练习要求的动画部分在本章末尾有介绍,而精灵移动及碰到边界弹回则在本章中间部分有介绍。
一个可能有些难实现的要求就是同时沿着X和Y方向进行移动。在前面的精灵移动例子中,您为精灵使用了一个float变量并根据移动精灵的不同而将该变量添加到X或Y坐标中(两个精灵都只沿着一个方向移动)。
现在我建议使用一个Vector2来代表速度,这样您就可以为X方向的速度和Y方向的速度记录不同的数值,而且您还可以通过直接相加的方式将您的Vector2速度加到您的Vector2位置(您可以像加整型或浮点型数值那样对Vector2对象进行相加)。
本练习的另一个意思是,在之前的移动例子中您利用Texture2D对象的大小来决定精灵应该向边界的反方向弹回多远,不过现在您的Texture2D对象的大小将会不准确了,因为您在用一个精灵位图,您现在需要根据精灵位图中的一个单帧的大小来检测图像什么时候碰到了屏幕的边界。
下面给出一个本例的解决方法:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace AnimatedSprites
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D texture;
Point frameSize = new Point(75, 75);
Point currentFrame = new Point(0, 0);
Point sheetSize = new Point(6, 8);
//Framerate stuff
int timeSinceLastFrame = 0;
int millisecondsPerFrame = 16;
//Speed and movement
Vector2 speed = new Vector2(5, 2);
Vector2 position = Vector2.Zero;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
texture = Content.Load<Texture2D>(@"Images\threerings");
}
protected override void UnloadContent()
{
// TODO: Unload any non-ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back ==
ButtonState.Pressed)
this.Exit();
//Update time since last frame and only
//change animation if framerate expired
timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
if (timeSinceLastFrame > millisecondsPerFrame)
{
timeSinceLastFrame -= millisecondsPerFrame;
++currentFrame.X;
if (currentFrame.X >= sheetSize.X)
{
currentFrame.X = 0;
++currentFrame.Y;
if (currentFrame.Y >= sheetSize.Y)
currentFrame.Y = 0;
}
}
//Move sprite
position += speed;
//If the sprite hit a wall, reverse direction
if (position.X > Window.ClientBounds.Width - frameSize.X ||
position.X < 0)
speed.X *= -1;
if (position.Y > Window.ClientBounds.Height - frameSize.Y ||
position.Y < 0)
speed.Y *= -1;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);
spriteBatch.Draw(texture, position,
new Rectangle(currentFrame.X * frameSize.X,
currentFrame.Y * frameSize.Y,
frameSize.X,
frameSize.Y),
Color.White, 0, Vector2.Zero,
1, SpriteEffects.None, 0);
spriteBatch.End();
base.Draw(gameTime);
}
}
}