§5.3 插入更多游戏组件
甚至在你注意到你的图像引擎已经成长为一个惊人的尺寸之前,你立刻拥有了大量的有用的类,这些类帮助你渲染2D和3D数据相当容易,就如你所见在大多数类中可以得到许多单元测试(如图5-14)。
到现在为止你还没有用过许多游戏组件,并且在你看来用组件编写图像引擎没有太重大的意义。你没有用任何Update 方法,或 Draw 方法,而游戏组件这种方式用到了。OK,Model 类使用了一个 Render方法,Input 类有一个 Update方法,不过除了you did not have any functionality that is compatible with game components。在model中的Render 方法和texture中的Render 方法工作完全不相同因为它们期待用户以不同的值调用它们,并且每一帧非常频繁的调用。我猜 Input 类可以被修改为一个游戏组件,不过我对这个主意并不非常兴奋。
取代我们考虑组件,哪一个更合适于游戏组件模型。如果你有一个类需要每一帧都被更新和绘制,那就有意义。这种类的范例可能是每秒帧的计数器或者摄像机类,你的引擎仍然缺少这个类。
简单的照相机类Simple Camera Class
对于你的单元测试,你不需要一个复杂的摄像机,不过它能四处移动一点,并且在你的引擎单元测试中对你渲染的对象有一个简单的3D观测就不错了。在view matrix 和 Matrix.CreateLookAt 方法的帮助下,你轻易就能创建上述功能,并且把它设置在任何你需要的地方。使用一个游戏组件类自动去做所有这些甚至更好;你必须去做的所有事是在YourGame 类的构造器中创建一个camera 类的实例,YourGame 类继承自BaseGame 类,并且不用额外的代码,所有的单元测试和其他3D代码突然将使用这个新的camera 类,因为对于YourGame 类中拥有的每一个游戏组件,Update方法被你自动调用。
public YourGame() {
// Init simple camera
this.Components.Add(new SimpleCamera(this));
} // YourGame()
SimpleCamera 类有一个构造器、 一个Initialize 方法和Update方法,这两者也都被自动调用。对于摄像机的X、Y、Z位置也有3个字段成员变量,它被初始化为 (0, 0, 15)。然后Update方法基于鼠标的移动改变 x 和 y ,或者如果你有一个gamepad,给予正确的操纵杆移动。此外,你能用左thumb stick放大缩小。
这个类相当简单,易于阅读整个代码:
/// <summary>
/// Simple camera class just to move around a little.
/// Always focuses on the center and uses the same height.
/// </summary>
class SimpleCamera : GameComponent {
#region Variables
float x = 0, y = 0;
float zHeight = 15.0f;
#endregion
#region Constructor
public SimpleCamera(BaseGame game) : base(game)
{
}
// SimpleCamera(game)
#endregion
#region Initialize
public override void Initialize() {
base.Initialize();
} // Initialize
#endregion
#region Update
public override void Update(GameTime gameTime) {
base.Update(gameTime);
// Update camera position (allow mouse and gamepad)
x += Input.MouseXMovement / 10;
y += Input.MouseYMovement / 10;
x += Input.GamePad.ThumbSticks.Right.X;
y += Input.GamePad.ThumbSticks.Right.Y;
zHeight += Input.GamePad.ThumbSticks.Left.Y;
BaseGame.ViewMatrix = Matrix.CreateLookAt( new Vector3(x, y, zHeight), Vector3.Zero, Vector3.Up);
} // Update(gameTime)
#endregion
} // class SimpleCamera
这里重要的一件事是来自于BaseGame类的ViewMatrix,它在Update 方法的末尾被设置。在model类或者在任何其他诸如line manager中渲染shader的时候,你将使用这个view matrix 并且确定你所有的 3D 数据被转换到你的view space with this exact matrix 直到你在下一帧再次修改它。
对于你在本章开始编写的TestRenderOurNewGraphicEngine 测试,现在你一起拥有一切,如果你朝项目中的所有导入的和编写的类看一看,它一个既易于使用也能够扩展的相当好的引擎,你将在下一章探索这些。
ScreenshotCapturer类
在引擎中还有另一个辅助类叫做ScreenshotCapturer,它允许你使用Print-Screen 键抓取屏幕快照。它也被作为一个游戏组件实现,并且被BaseGame 构造器初始化。Update 方法被自动地调用,如果用户正好按了Print-Screen 键就调用MakeScreenshot方法 :
public override void Update(GameTime gameTime)
{
if (Input.KeyboardKeyJustPressed(Keys.PrintScreen))
MakeScreenshot();
base.Update(gameTime);
} // Update(gameTime)
MakeScreenshot 方法创建一个临时的texture 纹理,并且在device的ResolveBackBuffer方法的帮助下保存back buffer。然后借助于类中的某些其它辅助方法,最终结果被保存到磁盘:
using (Texture2D dstTexture = new Texture2D( BaseGame.Device, BaseGame.Width, BaseGame.Height, 1, ResourceUsage.ResolveTarget, SurfaceFormat.Color, ResourceManagementMode.Manual))
{
// Get data with help of the resolve method
BaseGame.Device.ResolveBackBuffer(dstTexture);
dstTexture.Save( ScreenshotNameBuilder(screenshotNum), ImageFileFormat.Jpg);
} // using (dstTexture)
发布时间:2008/8/30 下午3:16:55 阅读次数:6173