遊戲訊息處理

2021-04-13 01:13:10 字數 3969 閱讀 1914

事件機制在很多高階程式語言中都有支援。譬如vb、c#(delegate)、c++builder(並不屬於c++的範疇。c++builder中的事件處理器必須用關鍵字closure《閉包》修飾)等等,甚至在html中也可以見到它的身影。事件機制的引入使軟體系統變得更加易於理解——它使一種語言(平台)更加接近於這個世界的真相。事情的發展變得像現實世界中那樣順理成章。某一事件的產生引發了一系列其他事件的產生,這些事件要麼是結果要麼又會引發一系列事件的產生……如此這般,資訊才得以在事件的新陳代謝中延續,世界才得以向前發展。在某些遊戲設計過程中的一項重要任務就是模擬現實世界的某些特徵,以期實現機器與使用者的更加親密的溝通。事件機制就是很好的一例。我們需要事件來使我們的系統更加人性化。

我想,在我繼續進行下面對討論之前,先簡單介紹一下「事件」這個東東。

1. 遊戲中的事件機制

聯絡是普遍存在的。事事有聯絡、時時有聯絡,整個世界是乙個相互聯絡的統一整體。乙個人的行為、物的狀態的改變或事的進展過程的某一階段可以引發乙個事件。乙個事件的發生或許會引發另外的事件——通過人的感知、大腦的反映,然後作出決策,付諸行動——也或許,就這麼蒸發掉,無人知曉。但無論如何,在這一過程中,我們總能抽象出一些實質性的東西來。就像下面的圖示:

在遊戲中:

事件源——表示任何可以引發事件的物件。譬如,乙個「人」、「坦克」、「建築物」、「地面」。

事件——表示任何可以處理的事件。譬如,「感冒」、「射擊」、「倒塌」、「有物件經過」。

響應者——表示任何對某事件感興趣的物件。

響應器——表示對某事件感興趣的物件對某一確定事件作出的反應。

特別的,對於過程:

通知——發生在事件與響應者之間。我們把它分為兩種方式:

有限聽眾式、

廣播式。對事件感興趣的物件(響應者)只有確定的有限個(只有乙個的情況下,可以叫做

點對點式)的情況就是有限聽眾式。而對於廣播式,事件並不知道會有哪些(個)物件對自己感興趣。它向所有可以接收事件通知的物件廣播事件。

觸發——響應者發現自己對特定事件需要做出相應的行動時就會觸發

事件處理器,並同時傳遞需要的事件資訊給它。對於響應者,它也可以選擇沉默——自己了解事件但並不作出行動。因此這個過程的決定權在響應者手上。

2. 萬事之鼻祖 event

我們需要乙個類來表示所有事件的普遍性質。

public class

event

// 獲取或設定事件的名稱

public string

message

// 獲取或設定事件的簡單描述

eventtypes eventtype

// 獲取或設定事件型別(列舉eventtypes)

listenercollection listeners

// 獲取響應者的集合

public bool

poolevent

// 獲取或設定事件的簡單描述

// 方法

void

raiseevent();

// 通知響應者事件的發生

void

abandonlistener( int index );

// 拋棄乙個事件響應者,並把它從 listeners 中移除。

void

abandonlistener();

// 拋棄所有的事件響應者

}3. 列舉型別 eventtypes

這個列舉型別指示事件通知過程的型別:有限聽眾式、廣播式。

public enum

eventtypes

4. 響應者介面 ilistener

該介面只有唯一的方法 eventarrived() 。事件發生時會呼叫這個方法並傳遞相關引數。這個引數必須是 eventargs 或由它派生而來。

public inte***ce

ilistener

5. eventpool

乙個事件池。當且僅當需要事件廣播時我們才需要它。需要注意的是 addevent 方法。它把乙個事件新增到池中,第二個引數指定是否將該事件已經指定的響應者亦新增到廣播的響應者中。事件新增後,其 event::eventtype 屬性會被設定為 eventtypes.broadcast。

public class

eventpool

// 獲取池中所有的事件的集合

public listnercollectionlistners

// 獲取池中所有的響應者的集合

// 方法

void

addevent( event obj ,bool copylistners );

// 新增乙個事件並把它作為廣播式事件

void

removeeventat( int index );

// 將乙個事件從列表中移除

void

removeevent( event listener );

// 將乙個事件從列表中移除

void

broadcast( event event );

// 向列表中的所有響應者廣播指定事件(可以是非池中的事件)

void

broadcastitemat( int index );

// 向列表中的所有響應者廣播池中的指定事件

}6. eventargs

public class

eventargs

// 獲取傳遞這個引數的事件

public

object sender

// 獲取事件源

8. 響應者行為

響應者實現 ilistener 介面後就可以響應事件了。在 eventarrived() 方法中,你可以直接處理事件,抑或是呼叫其它的事件處理器(響應器)。c#中有很好的解決方案——委託——替代函式指標的最有效的方法。在c++中也可以用虛函式表來模擬委託機制。總之,在響應器上的解決方案是很靈活的。在實際開發中,可以根據不同的環境做出不同的選擇。

9. 擴充套件機制

在乙個遊戲中,除了已經定義好的事件外,其劇情或功能可能會要求玩家自行定義一些事件。這就需要一種可擴充套件的方案。我們引入了 customevent 類——繼承自 event,以及 condition 類。

public class

customevent : event

public condition testcondition }

condition _condition = null;

}public abstract class

condition

bool abstract test();

} 初始化乙個 customevent 類時必須同時傳入乙個 condition 類。condition 類必須被繼承。test()方法在適當的時候被呼叫以檢測是否可以引發這個事件。

10. 後記

以上談到的只是乙個簡單的模型,是否實用還要等待實踐的檢驗。歡迎讀者的批評與建議。

遊戲內訊息處理

傳送訊息有4種渠道 1.io 2.bus 3.stage 4.public 前面已經講過了關於easymanager的初始化。public class easymanager implements private string scanpackage private mapresolvers new...

第七章 Windows 遊戲輸入訊息處理

虛擬鍵碼與鍵盤訊息 在windows中,所有鍵盤的按鍵都被定義為一組通用的 虛擬鍵碼 也就是說在windows系統下所有按鍵都會被視為虛擬鍵 包括滑鼠鍵在內 而每乙個虛擬鍵都有其對應的乙個虛擬鍵碼。windows系統是乙個訊息驅動的環境,一旦我們在鍵盤上進行輸入操作,那麼系統便會接收其對應的鍵盤訊息...

訊息和訊息處理之訊息迴圈

在win32程式設計中,訊息迴圈是相當重要的乙個概念,看似很難,但使用起來卻是非常簡單。在winmain函式的最後,有下列 while getmessage msg,null,0,0 windows應用程式可以接收以各種形式輸入的資訊,這包括鍵盤 滑鼠動作 計時器產生的訊息,也可以是其他應用程式發來...