2

我正在用 C# 编写视频游戏,我想只在游戏循环中的特定点处理某些事件(例如键盘/鼠标事件)。例如,有没有办法编写如下内容:

void gameLoop()
{
    // do updates
    handleAllEvents();
    render();
}

如果事件发生在循环中的其他点,我想等到handleAllEvents()处理它们。“事件”是指标准 C# 事件系统,例如:

public event Action<object, KeyboardEventArgs> KeyPressed;

如果问题表述不清楚,请告诉我。谢谢!

4

3 回答 3

5

删除对 的调用Application.Run(),并建立您自己的消息循环。例如像这样:

void GameLoop()
{
      while (!exitSignal)
      {
          Application.DoEvents();
          render();
      }
}

然后,您必须确保渲染不会在那里停留这么长时间。

有关更多信息,我建议您学习该Application课程,尤其是方法Run()DoEvents().

于 2011-11-23T21:55:21.897 回答
1

我相信在OpenTK中做到这一点的正确方法是从GameWindow类继承,然后覆盖OnUpdateFrameand OnRenderFrame。结帐时包含一个快速入门解决方案,检查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();
    }
}

此外,对于更详细的示例,请从他们的网页下载另一个入门工具包。该类应如下所示:

// 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并检查它是如何在那里实现的。

于 2011-11-23T22:00:53.143 回答
1

如果您使用的是游戏循环,您通常不会处理事件,您会在需要时轮询输入设备(即在您的handleAllEvents()方法中)。一些快速研究告诉我,在中,您可以在命名空间中找到这些东西,OpenTK.Input尤其是在KeyboardDevice类中。

于 2011-11-23T22:01:33.787 回答