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

DX游戏实用类库

starIconstarIconstarIconstarIconstarIcon

5.00/5 (23投票s)

2003年11月10日

4分钟阅读

viewsIcon

135045

downloadIcon

1690

一个托管 DirectX 类库,可用作基本 2D 游戏的基础。包含演示。

最新消息

有关此项目的最新消息,请访问 http://www.danpeverill.com/。如有任何问题或评论,请随时通过 dan@danpeverill.com 发送电子邮件给我。

引言

我创建此项目的初衷是创建一个可重用的托管 DirectX 类库,可用作基本 2D 游戏的基础。我希望我已经成功了。作为一名游戏爱好者,我将 GameUtil 类库呈现给您,以便您也能从其代码中受益。您可以以任何您想要的方式使用它;开始您自己的 2D 游戏,扩展和/或修改代码以满足您自己的需求,或者只是浏览源代码以供学习。

为了方便您使用,并作为迷你教程,我包含了一个演示项目,展示了使用 GameUtil 类库构建基本 2D 游戏引擎的便捷性。

要求

除了 .NET 1.0/1.1(您应该已经安装了)之外,您还需要最新版本的 托管 DirectX SDK(撰写本文时是 DirectX 9.0 SDK Update Summer 2003)。是的,即使是演示项目也需要它。

特点

DDGameSurface

此类可用作游戏表面,可以附加到任何 .NET 控件。它被设计得非常灵活,允许窗口(无论是 Form 还是 Control)和伪全屏模式。它为您处理一切,包括后备缓冲区工作和恢复丢失的表面。

创建和显示 DDGameSurface 再简单不过了;

DDGameSurface gameSurface = new DDGameSurface(control);

gameSurface.Clear(Color.White);
gameSurface.DrawText(0, 0, "Hello!", false);
gameSurface.Display();

gameSurface.Dispose();

DDGraphic

DDGraphic 类派生自 Surface 类,并提供了更友好的游戏功能,包括设置帧、帧大小以及检索要绘制的帧区域。这对于动画非常有用。但不用担心,如果您的图形没有帧,您不必设置这些详细信息。

这是对上述示例的扩展,展示了如何创建和显示 DDGameGraphic

DDGraphic playerGraphic = new DDGraphic("player.bmp", 
    new SurfaceDescription(), gameSurface);
playerGraphic.SetTransparency(0x00111111);
playerGraphic.FrameSize = new Size(32, 32);

if (gameSurface.CanDraw) {
      gameSurface.Clear(Color.White);
      gameSurface.DrawTransparent(0, 0, playerGraphic, 
          playerGraphic.GetFrameArea(0));
}

gameSurface.Display();

playerGraphic.Dispose();

DDGameGraphics

通常您不会直接创建 DDGraphic,而是希望此类来处理所有繁琐的工作。DDGameGraphics 类充当您游戏图形的查找表,您可以通过简单的 XML 编辑技能即时更改它。这样,您就可以通过简单的对象实例化来加载所有游戏图形(或特定地图的图形)。此类还提供了灵活性。您不再需要将所有那些讨厌的常量硬编码到您的图形所在的位置,而是可以使用 DDGameGraphics 类,它会使用 XML 文档提供的信息为您加载它们。是的,还支持嵌入式图形。

这是对上述代码的进一步扩展;

// graphics.xml (note that the only required attributes are key and path)
<GameGraphcs>

      <graphic key="player" path="Namespace.player.bmp" 
            frameWidth="32" frameHeight="32" transColor="00111111" 
                 embedded="true"/>

      <graphic key="enemy" path="Namespace.enemy.bmp" 
            frameWidth="32" frameHeight="32" transColor="00111111" 
                 embedded="true"/>

</GameGraphics>

// Game code...
DDGameGraphics graphics = new DDGameGraphics("graphics.xml", gameSurface);

DDGraphic playerGraphic = graphics["player"];
DDGraphic enemyGraphic = graphics["enemy"];

// Draw graphics.

// No need to dispose our DDGraphics, DDGameGraphics does that for us.
graphics.Dispose();

DIMouse

DIMouse 类起初可能有些奇怪。这是因为 DIMouse 对象只有在调用 Update() 方法时才会更新其内部状态。然而,其他一切都易于理解和使用。DIMouse 类封装了您从鼠标获得的所有功能,包括光标坐标、按钮单击(甚至滚轮单击)以及滚轮移动。但是,与 DDGameSurface 不同,DIMouse 必须为 Form 创建。

这是一个快速示例;

DIMouse mouse = new DIMouse(form);

// Inside game loop.
mouse.Update();
if (mouse.LeftClick) {
      Console.Writeline("Left click at coordinates: " + mouse.Location);
}
// --

mouse.Dispose();

DIKeyboard

DIKeyboard 的工作方式与 DIMouse 完全相同,只是它具有不同的接口来访问键盘信息。

DIKeyboard 演示

DIKeyboard keyboard = new DIKeyboard(form);

// Inside game loop.
if (keyboard[Key.A]) {
      Console.Writeline("The A key is pressed!");
}
// --

keyboard.Dispose();

QPTimer

没有某种高性能计时器,游戏会完整吗?QPTimer 类为您封装了 Query Performance Counter 和 Frequency,因此您只需使用其简单的接口即可。而且不用担心,每秒滴答次数是一个浮点数。另外,没有属性返回每毫秒滴答次数,但这很容易自己解决——只需将 TicksPerSecond 属性乘以 1000。

展示 QPTimer 的游戏循环示例

QPTimer timer = new QPTimer();
timer.Start(QPTimer.Counter);

while (gameRunning) {
      timer.Record();

      // Process mouse input.
      // Process keyboard input.
      // Update game logic with timer.TicksPerSecond.
      // Draw graphics.

      Console.Writeline("FPS: " + 1.0F/timer.TicksPerSecond);

      timer.Start(timer.RecordTime);
}

GameUtil 演示

仅仅提供一个类库而不实际展示如何使用它来创建游戏引擎是没有意义的。所以我已经创建了一个演示,展示了如何利用 GameUtil 类库的大部分功能。即使您真的想,也可以将此演示用作创建自己的 2D 游戏的模板。至少,它将成为一个很好的入门教程。

我想指出一两点;演示中显示的 FPS 比实际游戏中预期的要慢,那是因为演示引擎正在进行一些反射工作,同时还在更新 .NET 控件(我更感兴趣的是展示功能而不是使其高效)。尽管如此,演示仍然可以绘制 2,500 多个图形并保持稳定的 ~30 FPS(我的电脑是 800MHz Athlon,250MB PC133 RAM 和 Geforce 2 MX,所以您的表现可能会有所不同)。

结语

感谢您的阅读,希望您觉得这个类库很有用。

© . All rights reserved.