最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

pvzclass是如何實(shí)現(xiàn)的?pvzclass源代碼初步分析(10)events 組件 上

2021-09-21 22:07 作者:__W1thoutD0ubt  | 我要投稿

在 events 組件加入 pvzclass 之前,pvzclass 對 PVZ?內(nèi)部變化的判定實(shí)際上非常局限。

events 組件擴(kuò)充了 pvzclass 的判定功能,方便不擅長高級代碼的創(chuàng)作者實(shí)現(xiàn)復(fù)雜功能(比如:植物受到傷害時魅惑周圍的僵尸)。

events?組件是如何做到的?本篇可以讓你略知一二。

強(qiáng)烈建議在閱讀本篇前先閱讀第3~5篇的內(nèi)容。

注:本文以2021.8.28更新的版本為準(zhǔn)。?包括第51號合并請求的部分內(nèi)容。

events 組件入門教程

雖然本文理應(yīng)只解讀 events 組件的代碼實(shí)現(xiàn),但考慮到 events 組件多次更新,還是先補(bǔ)一份簡單的說明為好。

若想使用 events 組件的功能,你得先定義一個 EventHandler ,如:

(以上摘自第51號合并請求前的 pvzclass.cpp?)

EventHandler 的構(gòu)造函數(shù)需要一個參數(shù):PVZ 類(如以上例子中的 pvz )。

定義 EventHandler?之后,你就可以通過它的成員函數(shù) RegistryListeners()?注冊函數(shù),告訴這個?EventHandler?在什么類型的事件發(fā)生運(yùn)行什么函數(shù)。

RegistryListeners()?有兩種聲明。第一種聲明通過事件名稱指定事件類型:

(以上摘自 events.h )

另一種聲明在 2021.8.9 更新后加入,通過函數(shù)參數(shù)指定事件類型:

(以上摘自 events.h?)

無論使用何種聲明,注冊的函數(shù)應(yīng)具有如下參數(shù):事件類(可以是任一 Event 類的派生類,但每個函數(shù)只能有一個)和PVZ類。比如如下函數(shù)在“植物死亡"事件發(fā)生后執(zhí)行:

(以上摘自第51號合并請求前的 pvzclass.cpp?)

最后一個參數(shù) Level 表示函數(shù)執(zhí)行的優(yōu)先級,這里暫不詳細(xì)講述。

注冊完所有函數(shù)之后,你就可以調(diào)用成員函數(shù) Run() ,讓?EventHandler?開始干活。

但是調(diào)用一次 Run()?只能讓?EventHandler?運(yùn)行一次。所以你需要反復(fù)調(diào)用 Run() 。

另外,EventHandler?通過高頻比較 PVZ 本體的內(nèi)存變化實(shí)現(xiàn)它的功能,所以你調(diào)用 Run()?的頻率應(yīng)當(dāng)足夠高。

示例代碼干脆直接循環(huán)調(diào)用 Run() :

(以上摘自第51號合并請求前的?pvzclass.cpp?)

講了這么多,終于可以進(jìn)入本文的正題了:分析Events組件。

events.h

events.h 聲明并定義了 events?組件的大部分內(nèi)容,而組件中其他文件完成聲明的具體定義。

開頭的類型定義有一條需要注意:


這里定義的正是你通過?RegistryListeners() 注冊的函數(shù)。

除此之外,events.h?定義了兩個類:記錄事件類型和詳細(xì)信息的 Event?類(及其派生類),以及完成 events?組件功能的?EventHandler?類。

Event類的定義非常簡單:

CancleState?屬性的作用會在下面講到。

name(注意是全小寫)用來區(qū)分不同的派生類,其賦值在派生類的構(gòu)造函數(shù)中完成。

以其中一個派生類為例:

“植物受傷”事件

在 2021.8.9 更新前,構(gòu)造函數(shù)直接將字符串常量賦值給 name。但現(xiàn)在字符串常量都放到了 events.cpp?中,通過派生類的 Name?屬性間接賦值。

除了 Name?屬性,大部分派生類都會額外定義一些變量,用來記錄事件涉及的對象。

比如,EventPlantDamage?額外定義了 plant?和?zombie ,用于追蹤受傷的植物及其周圍的僵尸(事件可能會有多個,分別追蹤該植物周圍的每個僵尸)。

目前 events?組件支持的所有事件可以在 events.cpp?中?通過字符串常量間接查詢:

截至2021.8.28更新

EventHandler?類部件較多。

private?部分如下圖,包括供成員函數(shù)使用的 PVZ 類指針 pvz 、生成單位列表的三個 GetAll()?函數(shù)、上次?EventHandler?更新后場上的對象列表 …List 、已注冊函數(shù)的列表listeners... 、基址 Address 、兩個作用不大的變量,

