Windows 中的自定义 XNA 游戏循环
我试图弄清楚如何在 Windows 游戏中手动管理整个游戏循环,而不使用常规的游戏 Microsoft.Xna.Framework.Game 类。
原因是使用常规 Game 类会导致我的游戏出现一些卡顿。虽然不多,但由于游戏的特殊性,它仍然相当明显。
在尝试了一堆不同的设置(垂直同步、固定时间步长、各种帧速率等)之后,我决定尝试编写自己的游戏类来完全控制时间。我不确定这会解决它,但至少这样我可以完全控制。
基本上我需要:
- 设置游戏窗口
- 在循环中:照常进行所有渲染,然后将结果刷新到屏幕,管理后缓冲区等。
任何人都知道如何做到这一点?事实上,这听起来很简单,但找不到任何有关如何执行此操作的文档。
不确定我做错了什么,但我有以下代码(仅用于测试,计时将以不同方式处理),并且循环将运行一段时间然后停止。一旦我将鼠标指针移到窗口上,循环就会再次运行一段时间。
private void Application_Idle(object pSender, EventArgs pEventArgs)
{
Thread.Sleep(500);
//Message message;
//while (!PeekMessage(out message, IntPtr.Zero, 0, 0, 0))
{
gametime.update();
Update(gametime);
Draw(gametime);
GraphicsDevice.Present();
}
}
如果启用“while PeekMessage”,循环将连续运行,但忽略睡眠,并且当鼠标在窗口上移动时也会停止。不知道这里发生了什么...
我认为最好我只想在主渲染循环中做一些简单的事情:
while (alive)
{
Thread.Sleep(100);
gametime.update();
Update(gametime);
Draw(gametime);
GraphicsDevice.Present();
}
但在这种情况下,窗口保持空白,因为看起来窗口实际上并未使用新内容。我尝试了 form.Refresh(),但仍然不行...有什么想法吗?
I'm trying to figure out how to manage the whole game loop manually in a Windows game, without using the regular Game Microsoft.Xna.Framework.Game class.
The reason for this is using the regular Game class causes some stuttering in my game. Not much, but because of the specific nature of the game it is still quite visible.
After trying a bunch of different settings (vsync, fixedtimestep, various framerates etc.) I decided to try write my own Game class to have full control of the timing. I am not sure that will fix it, but at least this way I have full control.
Basically I need to:
- Set up the game window
- In a loop: Do all rendering as usual, and then flush the result to the screen, manage backbuffers etc.
Anyone knows how to do this? It sounds quite easy in fact, but could not find any documentation on how to do it.
Not sure what I am doing wrong, but I have the following code (just for testing, timing will be handled differently), and the loop will run for a little while then stop. Once I pass my mousepointer over the window the loop will run for a little while again.
private void Application_Idle(object pSender, EventArgs pEventArgs)
{
Thread.Sleep(500);
//Message message;
//while (!PeekMessage(out message, IntPtr.Zero, 0, 0, 0))
{
gametime.update();
Update(gametime);
Draw(gametime);
GraphicsDevice.Present();
}
}
If enabling the "while PeekMessage", the loop will run continuously, but ignoring the sleep and also stopping when the mouse is moving over the window. Not sure what is going on here...
I think optimally I would just want to do something simple like this in the main render loop:
while (alive)
{
Thread.Sleep(100);
gametime.update();
Update(gametime);
Draw(gametime);
GraphicsDevice.Present();
}
But in this case the window remains blank, as it seems the window is not actually being redrawn with the new content. I tried a form.Refresh(), but still no go... Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
(添加了 xbox 信息)
对于 Windows,您基本上需要创建一个表单并显示它,然后存储其句柄和表单本身。
使用这个句柄你可以创建一个GraphicsDevice。
然后,您将 Application.Idle 挂钩到您自己的函数,该函数调用您的更新和渲染。
例如
编辑 1
对于 xbox,您可能只能将自己的自定义运行函数与游戏循环一起放置在受限制的 while true 循环中。在 true 之外运行的内部,您可能必须使用 IntPtr.Zero 作为句柄进行图形设备初始化和验证
EDIT 2
我使用类似的东西(来自 http://www.koonsolo.com/news/dewitters-gameloop/ )
编辑 3
创建内容管理器需要更多工作,但仍然易于管理。您需要创建一个实现 IServiceProvider 的类。该类在其构造函数中采用 GraphicsDevice 来创建实现 IGraphicsDeviceProvider 的下一个类。另外,我像这样实现 GetService
为方便起见,我还向类添加了一个方法来创建和返回管理器
此外,我创建了一个实现 IGraphicsDeviceService 的类并引用我的 GraphicsDevice。然后我在其中创建一个属性和字段,就像这样
所以调用最终会类似于
where
-抱歉,代码碎片化了,但它不是我最近写的,所以我很难记住各个部分。
编辑4
我的自定义游戏有一个奇怪的情况,我只是记得当我为其新表单时我
必须绑定
,
否则我会遇到一些可怕的摊位。
(added xbox information)
for windows you Basically need to create a Form and Show it, then store its handle and the form itself.
Using this handle you can create a GraphicsDevice.
Then you hook Application.Idle to your own function that calls your update and render.
For example
EDIT 1
For xbox you may just be able to place your own custom run function with your game loop in a throttled while true loop. Inside that run outside the top of the while true you will probably have to do the graphics device initialization and verification with IntPtr.Zero as your handle
EDIT 2
i use something like this ( got from http://www.koonsolo.com/news/dewitters-gameloop/ )
EDIT 3
Creating a content manager was a little more work, but still managable. You need to create a class that implements IServiceProvider. This class takes a GraphicsDevice in its constructor in order to create the next class the implements IGraphicsDeviceProvider. in addition I implement GetService like this
For convenience i also add a method to the class to create and return managers
In addition i create a class that implements IGraphicsDeviceService and takes a reference to my GraphicsDevice. then I create a property and field in it like so
So the call ends up being somehting like
where
-Sorry for fragmenting the code around but its not something i wrote too recently so im having difficulty remembering parts.
EDIT 4
i had an odd case with my custom game i just remembered when i new the Form for it i
had to bind
to
otherwise i got some horrible stalls.