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

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

pvzclass是如何實現(xiàn)的?pvzclass源代碼初步分析(5)Plant類 & Zombie類

2021-07-10 00:12 作者:__W1thoutD0ubt  | 我要投稿

PVZ類的成員類,除了Memory類外都大同小異。

它們都有自己的構(gòu)造函數(shù),使用指針,通過基址+偏移的方法實現(xiàn)修改PVZ對象的功能。

本篇以Plant類和Zombie類為例,解讀pvzclass如何實現(xiàn)除Memory類外的成員類。

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

雖然有定義成員類的代碼,但是PVZ類下并沒有定義類型為成員類的變量。以Plant類為例:

Plant類代碼的結(jié)尾部分

同時可以看到,pvzclass中,返回值為成員類的方法,返回的都是指針。

再加上幾乎每個成員類都有構(gòu)造函數(shù),實例化成員類時,建議使用指針和new。

Plant類

Plant類包括的內(nèi)容,自然是修改PVZ中植物的屬性用的。

Plant類的內(nèi)容可以分為三部分:基址和構(gòu)造函數(shù)、對象屬性、方法。

(以下展示的代碼不包括原代碼中的注釋部分)

基址和構(gòu)造函數(shù)?部分

BaseAddress變量存儲的,是Plant對象對應(yīng)的植物對象在PVZ本體中的內(nèi)存基址。它的賦值由構(gòu)造函數(shù)完成:

在Classes文件夾下的"Plant.cpp"中

構(gòu)造函數(shù)的參數(shù)是"indexoraddress",即"index"或"address"。其中"index"指的是植物對象的序號,不會大于1024;而"address"則是上文提到的,植物對象所在的內(nèi)存基址,必然大于1024。這種數(shù)值分布是PVZ內(nèi)部決定的。

pvzclass可以依照這條特性確認(rèn)參數(shù)是"index"還是"address",最終確認(rèn)基址并完成初始化。

DebugType的初始化涉及Plant類的屬性,接下來講。

對象屬性?部分
另一部分屬性

對象屬性部分的代碼幾乎完全使用INT_PROPERTY宏和T_PROPERTY宏實現(xiàn)。

這些成員變量可以像常規(guī)變量一樣調(diào)用和賦值,并且因為宏定義的調(diào)節(jié),可以直接反映到PVZ本體的對應(yīng)變量上。

使用INT_PROPERTY宏定義的變量,其名稱為第一個"參數(shù)";使用T_PROPERTY宏定義的變量,其名稱為第二個"參數(shù)"。

比如,如果你要將某一植物的生命值(即"Hp")改為23333,你的代碼應(yīng)當(dāng)為:

如果你沒能從變量名中推測出變量的作用,可以打開MemoryAddressList,利用變量對應(yīng)的偏移量(就是最后一個參數(shù)),在植物對象的成員變量中找到對應(yīng)的變量。

方法?部分
方法?部分

使用這些方法可以對植物進(jìn)行一些操作。

方法的具體定義在Classes文件夾下的"Plant.cpp"中。

GetAnimationPart1()和GetAnimationPart2()可以獲取植物對象的動畫部件。它們的實現(xiàn)非常簡單:

說白了,就是套皮ReadMemory

Light()和Flash()的實現(xiàn)也很簡單:

套皮WriteMemory

查詢MemoryAddressList可知,0xB8和0xBC對應(yīng)的變量分別是發(fā)光倒計時和閃光倒計時。

這兩個方法的原理也很簡單,就是通過修改倒計時實現(xiàn)相應(yīng)效果。

剩下的四個方法都使用了注入?yún)R編代碼的方式實現(xiàn)功能。它們直接調(diào)用PVZ內(nèi)部的函數(shù),以實現(xiàn)一般情況下難以通過修改(或讀?。┥贁?shù)變量實現(xiàn)的功能。

CreateEffect()
SetStatic()

在第3篇中已經(jīng)講過,SETARG宏用于修改byte數(shù)組(也就是待注入的匯編碼)中的部分內(nèi)容,這里用于調(diào)整指令用的參數(shù)。

這些匯編代碼的聲明在AsmFuntions.h,定義則在AsmFunctions.cpp中。

Shoot()的架構(gòu)基本一致,不過因為自身的功能(即立刻令植物發(fā)射子彈),代碼上有一些不同:

Shoot()的代碼

