我正在用C#编写视频游戏,我想仅在游戏循环的特定点处理某些事件(例如键盘/鼠标事件)。例如,有没有办法写出如下内容:
void gameLoop()
{
// do updates
handleAllEvents();
render();
}
如果事件发生在循环中的某个其他位置,我想等到handleAllEvents()
来处理它们。通过"事件"我的意思是标准的C#事件系统,例如:
public event Action<object, KeyboardEventArgs> KeyPressed;
如果问题没有明确表达,请告诉我。谢谢!
答案 0 :(得分:5)
删除对Application.Run()
的调用,并建立自己的消息循环。例如:
void GameLoop()
{
while (!exitSignal)
{
Application.DoEvents();
render();
}
}
然后你必须确保,渲染不会停留那么久。
有关详细信息,建议您学习Application
课程,尤其是方法Run()
和DoEvents()
。
答案 1 :(得分:1)
我认为在OpenTK中执行此操作的正确方法是从GameWindow
类继承,然后覆盖OnUpdateFrame
和OnRenderFrame
。签出中继时包含QuickStart解决方案,请检查Game.cs
文件。
[编辑] 为了进一步说明,OpenTK.GameWindow
类提供Keyboard
属性(类型为OpenTK.Input.KeyboardDevice),应该在OnUpdateFrame
内阅读}。不需要单独处理键盘事件,因为这已经由基类处理。
/// <summary>
/// Called when it is time to setup the next frame. Add you game logic here.
/// </summary>
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
TimeSlice();
// handle keyboard here
if (Keyboard[Key.Escape])
{
// escape key was pressed
Exit();
}
}
此外,有关更详细的示例,请从其网页下载Yet another starter kit。这个类应该是这样的:
// Note: Taken from http://www.opentk.com
// Yet Another Starter Kit by Hortus Longus
// (http://www.opentk.com/project/Yask)
partial class Game : GameWindow
{
/// <summary>Init stuff.</summary>
public Game()
: base(800, 600, OpenTK.Graphics.GraphicsMode.Default, "My Game")
{ VSync = VSyncMode.On; }
/// <summary>Load resources here.</summary>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// load stuff
}
/// <summary>Called when your window is resized.
/// Set your viewport/projection matrix here.
/// </summary>
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
// do resize stuff
}
/// <summary>
/// Called when it is time to setup the next frame. Add you game logic here.
/// </summary>
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
TimeSlice();
// handle keyboard here
}
/// <summary>
/// Called when it is time to render the next frame. Add your rendering code here.
/// </summary>
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
// do your rendering here
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (Game game = new Game())
{
game.Run(30.0);
}
}
}
我建议您下载Yask并检查它是如何在那里实施的。
答案 2 :(得分:1)
如果您正在使用游戏循环,通常不会处理事件,您可以在需要时轮询输入设备(即在handleAllEvents()
方法中)。一些快速研究告诉我,在opentk中,您可以在OpenTK.Input
命名空间中找到这些内容,特别是KeyboardDevice
类。