C語言手寫-植物大戰(zhàn)僵尸

項目效果(主頁置頂視頻)
說明:因為完整動圖提交后提示違規(guī),所以這里僅截圖示意。如果需要演示視頻,在評論中回復即可。

項目準備
安裝Visual Studio的任意版本(推薦VS2019社區(qū)版、VS2022社區(qū)版)
安裝easyx圖形庫(官網(wǎng)下載地址)
領取項目素材(回復“植物大戰(zhàn)僵尸”,即可領?。?/p>
創(chuàng)建項目
使用VS創(chuàng)建項目,使用空項目模板:

導入素材:在項目目錄下,創(chuàng)建res文件夾,把解壓后的素材拷貝到res目錄下。



實現(xiàn)游戲初始場景
代碼如下(需要逐行代碼視頻講解,可回復“代碼講解“)。






添加啟動菜單
創(chuàng)建菜單界面,代碼如下:

在main函數(shù)中調(diào)用菜單,代碼如下:

生產(chǎn)陽光
熟悉植物大戰(zhàn)僵尸的同學都知道,種植植物才能消滅僵尸,但是種植植物,需要先具備一定數(shù)量的陽光值。初始的陽光值很小。有兩種方式生成陽光:第一種,隨機降落少量的陽光;第二種,通過種植向日葵,讓向日葵自動生產(chǎn)陽光。我們先實現(xiàn)第一種方式。
定義一個結構體,來表示陽光球。因為陽光是以旋轉的方式運動的,所以定義一個圖片幀數(shù)組,通過循環(huán)播放圖片幀來實現(xiàn)旋轉效果。

在gameInit函數(shù)中,初始化陽光幀數(shù)組。

創(chuàng)建陽光,代碼如下。

修改陽光的位置和幀序號,代碼如下。

在updateGame函數(shù)中調(diào)用以上兩個函數(shù) ,以創(chuàng)建陽光并更新陽光的狀態(tài)。

在updateWindow函數(shù)中,渲染陽光。

收集陽光
當“陽光球”出現(xiàn)的時候,用戶點擊陽光球,就可以“收集”這個陽光,當前總的陽光值就會增加25點。在原版的植物大戰(zhàn)僵尸游戲中,陽光球被收集后,會慢慢移動到頂部的“工具欄”的左側。這個陽光球的“移動過程”,我們后續(xù)再實現(xiàn)。
定義一個全局變量,表示當前總的陽光值。
int sunshine;
在初始化gameInit中,設置一個初始值。
sunshine = 150;
創(chuàng)建收集陽光的函數(shù),如下:

在用戶點擊處理中,調(diào)用收集陽光的函數(shù)。

顯示當前總的陽光值
在gameInit初始化中,設置字體。

在updateWindow中繪制陽光值。

創(chuàng)建僵尸
創(chuàng)建僵尸的數(shù)據(jù)模型。這里一共創(chuàng)建了10個僵尸,這10個僵尸全部被消滅后,這個關卡就勝利了。

僵尸數(shù)組,以及僵尸序列幀圖片數(shù)組,在gameInit函數(shù)中進行初始化,如下。(注意:把僵尸的素材圖片保存到src/zm目錄下。)

創(chuàng)建僵尸,代碼如下:

更新僵尸的數(shù)據(jù)(僵尸的圖片幀序號、僵尸的位置),代碼如下:

在updateGame函數(shù)中,創(chuàng)建僵尸并更新僵尸數(shù)據(jù),如下:

創(chuàng)建繪制僵尸的接口, 如下:

在updateWindow函數(shù)中,繪制僵尸,如下:

實現(xiàn)陽光球的飛躍
現(xiàn)在的實現(xiàn)效果是,陽光被點擊后,陽光球直接消失了!而原版的植物大戰(zhàn)僵尸中,陽光被點擊后,陽光會自動飛向左上角的位置,飛到終點后,陽光值才增加25點。我們的實現(xiàn)方式是,陽光球每次飛躍4個點,直到飛到終點,如下圖:

給陽光的結構體添加兩個成員,表示飛躍過程中的偏移量:

在陽光被創(chuàng)建時,把變異量設置為0, 如下:

陽光被點擊后,馬上修改陽光球的xoff和yoff:

在陽光飛躍過程中更新陽光的位置,如下:(注意是在飛躍過程中,不斷計算偏移量,效果更好。)

刪除原來被點擊后,立即更新陽光值的代碼。

修改渲染陽光的判斷條件,如下:

此時已經(jīng)能夠實現(xiàn)陽光的飛躍了,但是飛躍動作太慢了,后期我們再優(yōu)化。
發(fā)射豌豆
僵尸靠近時,已經(jīng)種植的植物豌豆就會自動發(fā)射“子彈”,我們先為子彈定義數(shù)據(jù)類型,如下:

在gameInit函數(shù)中,初始化“豌豆子彈池”和子彈的圖片,如下:

在僵尸結構體中,添加成員row, 表示該僵尸所在的“行”,方便后續(xù)的判斷。也可以不加,直接根據(jù)僵尸的y坐標來計算。

在createZM函數(shù)中,創(chuàng)建僵尸的時候,設置row成員的值,如下:

創(chuàng)建shoot函數(shù),實現(xiàn)豌豆發(fā)射子彈,如下:

更新子彈的位置,如下:

在updateGame函數(shù)中,發(fā)射子彈并更新子彈的位置,如下:

在updateWindow中繪制子彈,如下:

子彈和僵尸的碰撞
子彈碰到僵尸之后,子彈會“爆炸”,同時僵尸會“掉血”。我們先給僵尸添加血量成員。

并在創(chuàng)建僵尸的時候,把血量初始化為100,如下:

子彈在碰到僵尸之后才會爆炸,并顯示爆炸圖片:

所以,我們在子彈的結構體中添加兩個成員,分別表示當前是否已經(jīng)爆炸,以及爆炸的幀圖片序號,如下:

在gameInit函數(shù)中對子彈幀圖片數(shù)組,進行初始化,如下:

在發(fā)射子彈shoot函數(shù)中,對子彈的blast和幀序號frameIndex進行初始化,如下:

在更新子彈的updateBullets函數(shù)中,更新子彈爆炸的幀序號,如下:

進行碰撞檢測,檢查子彈和僵尸是否發(fā)生碰撞,如下:

在updateGame函數(shù)中,調(diào)用碰撞檢測函數(shù),如下:

渲染子彈的爆炸效果,如下:

僵尸死亡
僵尸被豌豆子彈擊中后,會“掉血”,血量掉光了,就直接KO了,同時變成一堆“黑沙”。
給僵尸結構體添加dead成員,表示是否已經(jīng)死亡,另外添加一個圖片幀數(shù)組,用來表示變成成黑沙的過程。

在gameInit中對這個圖片幀數(shù)組進行初始化。

在碰撞檢測中對僵尸的血量做檢測,如果血量降到0,就設置為死亡狀態(tài)。如下:

僵尸死亡后,在updateZM中,更新僵尸的狀態(tài)(變成黑沙發(fā))。如下:

繪制僵尸的黑沙狀態(tài),如下:

后續(xù)的內(nèi)容詳情看主頁置頂視頻