2011-11-23 68 views
2

我正在用C#編寫視頻遊戲,並且我想僅在我的遊戲循環中的特定點處理某些事件(例如鍵盤/鼠標事件)。例如,是否有寫類似以下的方式:如果在迴路中的其他一些點發生的事件只在C#中的特定時間觸發事件#

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

,我想等到handleAllEvents()來處理它們。通過「活動」我的意思是標準的C#事件的系統,例如:

public event Action<object, KeyboardEventArgs> KeyPressed; 

請讓我知道,如果問題不是很清楚。謝謝!

+2

是不是一個事件的整個點,你不同步處理它,即當達到特定的代碼行?如果你的「事件」不是真正的「事件」,或許你應該探索一種不同的設計策略。另外,反應式擴展是處理事件的真正強大的框架 - http://msdn.microsoft.com/zh-cn/data/gg577609。一探究竟。 –

+0

作爲發佈事件答案的替代方案,請參閱[mine](http://stackoverflow.com/q/8249664/593627)瞭解遊戲中更常用的方法(輪詢)。 –

+0

@ Sean:遊戲循環是遊戲編程中很常見的模式。它不一定需要用這種方式來實現,但重點是在渲染每一幀之前完全處理輸入和遊戲邏輯。隨機發生事件的可能性大大增加了遊戲設計的複雜性。 – Groo

回答

5

刪除對Application.Run()的呼叫,並建立自己的消息循環。例如像這樣:

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

然後你必須確保渲染不會停留那麼久。

欲瞭解更多信息,我建議你學習Application類,特別是方法Run()DoEvents()

+0

這是一個很好的方式來做到這一點,但我認爲沒有理由重塑。 'OpenTK.GameWindow'類已經處理了這個和其他的東西,如vsyncing,時間分割,雙緩衝等等。你可以檢查它的源代碼[here](http://www.opentk.com/files/doc/_game_window_8cs_source.html )看到它所做的所有事情。 – Groo

+0

我已經在使用GameWindow了。我想我的問題是,我不在乎什麼時候發生某些事件(例如操作系統事件),以及我做的其他事件(例如,如果我可以等待處理按鍵直到完成每次按鍵操作,幀初始化)。這聽起來合理嗎?還是我應該考慮以其他方式來構建我的程序? – fyhuang

1

我相信在OpenTK中做到這一點的正確方法是繼承GameWindow類,然後覆蓋OnUpdateFrameOnRenderFrame。當您結帳時,包含QuickStart解決方案,請檢查Game.cs文件。

[編輯]爲了進一步闡明,OpenTK.GameWindow類提供一個Keyboard屬性,它應內部OnUpdateFrame被讀取(類型OpenTK.Input.KeyboardDevice的)。不需要單獨處理鍵盤事件,因爲這已經由基類處理過了。

/// <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,並檢查它是如何實現的存在。

+0

雖然這並不能告訴他如何處理輸入,這是他所要求的。 –

+0

@George:我已經更新了答案。 – Groo

+0

+1。很好的答案。 –

1

如果您使用的是遊戲循環,則通常不會處理事件,您需要時會輪詢輸入設備(即在您的handleAllEvents()方法中)。一些快速研究告訴我,在中,你可以在OpenTK.Input命名空間中找到這個東西,特別是KeyboardDevice類。

+0

感謝您的建議!儘管如此,處理某些輸入作爲「事件」不是更容易 - 例如,處理文本輸入的按鍵?我可以理解對「連續」輸入的輪詢(如右鍵向右移動字符),但如果我遇到類似事件的模型似乎更合適的情況呢? – fyhuang

+0

如果你想要處理輸入文本,那麼是的,如果你想處理比較典型的遊戲(移動角色),那麼事件模型更好,然後通過輪詢來完成。 –