仅在C#中的特定时间触发事件

时间:2011-11-23 21:42:34

标签: c# events opentk

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

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

如果事件发生在循环中的某个其他位置,我想等到handleAllEvents()来处理它们。通过"事件"我的意思是标准的C#事件系统,例如:

public event Action<object, KeyboardEventArgs> KeyPressed;

如果问题没有明确表达,请告诉我。谢谢!

3 个答案:

答案 0 :(得分:5)

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

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

然后你必须确保,渲染不会停留那么久。

有关详细信息,建议您学习Application课程,尤其是方法Run()DoEvents()

答案 1 :(得分:1)

我认为在OpenTK中执行此操作的正确方法是从GameWindow类继承,然后覆盖OnUpdateFrameOnRenderFrame。签出中继时包含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.Input命名空间中找到这些内容,特别是KeyboardDevice类。