在PVZ中,香蒲的子彈可以跟蹤攻擊場上的僵尸。Shoot命令的targetid參數(shù)可以為生成的子彈指定僵尸作為攻擊目標(biāo),并完成其他屬性的設(shè)置。

容易看出,代碼的前半段是生成子彈,后半段是設(shè)置子彈的跟蹤情況。

這里出現(xiàn)了第4篇中提到過的Memory::Variable,它在這里的作用是暫時存儲子彈的基址,這個基址最終會被Execute()函數(shù)抓取。

因為注意:對楊桃使用Shoot()方法時,pvzclass不會抓取基址,而是直接留空。

這里牽扯到了一些子彈的屬性,這個后面會講。

還剩下一個SetAnimation(),它的代碼是這樣的:

其中的lstrcpyA()可以視為一種特殊的strcpy()。

看上去和前面幾個都不一樣。

然而,我們把Execute()的代碼拿出來,比對一下:

幾乎完全一致

為什么SetAnimation()沒有使用Execute()?

我們看一眼匯編碼部分,它長這樣:

這一部分相當(dāng)于如下的代碼:

SetAnimation()中有一個動態(tài)設(shè)置的參數(shù),這一參數(shù)根據(jù)申請的內(nèi)存地址進(jìn)行確定,但PUSHDWORD宏的參數(shù)是絕對引用的。
因此SetAnimation()不得不采取改寫Execute()的方法。

如果使用pvzclass寫匯編代碼,需要動態(tài)為與申請的內(nèi)存地址相關(guān)的變量賦值,可以考慮用類似的方法來實現(xiàn)。

Zombie類

Zombie類包括的內(nèi)容用于修改PVZ中僵尸的屬性。

類似地,Zombie類的內(nèi)容可以分為三部分:基址和構(gòu)造函數(shù)、對象屬性、方法。

基址和構(gòu)造函數(shù) 部分
構(gòu)造函數(shù)的實現(xiàn)(在Classes文件夾的Zombie.cpp中)

這一部分和Plant類基本一樣,跳過。

屬性方面,除了Index(僵尸對象序列的基址)意外,依然是用T_PROPERTY宏及其變種定義成員變量。

同樣地,你可以打開MemoryAddressList,利用變量對應(yīng)的偏移量在僵尸對象的成員變量中找到對應(yīng)的變量,以確認(rèn)變量對應(yīng)的僵尸屬性。

方法方面,Zombie類包含的方法更多,但原理也就那么幾類:

套皮WriteMemory
套皮ReadMemory
涉及CollisionBox的Memory類讀寫操作
涉及護(hù)甲類的Memory類讀寫操作(代碼未截全)

這里出現(xiàn)的CollisionBox(碰撞箱)、AccessoriesType1(I類護(hù)甲)和AccessoriesType2(II類護(hù)甲)三種結(jié)構(gòu)體,都是在PVZ類之外定義的。定義它們的代碼在PVZ.h開頭的部分。

代碼注入
類Execute()的代碼注入

Zombie::SetAnimation()和Plant::SetAnimation()相似,都是用類似Execute()的代碼完成自身的功能。

各位創(chuàng)作者想要實現(xiàn)類似的功能時,也可以模仿上面的代碼,自己編寫出同類型功能的代碼。

下一篇將解讀PVZ類直屬的成員變量和直屬方法。

陽光數(shù)、出怪倒計時等場景性的屬性,大部分由直屬的成員變量進(jìn)行調(diào)控。

實例化PVZ類成員類的方法,大都是直屬方法。

都是地位比較高的內(nèi)容。

敬請期待。

pvzclass是如何實現(xiàn)的?pvzclass源代碼初步分析(5)Plant類 & Zombie類的評論 (共 條)

分享到微博請遵守國家法律
松阳县| 临汾市| 吉安市| 罗定市| 东宁县| 鄯善县| 平顺县| 盈江县| 镶黄旗| 贡觉县| 莎车县| 浏阳市| 青海省| 延庆县| 五大连池市| 始兴县| 疏附县| 天津市| 锦州市| 邯郸县| 时尚| 郑州市| 安龙县| 惠来县| 芜湖县| 天峨县| 达拉特旗| 邵武市| 沛县| 桃园市| 平阳县| 额尔古纳市| 和政县| 林州市| 台东市| 洛川县| 静宁县| 二手房| 烟台市| 包头市| 兴义市|