游戏编程 - 一






4.67/5 (36投票s)
介绍用于创建简单游戏的方法。
引言
这些教程的初步目的是向您展示如何从零开始创建一个简单的游戏,而无需借助 XNA 或 DirectX 等高级 API,这些 API 会为您自动化一半的过程。我们将仅使用 Windows Form 和 GDI+ 进行一些基本的绘图,并为了方便起见,使用 Form 的一些事件。
下一篇 » |
背景
游戏循环和逻辑流程会存在一些奇怪之处;这是因为 Windows Forms 是基于事件的,而总体而言,游戏通常不是。我将指出一些“常规”代码与必须用于 Windows Form 的代码之间可能存在的差异。
步骤 1:设置游戏
基本循环
由于游戏通常不是事件驱动的,因此我们使用一个循环并在该循环中执行所有逻辑和绘图。因此,在每个循环中,我们将执行游戏逻辑、检查输入,并将图形绘制到屏幕上。看看下面的代码。您能发现任何问题吗?
bool runGame = true;
while(runGame)
{
GetInput();
PerformLogic();
DrawGraphics();
}
如果您注意到游戏将以尽可能快的速度运行,那么恭喜您。使用此循环,游戏将以尽可能快的速度运行,速度可能从 1fps 到 1000fps 以上不等。随着敌人或对象添加到游戏中,游戏的速度可能会有所不同,玩家可能根本来不及反应。
一切关乎时机
我们需要控制游戏运行的速度;为此,我们使用一个计时器。计时器将设置一个标志,以便我们知道何时在主循环中运行逻辑;这样,游戏将以更易于管理的速度运行。
Timer MainTimer;
//The timer’s interval is in milliseconds, so we need to work out
//how long each interval should be
MainTimer.Interaval = 1000/60;
bool runGame = true;
volatile bool doStuff = false;
Main()
{
while(runGame)
{
if(doStuff)
{
GetInput();
PerformLogic();
DrawGraphics();
doStuff = false;
}
}
}
Timer()
{
doStuff = true;
}
我们可以做得更好!
尽管这会将游戏速度限制在可接受的水平,但仍有更多我们可以做的事情。将图形绘制到屏幕通常是游戏中速度最慢的部分,因此如果场景渲染花费的时间太长,它将导致逻辑运行缓慢,整个游戏都会减慢。为了避免此问题,我们需要将图形绘制与其余逻辑分开,然后我们需要确保逻辑优先于场景渲染。这意味着如果逻辑落后,我们不应该在当前循环中更新图形,因此我们丢弃该帧。
这是我们将用于管理我们游戏的设置
Timer MainTimer;
//The timer’s interval is in milliseconds, so we need to work out
//how long each interval should be
MainTimer.Interaval = 1000/60;
bool runGame = true;
volatile uint speedCounter = 0;
Main()
{
while(runGame)
{
if(speedCounter >0)
{
GetInput();
PerformLogic();
speedCounter--;
if(speedCounter == 0)
DrawGraphics();
}
}
}
Timer()
{
speedCounter++;
}
在此循环中,只有当计数器大于零时,逻辑才会运行。运行完所有逻辑后,我们将计数器减一,如果计数器回到零,我们将更新场景。如果整个循环花费的时间超过一帧(计时器的间隔),那么当我们减少计数器时;它仍然会大于零,因此我们丢弃该帧,看看是否可以争取一些时间。
窗体的更改
如果在 Windows Form 上使用 `while` 循环,Windows 将永远不会更新屏幕,应用程序将挂起。因此,我们将把逻辑放在计时器的回调函数中,至少目前是这样 - 稍后,我们将把它放到自己的线程中。除此之外,一切都将保持不变。最终的代码看起来会像这样
bool drawGraphics = false
void TimerElapsed()
{
//Increase the counter
speedCounter++;
GetInput();
PerformLogic();
speedCounter--;
//If the counter is 0, then the logic is not running slow
//we can therefore get on with drawing the graphics
if(speedCounter == 0)
drawGraphics = true;
}
我们还需要重写 `OnPaint` 和 `OnPaintBackground` 方法,以便 Windows 不会自己进行任何绘制,我们可以自己处理。请记住,我们不会调用 `base.OnPaint` 或 `base.OnPaintBackground`。
protected override void OnPaint(PaintEventArgs e)
{
//We do our drawing here
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//Do nothing
//base.OnPaintBackground(e);
}
GDI+
由于我们将使用它来绘制图形,我认为最好回顾一下如何使用它。要开始绘图,我们需要一些东西
- 一个图形对象(它将负责绘图)。
- 一个用于绘图的表面。
- 一支画笔或一支笔 - 真的。
如果我们重写窗体的 `OnPaint` 方法,我们可以使用 `PaintEventArgs` 中的 `Graphics` 对象,它已经将窗体作为表面。然后,您可以使用 `Graphics` 对象中的方法在屏幕上绘图。
override void OnPaint(PaintEventArgs e)
{
//We can draw with e.Graphics
//Brushes are used to fill areas
Brush myBrush = new SolidBrush(Color.Red);
e.Graphics.FillRectangle(myBrush,0,0,100,100);
//Pens are used to draw lines
Pen myPen = new Pen(Color.Green);
e.Graphics.DrawLine(myPen, 50, 250, 65, 15);
}
演示
演示包含我们一直在谈论的游戏循环,以及一些绘图代码,以便我们可以看到屏幕上的内容。
什么?家庭作业!
在我撰写下一篇文章(或者在你阅读它之前),为什么不尝试编辑演示,让圆形在屏幕上移动?哦,拜托,这并不难,我知道如果你尝试,你就能做到。
即将推出
好吧,我今天就到这里。但好消息是,既然我们有了基本的游戏代码,我们就可以开始对它进行操作了。下一篇文章将介绍
- 双缓冲
- 获取输入
- 设置 FPS 计数器
- 绘制和动画精灵
您想要什么?
您可以随时发表您希望在这些文章中看到的内容。我在这里提供帮助,如果您知道如何做您所要求的,我会尝试包含它。这些文章将涉及 2D 游戏的世界,并向上延伸到 3D 领域 - 尽管我们可能需要为此切换到 C++ 和 OpenGL。我一直不太喜欢 DirectX,也从未使用 XNA 进行 3D。请记住,我不是要给您代码来制作游戏,而是向您展示如何构建可用于制作游戏的 कोड - 如果您跟上,语言就不那么重要了。
历史
- 2008 年 5 月 8 日 - 文章提交。