我目前正在使用OpenTK Framework和OpenGL在C#中编写Jump n'Run游戏。
Open TK提供预设功能,例如GameWindow.Run();
或GameWindow.onUpdateFrame();
onRenderFrame();
据我所知,绘制OpenGL元素或基元的所有动作都应该属于onRenderFrame,而玩家移动等游戏事件应该在onUpdateFrame中执行,因此可以在渲染新帧之前预先计算这些动作。
我是对的吗?在onRenderFrame方法中执行所有操作会有所不同吗? OpenTK建议不要覆盖这些方法并订阅他们的事件(onRenderFrameEvent)。
什么是订阅以及如何订阅事件而不是覆盖某个方法?
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
this.gameObjects.moveObjects();
this.player.Move();
if (this.player.jumpstate == true) this.player.Jump();
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref modelview);
GL.LoadIdentity();
GL.Translate(0.0f, 0.0f, -3.5f);
this.gameObjects.drawObjects();
this.player.Draw();
SwapBuffers();
}
答案 0 :(得分:5)
与评论相似:在UpdateFrame
事件中更新您的世界并在RenderFrame
中呈现。
当你意识到你的游戏将在完全不同的硬件上运行时,这是有道理的。有些计算机可能只能以15fps渲染你的游戏。其他人将达到稳固的60fps。拥有120Hz显示器的玩家希望您的游戏以120fps的速度运行,以充分发挥其系统的潜力。
在所有这些情况下,您希望您的游戏逻辑以相同的速度运行并提供相同的结果。
实现此目标的最简单方法是在UpdateFrame
中设置固定的GameWindow.Run()
费率:
using (var game = new GameWindow())
{
game.VSync = VSyncMode.Adaptive;
game.Run(60.0, 0.0);
}
此代码段指示OpenTK每秒引发60 UpdateFrame
个事件以及系统可以处理的RenderFrame
个事件,直至监视器的刷新率。在较慢的系统上运行时,OpenTK将丢弃RenderFrame
个事件,以确保每秒发生稳定的60 UpdateFrame
个事件。这通常被称为"固定的时间步长"。
请参阅Fix Your Timestep!了解为什么这是可取的。
请参阅Quake 3了解为什么不在RenderFrame
事件中执行世界更新的原因(简短版本:在Quake 3中,高fps的数字不准确性允许玩家跳转更高并获得竞争优势。)
修改:对于问题的第二部分,请参阅understanding C# events。例如:
using (var game = new GameWindow())
{
game.RenderFrame += (sender, e) =>
{
GL.Clear(ClearBufferMask.ColorBufferBit);
game.SwapBuffers();
};
}
与继承GameWindow.RenderFrame
并重载GameWindow
方法相比,订阅OnRenderFrame
没有固有的优势。选择适合您的代码结构的方法。