以及成員函數(shù) InvokeEvent() (事件產(chǎn)生,觸發(fā)注冊的函數(shù))、Update() (EventHandler?的主函數(shù),檢測事件是否產(chǎn)生并更新對象列表)及其分支。

public?部分包括它的構(gòu)造函數(shù)、析構(gòu)函數(shù),和成員函數(shù) Run() 、?RegistryListeners() 。

上面提到,RegistryListeners()?有兩種聲明,但實(shí)際上第二種聲明(如下圖)……

第一種聲明的套皮罷了

同時需要注意,這里注冊函數(shù)可以對一整類事件生效,無論你使用哪種聲明的 RegistryListeners()。

如果你對可能涉及到的對象有其他額外要求(比如只對氣球僵尸有效),你需要在將被注冊的函數(shù)中自行添加用于判定的代碼。EventHandler 可不在乎這些。

events.cpp

除去上文提到的字符串常量,events.cpp?還包括 InvokeEvent()?和 RegistryListeners()?兩個成員函數(shù)的定義。

RegistryListeners()?根據(jù)優(yōu)先級將函數(shù)放到不同的 listeners?動態(tài)數(shù)組中:

InvokeEvent()?則負(fù)責(zé)根據(jù)觸發(fā)的事件運(yùn)行已經(jīng)注冊好的函數(shù)。

可以看出,對于注冊時優(yōu)先級相同的函數(shù),先注冊的函數(shù)有更高優(yōu)先級。

這里可以看出 event?的屬性 CancleState?的作用:若 CancleState 為 true,則注冊的函數(shù)在執(zhí)行完畢后立刻返回,不再執(zhí)行優(yōu)先級更低的函數(shù)。

isDelete?表明這次事件觸發(fā)完成后是否會將這個事件釋放,避免內(nèi)存泄漏。

雖然這個參數(shù)存在,但實(shí)際上這個參數(shù)的值(至少 events 組件自身的調(diào)用如此)都是 true 。

不過,如果 InvokeEvent 因?yàn)槭录?CancleState 為真而返回,isDelete 就無法發(fā)揮作用

這個漏洞的修復(fù)恐怕要等到第53號合并請求了。

分析完了events(.h/.cpp),接下來先分析最簡單的 LevelEvent.cpp。

LevelEvent.cpp

這份文件包括一個變量 wave,用于存儲當(dāng)前波數(shù),以及之前提到過的函數(shù)?UpdateLevels() 。

這個函數(shù)檢測關(guān)卡類事件是否發(fā)生。

關(guān)卡類事件可以分為兩類:切換類(進(jìn)入關(guān)卡、重開、退出關(guān)卡)和進(jìn)行類(關(guān)卡開始,一波僵尸刷新)。

以下是切換類事件相關(guān)的代碼:

其實(shí)原理很簡單:在關(guān)卡內(nèi),BaseAddress?必定非0,否則 BaseAddress?一定為0。關(guān)卡重開時會將 BaseAddress?換為一個新的值。

不過重開事件(即 EventLevelRestart)是2021.8.26更新后才加上的,它是否能正確觸發(fā)我也不大確定(因?yàn)樯衔乃f的更換?BaseAddress?可能先將其設(shè)定為0),可能還藏著一個漏洞。

重開事件和進(jìn)入關(guān)卡事件的觸發(fā)后面,都接著一段刷新對象列表的代碼,這是為了防止讀檔時存檔記錄的對象觸發(fā)各自的“生成”事件(這一事件顯然理應(yīng)已觸發(fā)過)。

進(jìn)行類事件相關(guān)的代碼如下:

原理也很好理解,簡單分析通過 PVZ?類讀取的數(shù)值,確定事件是否發(fā)生,并調(diào)整相關(guān)變量。

這么一看,其實(shí)重開事件觸發(fā)的代碼寫得很倉促,有兩個變量沒有處理。這種瑕疵還是挺不應(yīng)該的。

本篇分析的,大部分是 events 組件的外部框架。

下一篇就要分析 events?組件的內(nèi)核了。

實(shí)際上,events?組件的內(nèi)核不很精致,甚至可以說很粗陋。

詳細(xì)展開,就要等到下篇了。

pvzclass是如何實(shí)現(xiàn)的?pvzclass源代碼初步分析(10)events 組件 上的評論 (共 條)

分享到微博請遵守國家法律
台北市| 军事| 原阳县| 普兰店市| 项城市| 台前县| 建阳市| 汤阴县| 宜兴市| 金寨县| 聊城市| 法库县| 杨浦区| 通化市| 黄浦区| 磐石市| 莒南县| 无极县| 临城县| 塔城市| 鹤庆县| 嘉兴市| 威海市| 秦安县| 宁国市| 榆树市| 齐齐哈尔市| 台江县| 浮山县| 桑日县| 巴彦县| 子长县| 河西区| 涪陵区| 同仁县| 新安县| 中江县| 林芝县| 囊谦县| 鄱阳县| 富平县|