公司用wordpress建站用花钱,简洁大气网站源码,河南专业网络推广公司,网站开发属于哪一类#x1f680;欢迎互三#x1f449;#xff1a;程序猿方梓燚 #x1f48e;#x1f48e; #x1f680;关注博主#xff0c;后期持续更新系列文章 #x1f680;如果有错误感谢请大家批评指出#xff0c;及时修改 #x1f680;感谢大家点赞#x1f44d;收藏⭐评论✍ 游戏… 欢迎互三程序猿方梓燚 关注博主后期持续更新系列文章 如果有错误感谢请大家批评指出及时修改 感谢大家点赞收藏⭐评论✍ 游戏效果
一、准备工作
确保你安装了一个 C 编译器如 Visual Studio 2019 等。安装了EasyX图形库。并且了解基本的 C 语法包括变量声明、数据类型、控制结构如循环和条件语句等。
二、代码结构概述
整个代码实现了一个类似《植物大战僵尸》的游戏。 代码主要分为以下几个部分 头文件head.h包含了游戏中所需的各种库的引用、宏定义、结构体、枚举类型、类的声明等。 源文件PvZ.cpp实现了游戏的各种功能函数和主函数。
三、头文件head.h详解
1、库引用和宏定义 #include iostream等一系列库的引用为程序提供了输入输出、时间处理、图形绘制、声音播放等功能。 宏定义了各种游戏元素的类型例如不同的植物和僵尸类型、地图状态等方便在程序中使用统一的标识符来表示这些元素。
#define GRASS 0
#define GRAVE1 1
//...
#define BUCKETHEADZOMBIE 16这些宏定义使得在程序中可以使用诸如GRASS表示草地、BUCKETHEADZOMBIE表示铁桶僵尸等提高了代码的可读性和可维护性。
2、结构体和枚举类型 coordinate结构体定义了坐标方便在程序中表示游戏元素的位置。
struct coordinate
{int x;int y;
};CURSORFLAG枚举类型定义了鼠标光标的不同状态用于确定玩家当前可以进行的操作。
enum CURSORFLAG
{Chammer, CpotatoMine,Ciceshroom,Cgravebuster
};3、类的声明
Bang类表示爆炸效果包含爆炸的位置和倒计时等成员变量用于在游戏中显示爆炸效果并控制其持续时间。
class Bang
{
public:int No;int x;int y;int countDown;Bang(int x,int y){No bangNum;bangNum;this-x x;this-y y;countDown 20;}
};Sun类表示太阳包含太阳的位置、帧、编号等成员变量用于在游戏中生成和管理太阳资源。
class Sun
{
public:int x;int y;int frame;int No;int changeFrameCountDown;int goToCount;int goToCountFrame;int tempX;int tempY;Sun(int x,int y){frame 0;NosunNum;sunNum;this-x x;this-y y;this-tempX x;this-tempY y;changeFrameCountDown 5;goToCount 0;goToCountFrame 10;}
};Plant类是植物的基类包含植物的类型、生命值、帧编号等成员变量为不同类型的植物提供了共同的属性和方法。
class Plant
{
public:int type;int HP;int frameNo;int No;int x;int y;int changeFrameCountDown;Plant(){No plantNum;plantNum;changeFrameCountDown 5;HP 6;}~Plant(){}
};PotatoMine、GraveBuster、IceShroom类分别是土豆雷、墓碑吞噬者、寒冰菇的具体类继承自Plant类并添加了各自特有的成员变量实现了不同植物的特定功能。Zombie类是僵尸的基类包含僵尸的生命值、行、位置、状态等成员变量为不同类型的僵尸提供了共同的属性和方法。
class Zombie
{
public:int HP;int row;int location;int emerge1walk2eat3;int frameNo;int height;int No;int changeFrameCountDown;int isFrozen;int isSlowed;int type;Zombie(){No zombieNum;zombieNum;isFrozen 0;isSlowed 0;height 115;frameNo 19;emerge1walk2eat3 1;changeFrameCountDown 10;}
};NormalZombie、ConeheadZombie、BucketheadZombie类分别是普通僵尸、路障僵尸、铁桶僵尸的具体类继承自Zombie类并设置了不同的生命值和类型实现了不同僵尸的特定行为。Lawnmower类表示除草机包含除草机的位置和状态等成员变量用于在游戏中处理僵尸与除草机的交互。
class Lawnmower
{
public:int location -20;int isActivated 0;int isOut 0;
};Node和LinkList模板类用于实现链表结构分别表示链表节点和链表用于管理游戏中的各种对象如太阳、植物、僵尸等。
templateclass T
class Node
{
public:T* content;Node* next NULL;Node(T* t){content t;}
};templateclass T
class LinkList
{
public:NodeT* head; NodeT* tail;LinkList(){head NULL;tail NULL;};LinkList(NodeT node){ head node; tail node; };~LinkList(){ DeleteAllNode();} void InsertNode(T* t)//... (其他函数的实现)
};四、源文件PvZ.cpp详解
1、函数声明和命名空间
使用各种编译指令和命名空间声明为程序提供必要的设置和功能。using namespace std;使得可以直接使用标准库中的名称而无需加上std::前缀方便了代码的编写。
2、初始化函数init
void init()
{for (int i 0; i 5; i){for (int j 0; j 9; j){mapState[i][j] GRASS;}}currentSunshine 0;plants.DeleteAllNode();zombies.DeleteAllNode();suns.DeleteAllNode();bangs.DeleteAllNode();for (int i 0; i 5; i){lawnmowers[i] new Lawnmower();}normalfrequency 0.002;coneheadfrequency 0.0025;bucketheadfrequency 0.0028;SunsFrequency 0.05;isNewGame 1;isHitting 0;hammerRadius 0;drawingHint 0;hintCountDown 70;snowCountDown 0;graveNum 0;Win1Lose2 0;
}这个函数初始化了游戏的各种参数包括地图状态、阳光数量、各种链表的清空、除草机的状态、生成僵尸和太阳的频率等。它为游戏的开始或重新开始提供了一个干净的状态。
3、 读取存档函数readArchive和写入存档函数writeArchive
readArchive函数从文件中读取游戏存档数据包括地图状态、各种对象的状态等并将其加载到游戏中。
void readArchive(char name[])
{init();char path[] ./archives/, tmppath[200] { 0 };strcat(strcat(tmppath, path), name);FILE* fp fopen(tmppath, rb);::fread(mapState, sizeof(mapState), 1, fp);for (int i 0; i 5; i){lawnmowers[i] new Lawnmower();::fread(lawnmowers[i]-location, sizeof(int), 1, fp);::fread(lawnmowers[i]-isActivated, sizeof(int), 1, fp);::fread(lawnmowers[i]-isOut, sizeof(int), 1, fp);}fread(currentSunshine, sizeof(int), 1, fp);//... (读取其他参数和对象的状态)while (fread(separator,sizeof(int),1,fp)){Sun* tmpSun new Sun(0, 0);fread(tmpSun-x, sizeof(int), 1, fp);fread(tmpSun-y, sizeof(int), 1, fp);fread(tmpSun-frame, sizeof(int), 1, fp);fread(tmpSun-No, sizeof(int), 1, fp);fread(tmpSun-changeFrameCountDown, sizeof(int), 1, fp);fread(tmpSun-goToCount, sizeof(int), 1, fp);fread(tmpSun-goToCountFrame, sizeof(int), 1, fp);fread(tmpSun-tempX, sizeof(int), 1, fp);fread(tmpSun-tempY, sizeof(int), 1, fp);suns.InsertNode(tmpSun);}fclose(fp);
}writeArchive函数将游戏当前状态写入文件以保存存档。
4、精确延时函数HpSleep
void HpSleep(int ms)
{static clock_t oldclock clock();oldclock ms * CLOCKS_PER_SEC / 1000;if (clock() oldclock)oldclock clock();elsewhile (clock() oldclock)Sleep(1);
}这个函数通过计算时间差实现精确的延时功能可以精确到 1ms。它用于控制游戏的帧率和动画效果的播放速度。
5、透明图像绘制函数transparentImage和添加冰效果函数addIce
transparentImage函数用于将一个图像以透明的方式绘制到另一个图像上指定的位置。
void transparentImage(IMAGE* dstimg, int x, int y, IMAGE* srcimg)
{HDC dstDC GetImageHDC(dstimg);HDC srcDC GetImageHDC(srcimg);int w srcimg-getwidth();int h srcimg-getheight();BLENDFUNCTION bf { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };AlphaBlend(dstDC, x, y, w, h, srcDC, 0, 0, w, h, bf);
}addIce函数用于给图像添加冰效果通过调整图像的颜色值实现。
void addIce(IMAGE* targetImage, IMAGE* srcImage, int addRed 0, int addGreen 0, int addBlue 50)
{int srcImgWidth srcImage-getwidth(), srcImgHeight srcImage-getheight();targetImage-Resize(srcImgWidth, srcImgHeight);DWORD* pTargetBuffer GetImageBuffer(targetImage);DWORD* pSrcBuffer GetImageBuffer(srcImage);int allPixel srcImgHeight * srcImgWidth;for (int i 0; i allPixel; i){UCHAR r (UCHAR)GetRValue(pSrcBuffer[i]);UCHAR g (UCHAR)GetGValue(pSrcBuffer[i]);UCHAR b (UCHAR)GetBValue(pSrcBuffer[i]);r r addRed;r r 255? 255 : r;g g addGreen;g g 255? 255 : g;b b addBlue;b b 255? 255 : b;pTargetBuffer[i] (DWORD)RGBA(r, g, b, pSrcBuffer[i] 24);}
}6、绘制游戏元素的函数
paintPlantsAndGraves函数绘制植物和墓碑。根据地图状态在不同的位置绘制不同类型的植物和墓碑并更新植物的状态。
void paintPlantsAndGraves()
{for (int i 0; i 5; i){for (int j 0; j 9; j){switch (mapState[i][j]){case GRASS:break;case GRAVE1:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[0]);break;}//... (处理其他地图状态)}}}
}paintZombies函数绘制僵尸。根据僵尸的状态绘制不同的僵尸图像并处理僵尸的移动、动画和状态变化。
void paintZombies()
{NodeZombie *cur zombies.head, *next NULL;while (cur! NULL){Zombie* zombieptr cur-content;if (zombieptr-emerge1walk2eat3 1){//... (绘制正在冒出来的僵尸)}else if (zombieptr-emerge1walk2eat3 2){//... (绘制正在行走的僵尸)}else if (zombieptr-emerge1walk2eat3 3){//... (绘制正在吃植物的僵尸)}// 判断是否冻住或减速if (zombieptr-isFrozen 0){//...}if (zombieptr-isSlowed 0){//...}// 如果僵尸走到最左边且此行有除草机if (zombieptr-location -50 lawnmowers[zombieptr-row]-isOut 0){//...}// 如果僵尸前面有植物//...// 如果僵尸前面有除草机if (lawnmowers[zombieptr-row]-isOut 0 zombieptr-location lawnmowers[zombieptr-row]-location - 30){//...}cur cur-next;}
}paintSuns函数绘制太阳。更新太阳的帧并处理太阳被收集的情况
void paintSuns()
{NodeSun *cur suns.head, *next;while (cur! NULL){Sun* sun cur-content;transparentImage(NULL, sun-x, sun-y, sunPictures[sun-frame]);sun-changeFrameCountDown--;if (sun-changeFrameCountDown 0){sun-changeFrameCountDown 5;sun-frame;if (sun-frame 22) sun-frame 0;if (sun-goToCount 1){sun-x sun-tempX / 10 * sun-goToCountFrame;sun-y sun-tempY / 10 * sun-goToCountFrame;sun-goToCountFrame--;if (sun-goToCountFrame 0){next cur-next;suns.DeleteNode(sun-No);cur next;currentSunshine 25;continue;}}}cur cur-next;}
}这个函数遍历太阳链表绘制每个太阳的图像。通过更新太阳的帧编号和倒计时实现太阳的动画效果。当太阳被点击 (goToCount为 1)时太阳会逐渐移动到特定位置然后被收集增加阳光数量并从链表中删除。paintBangs函数绘制爆炸效果。根据爆炸的倒计时绘制爆炸图像并在倒计时结束时删除爆炸对象。
void paintBangs()
{NodeBang* cur bangs.head,*pre;while (cur! NULL){if (cur-content-countDown 0){cur-content-countDown--;transparentImage(NULL, cur-content-x, cur-content-y, bang);}pre cur;cur cur-next; if(pre-content-countDown0)bangs.DeleteNode(pre-content-No);}
}该函数遍历爆炸效果链表绘制每个爆炸的图像。随着倒计时的减少不断更新爆炸的状态。当倒计时为 0 时从链表中删除对应的爆炸对象。paintCursor函数绘制鼠标光标。根据光标的状态绘制不同的图像。
void paintCursor()
{if (cursor Chammer){// 如果没锤画正常角度锤子if (!isHitting)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, hammer[0]);else{// 画旋转锤子transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, hammer[hammerRadius]);hammerRadius;if (hammerRadius 13){hammerRadius 0;isHitting 0;}}}else if (cursor CpotatoMine)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, potaotoMinePictures[0]);else if (cursor Ciceshroom)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, iceshroomPictures[0]);elsetransparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, gravebusterPictures[0]);
}根据鼠标光标的状态锤子、土豆雷、寒冰菇、墓碑吞噬者在鼠标位置绘制相应的图像。如果是锤子状态且正在锤击isHitting为真则绘制旋转的锤子图像。
7、随机生成游戏元素的函数
generateSunshine函数在一定概率下生成阳光并将其添加到游戏中。
void generateSunshine(int x, int y)
{// 一定概率产生 3 个阳光double p rand() / (double)RAND_MAX;if (p SunsFrequency){Sun* sunshine[3];for (int i 0; i 3; i){sunshine[i] new Sun(x 80 rand() % 100 - 50, y 60 rand() % 50 - 25);suns.InsertNode(sunshine[i]);}}
}这个函数根据给定的概率生成阳光对象并将它们添加到太阳链表中。阳光的位置在一定范围内随机生成。randomZombies函数随机生成僵尸。根据概率在地图上随机位置生成不同类型的僵尸并播放相应的音效。
void randomZombies()
{// 随机产生僵尸for (int i 0; i 5; i){for (int j 3; j 9; j){if (1 mapState[i][j] mapState[i][j] 8){double p rand() / (double)RAND_MAX;if (p normalfrequency){NormalZombie* normalZombie new NormalZombie();normalZombie-row i;normalZombie-location xys[i][j].x - 75;zombies.InsertNode(normalZombie);mciSendString(play./Music/dirt_rise.mp3 from 0, 0, 0, 0);}else if (normalfrequency p p coneheadfrequency){ConeheadZombie* coneheadZombie new ConeheadZombie();coneheadZombie-row i;coneheadZombie-location xys[i][j].x - 75;zombies.InsertNode(coneheadZombie);mciSendString(play./Music/dirt_rise.mp3 from 0, 0, 0, 0);}else if (coneheadfrequency p p bucketheadfrequency){BucketheadZombie* bucketheadZombie new BucketheadZombie();bucketheadZombie-row i;bucketheadZombie-location xys[i][j].x - 75;zombies.InsertNode(bucketheadZombie);mciSendString(play./Music/dirt_rise.mp3 from 0, 0, 0, 0);}}}}// 随机呻吟声double p rand() / (double)RAND_MAX;if (p groanFrequency){int px rand() % 6 1;switch (px){case 1:mciSendString(play./Music/groan.mp3 from 0, 0, 0, 0);break;case 2:mciSendString(play./Music/groan2.mp3 from 0, 0, 0, 0);break;case 3:mciSendString(play./Music/groan3.mp3 from 0, 0, 0, 0);break;case 4:mciSendString(play./Music/groan4.mp3 from 0, 0, 0, 0);break;case 5:mciSendString(play./Music/groan5.mp3 from 0, 0, 0, 0);break;case 6:mciSendString(play./Music/groan6.mp3 from 0, 0, 0, 0);break;}}
}这个函数在游戏中随机生成僵尸。首先根据给定的概率在地图上的特定位置生成普通僵尸、路障僵尸或铁桶僵尸并播放相应的音效。然后再次根据概率随机播放僵尸的呻吟声。randomGraves函数随机生成墓碑。确保游戏中有一定数量的墓碑并随机分布在地图上。
void randomGraves()
{// 随机产生墓碑while (graveNum 6 || graveNum 13){graveNum 0;for (int i 0; i 5; i){int num rand() % 4;for (int j 0; j num; j){int column rand() % 6 3;if (mapState[i][column] 0){mapState[i][column] rand() % 8 1;graveNum;}else j--;}}}
}该函数用于在游戏开始时随机生成一定数量的墓碑。通过不断调整墓碑的数量确保游戏中有 6 到 13 个墓碑随机分布在地图上。
8、绘制存档名称函数paintNames和绘制提示函数drawHint
paintNames函数读取存档文件夹中的存档文件并在游戏界面上绘制存档名称。如果存档过多或没有存档会显示相应的提示信息。
void paintNames()
{// 画出存档名称getFiles(./archives);RECT rect;setbkmode(TRANSPARENT);settextcolor(RGB(222, 186, 97));if (files.size() 5){settextstyle(20, 0, 华文隶书);rect { 268, 135, 538, 335 };drawtext(存档过多请删除 archives, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);rect { 268, 175, 538, 375 };drawtext(文件夹下的存档并重启!, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);}else if (files.size() 0){settextstyle(40, 0, 华文隶书);rect { 268, 159, 538, 360 };drawtext(没有存档!, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);}else{int h 189;settextstyle(35, 0, 华文隶书);for (int i 0; i files.size(); i){rect { 268, h, 538, h 40 };drawtext(files[i].c_str(), rect, DT_CENTER);h 40;}}
}这个函数首先获取存档文件夹中的存档文件列表。然后根据存档数量的不同情况在游戏界面上绘制相应的提示信息或存档名称。如果存档过多会提示玩家删除一些存档并重启游戏如果没有存档则显示 “没有存档”如果有存档则逐个绘制存档名称。drawHint函数根据游戏状态绘制提示信息如 “此处不能种植物” 或 “阳光不足”。
void drawHint()
{if (drawingHint! 0){settextcolor(WHITE);settextstyle(40, 0, 隶书);if (drawingHint 1){drawtext(此处不能种植物, rect, DT_CENTER);}else if (drawingHint 2)drawtext(阳光不足, rect, DT_CENTER);hintCountDown--;if (hintCountDown 0){hintCountDown 70;drawingHint 0;}}
}该函数根据游戏中的提示状态drawingHint绘制相应的提示信息在游戏界面上。如果提示状态为 1则绘制 “此处不能种植物”如果提示状态为 2则绘制 “阳光不足”。提示会持续一段时间由hintCountDown控制然后消失。
五、完整代码素材
head.h
#include iostream
#include ctime
#include string
#include graphics.h
#include conio.h
#include Windows.h
#include io.h
#include vector
#include stdio.h
#include cmath
#include mmsystem.h
using namespace std;#define GRASS 0
#define GRAVE1 1
#define GRAVE2 2
#define GRAVE3 3
#define GRAVE4 4
#define GRAVE5 5
#define GRAVE6 6
#define GRAVE7 7
#define GRAVE8 8
#define POTATO 9
#define POTATOMINE 10
#define POTATOBOOM 11
#define GRAVEBUSTER_GRAVE1 12
#define GRAVEBUSTER_GRAVE2 13
#define GRAVEBUSTER_GRAVE3 14
#define GRAVEBUSTER_GRAVE4 15
#define GRAVEBUSTER_GRAVE5 16
#define GRAVEBUSTER_GRAVE6 17
#define GRAVEBUSTER_GRAVE7 18
#define GRAVEBUSTER_GRAVE8 19
#define ICESHROOM 20
#define NORMALZOMBIE 21
#define CONEHEADZOMBIE 22
#define BUCKETHEADZOMBIE 16//非游戏参数
int zombieNum0;
int plantNum0;
int sunNum0;
int bangNum0;
double groanFrequency 0.0005;
IMAGE potatoBoom;
IMAGE potato;
IMAGE grave[8];
IMAGE hammer[13];
IMAGE tmpImg;
IMAGE tmpImg2;
IMAGE potaotoMinePictures[8];
IMAGE iceshroomPictures[11];
IMAGE gravebusterPictures[28];
IMAGE sunPictures[22];
IMAGE normalZombieWalkPictures[47];
IMAGE normalZombieEmergePictures[20];
IMAGE normalZombieEatPictures[10];
IMAGE coneheadZombieWalkPictures[47];
IMAGE coneheadZombieEmergePictures[20];
IMAGE coneheadZombieEatPictures[10];
IMAGE bucketheadZombieWalkPictures[47];
IMAGE bucketheadZombieEmergePictures[20];
IMAGE bucketheadZombieEatPictures[10];
IMAGE plantsBar;
IMAGE menu;
IMAGE background;
IMAGE selectID;
IMAGE iceTrap;
IMAGE snow;
IMAGE lawnmower;
IMAGE loseGame;
IMAGE winGame;
IMAGE bang;
ExMessage mousemsg;struct coordinate
{int x;int y;
};enum CURSORFLAG
{Chammer, CpotatoMine,Ciceshroom,Cgravebuster
};coordinate xys[32][32];
CURSORFLAG cursor;
RECT rect { 0, 500, 820, 600 };
char sunshineNum[10];
char username[200];
vectorstring files;class Bang
{
public:int No;int x;int y;int countDown;Bang(int x,int y){No bangNum;bangNum;this-x x;this-y y;countDown 20;}
};class Sun
{
public:int x;int y;int frame;int No;int changeFrameCountDown;int goToCount;int goToCountFrame;int tempX;int tempY;Sun(int x,int y){frame 0;NosunNum;sunNum;this-x x;this-y y;this-tempX x;this-tempY y;changeFrameCountDown 5;goToCount 0;goToCountFrame 10;}
};class Plant
{
public:int type;int HP;int frameNo;int No;int x;int y;int changeFrameCountDown;Plant(){No plantNum;plantNum;changeFrameCountDown 5;HP 6;}~Plant(){}
};// 土豆雷
class PotatoMine : public Plant
{
public:int underCountDown 400;int boomCountDown 50;PotatoMine(){frameNo 0;type POTATOMINE;}
};// 墓碑吞噬者
class GraveBuster : public Plant
{
public:GraveBuster(){frameNo 1;type GRAVEBUSTER_GRAVE1;}
};// 寒冰菇
class IceShroom : public Plant
{
public:int frozenCountDown 200;int slowingCountDown 1000;IceShroom(){frameNo 0;type ICESHROOM;}
};class Zombie
{
public:int HP;int row;int location;int emerge1walk2eat3;int frameNo;int height;int No;int changeFrameCountDown;int isFrozen;int isSlowed;int type;Zombie(){No zombieNum;zombieNum;isFrozen 0;isSlowed 0;height 115; // 僵尸图像高度frameNo 19; // 表示播放到第几帧emerge1walk2eat3 1; // 正在冒出来用 1 表示正在行走用 2 表示正在吃植物用 3 表示changeFrameCountDown 10;}
};
class NormalZombie : public Zombie
{
public:NormalZombie(){HP 1;type NORMALZOMBIE;}
};class ConeheadZombie : public Zombie
{
public:ConeheadZombie(){HP 2;type CONEHEADZOMBIE;}
};class BucketheadZombie : public Zombie
{
public:BucketheadZombie(){HP 3;type BUCKETHEADZOMBIE;}
};class Lawnmower
{
public:int location -20;int isActivated 0;int isOut 0;
};templateclass T
class Node
{
public:T* content;Node* next NULL;Node(T* t){content t;}
};templateclass T
class LinkList
{
public:NodeT* head; NodeT* tail;LinkList(){head NULL;tail NULL;};LinkList(NodeT node){ head node; tail node; };~LinkList(){ DeleteAllNode();} void InsertNode(T* t){NodeT* nodenew NodeT(t);if (head NULL){head node;tail node;}else{tail-next node;tail node;}};void DeleteNode(int No){NodeT* cur head,*preNULL;while (cur ! NULL cur-content-No ! No){pre cur;cur cur-next;}if (pre NULL){head cur-next;}else if (cur NULL){cout 没有找到符合条件的结点 endl;return;}else{pre-next cur-next;}if (cur tail){tail pre;}delete cur;};void DeleteAllNode(){NodeT* cur head,*preNULL;while (tail ! NULL){pre cur;cur cur-next;DeleteNode(pre-content-No);}};
};PvZ.cpp
#include head.h
#pragma warning (disable:4996)
#pragma comment( lib, MSIMG32.LIB)
#pragma comment( lib, winmm.lib)// 游戏参数
int mapState[32][32]; // 地图状态。0空1墓碑2地雷没出土3地雷已出土4寒冰菇
int currentSunshine;
LinkListSun suns;
LinkListPlant plants;
LinkListZombie zombies;
LinkListBang bangs;
Lawnmower* lawnmowers[5];
double normalfrequency;
double coneheadfrequency;
double bucketheadfrequency;
double SunsFrequency;
int isNewGame;
int isHitting;
int hammerRadius;
int drawingHint;
int hintCountDown;
int snowCountDown;
int graveNum;
int Win1Lose2;void init()
{for (int i 0; i 5; i){for (int j 0; j 9; j){mapState[i][j] GRASS;}}currentSunshine 0;plants.DeleteAllNode();zombies.DeleteAllNode();suns.DeleteAllNode();bangs.DeleteAllNode();for (int i 0; i 5; i){lawnmowers[i] new Lawnmower();}normalfrequency 0.002;coneheadfrequency 0.0025;bucketheadfrequency 0.0028;SunsFrequency 0.05;isNewGame 1;isHitting 0;hammerRadius 0;drawingHint 0;hintCountDown 70;snowCountDown 0;graveNum 0;Win1Lose2 0;
}void getFiles(string path)
{files.clear();//文件句柄 intptr_t hFile 0;//文件信息 struct _finddata_t fileinfo;string p;if ((hFile _findfirst(p.assign(path).append(\\*).c_str(), fileinfo)) ! -1){do{files.push_back(fileinfo.name);} while (_findnext(hFile, fileinfo) 0);_findclose(hFile);}files.erase(files.begin());files.erase(files.begin());
}void readArchive(char name[])
{init();char path[] ./archives/, tmppath[200] { 0 };strcat(strcat(tmppath, path), name);FILE* fp fopen(tmppath, rb);::fread(mapState, sizeof(mapState), 1, fp);for (int i 0; i 5; i){lawnmowers[i] new Lawnmower();::fread(lawnmowers[i]-location, sizeof(int), 1, fp);::fread(lawnmowers[i]-isActivated, sizeof(int), 1, fp);::fread(lawnmowers[i]-isOut, sizeof(int), 1, fp);}fread(currentSunshine, sizeof(int), 1, fp);fread(normalfrequency, sizeof(double), 1, fp);fread(coneheadfrequency, sizeof(double), 1, fp);fread(bucketheadfrequency, sizeof(double), 1, fp);fread(SunsFrequency, sizeof(double), 1, fp);fread(isNewGame, sizeof(int), 1, fp);fread(isHitting, sizeof(int), 1, fp);fread(hammerRadius, sizeof(int), 1, fp);fread(drawingHint, sizeof(int), 1, fp);fread(hintCountDown, sizeof(int), 1, fp);fread(snowCountDown, sizeof(int), 1, fp);fread(graveNum, sizeof(int), 1, fp);fread(Win1Lose2, sizeof(int), 1, fp);int separator;while (1){fread(separator, sizeof(int), 1, fp);if (separator!1234567){Zombie* tmpZombie new Zombie();fseek(fp, -(int)sizeof(int), SEEK_CUR);fread(tmpZombie-HP, sizeof(int), 1, fp);fread(tmpZombie-row, sizeof(int), 1, fp);fread(tmpZombie-location, sizeof(int), 1, fp);fread(tmpZombie-emerge1walk2eat3, sizeof(int), 1, fp);fread(tmpZombie-frameNo, sizeof(int), 1, fp);fread(tmpZombie-height, sizeof(int), 1, fp);fread(tmpZombie-No, sizeof(int), 1, fp);fread(tmpZombie-changeFrameCountDown, sizeof(int), 1, fp);fread(tmpZombie-isFrozen, sizeof(int), 1, fp);fread(tmpZombie-isSlowed, sizeof(int), 1, fp);fread(tmpZombie-type, sizeof(int), 1, fp);zombies.InsertNode(tmpZombie);}else break;}int tmpPlantType;while (1){fread(separator, sizeof(int), 1, fp);if (separator!7654321){fseek(fp, -(int)sizeof(int), SEEK_CUR);fread(tmpPlantType, sizeof(int), 1, fp);switch (tmpPlantType){case POTATOMINE:{PotatoMine* tmpPotatoMine new PotatoMine();tmpPotatoMine-type tmpPlantType;fread(tmpPotatoMine-frameNo, sizeof(int), 1, fp);fread(tmpPotatoMine-No, sizeof(int), 1, fp);fread(tmpPotatoMine-x, sizeof(int), 1, fp);fread(tmpPotatoMine-y, sizeof(int), 1, fp);fread(tmpPotatoMine-changeFrameCountDown, sizeof(int), 1, fp);fread(tmpPotatoMine-underCountDown, sizeof(int), 1, fp);fread(tmpPotatoMine-boomCountDown, sizeof(int), 1, fp);plants.InsertNode(tmpPotatoMine);break;}case GRAVEBUSTER_GRAVE1:{GraveBuster* tmpGraveBuster new GraveBuster();tmpGraveBuster-type tmpPlantType;fread(tmpGraveBuster-frameNo, sizeof(int), 1, fp);fread(tmpGraveBuster-No, sizeof(int), 1, fp);fread(tmpGraveBuster-x, sizeof(int), 1, fp);fread(tmpGraveBuster-y, sizeof(int), 1, fp);fread(tmpGraveBuster-changeFrameCountDown, sizeof(int), 1, fp);plants.InsertNode(tmpGraveBuster);break;}case ICESHROOM:{IceShroom* tmpIceShroom new IceShroom();tmpIceShroom-type tmpPlantType;fread(tmpIceShroom-frameNo, sizeof(int), 1, fp);fread(tmpIceShroom-No, sizeof(int), 1, fp);fread(tmpIceShroom-x, sizeof(int), 1, fp);fread(tmpIceShroom-y, sizeof(int), 1, fp);fread(tmpIceShroom-changeFrameCountDown, sizeof(int), 1, fp);fread(tmpIceShroom-frozenCountDown, sizeof(int), 1, fp);fread(tmpIceShroom-slowingCountDown, sizeof(int), 1, fp);plants.InsertNode(tmpIceShroom);break;}}}else break;}while (1){fread(separator, sizeof(int), 1, fp);if (separator ! 357421){Bang* tmpBang new Bang(0,0);fseek(fp, -(int)sizeof(int), SEEK_CUR);fread(tmpBang-No, sizeof(int), 1, fp);fread(tmpBang-x, sizeof(int), 1, fp);fread(tmpBang-y, sizeof(int), 1, fp);fread(tmpBang-countDown, sizeof(int), 1, fp);bangs.InsertNode(tmpBang);}elsebreak;}while (fread(separator,sizeof(int),1,fp)){Sun* tmpSun new Sun(0, 0);fread(tmpSun-x, sizeof(int), 1, fp);fread(tmpSun-y, sizeof(int), 1, fp);fread(tmpSun-frame, sizeof(int), 1, fp);fread(tmpSun-No, sizeof(int), 1, fp);fread(tmpSun-changeFrameCountDown, sizeof(int), 1, fp);fread(tmpSun-goToCount, sizeof(int), 1, fp);fread(tmpSun-goToCountFrame, sizeof(int), 1, fp);fread(tmpSun-tempX, sizeof(int), 1, fp);fread(tmpSun-tempY, sizeof(int), 1, fp);suns.InsertNode(tmpSun);}fclose(fp);
}void writeArchive(char name[])
{char path[] ./archives/, tmppath[200] { 0 };strcat(strcat(tmppath, path), name);FILE* fp fopen(tmppath, wb);::fwrite(mapState, sizeof(mapState), 1, fp);for (int i 0; i 5; i){::fwrite(lawnmowers[i]-location, sizeof(int), 1, fp);::fwrite(lawnmowers[i]-isActivated, sizeof(int), 1, fp);::fwrite(lawnmowers[i]-isOut, sizeof(int), 1, fp);}::fwrite(currentSunshine, sizeof(int), 1, fp);::fwrite(normalfrequency, sizeof(double), 1, fp);::fwrite(coneheadfrequency, sizeof(double), 1, fp);::fwrite(bucketheadfrequency, sizeof(double), 1, fp);::fwrite(SunsFrequency, sizeof(double), 1, fp);::fwrite(isNewGame, sizeof(int), 1, fp);::fwrite(isHitting, sizeof(int), 1, fp);::fwrite(hammerRadius, sizeof(int), 1, fp);::fwrite(drawingHint, sizeof(int), 1, fp);::fwrite(hintCountDown, sizeof(int), 1, fp);::fwrite(snowCountDown, sizeof(int), 1, fp);::fwrite(graveNum, sizeof(int), 1, fp);::fwrite(Win1Lose2, sizeof(int), 1, fp);NodeZombie* curZombie zombies.head;while (curZombie ! NULL){Zombie* zombie curZombie-content;::fwrite(zombie-HP, sizeof(int), 1, fp);::fwrite(zombie-row, sizeof(int), 1, fp);::fwrite(zombie-location, sizeof(int), 1, fp);::fwrite(zombie-emerge1walk2eat3, sizeof(int), 1, fp);::fwrite(zombie-frameNo, sizeof(int), 1, fp);::fwrite(zombie-height, sizeof(int), 1, fp);::fwrite(zombie-No, sizeof(int), 1, fp);::fwrite(zombie-changeFrameCountDown, sizeof(int), 1, fp);::fwrite(zombie-isFrozen, sizeof(int), 1, fp);::fwrite(zombie-isSlowed, sizeof(int), 1, fp);::fwrite(zombie-type, sizeof(int), 1, fp);curZombie curZombie-next;}int separator1 1234567;::fwrite(separator1, sizeof(int), 1, fp);NodePlant* curPlant plants.head;while (curPlant ! NULL){switch (curPlant-content-type){case POTATOMINE:{PotatoMine* potatoMine static_castPotatoMine*(curPlant-content);::fwrite(potatoMine-type, sizeof(int), 1, fp);::fwrite(potatoMine-frameNo, sizeof(int), 1, fp);::fwrite(potatoMine-No, sizeof(int), 1, fp);::fwrite(potatoMine-x, sizeof(int), 1, fp);::fwrite(potatoMine-y, sizeof(int), 1, fp);::fwrite(potatoMine-changeFrameCountDown, sizeof(int), 1, fp);::fwrite(potatoMine-underCountDown, sizeof(int), 1, fp);::fwrite(potatoMine-boomCountDown, sizeof(int), 1, fp);break;}case ICESHROOM:{IceShroom* iceShroom static_castIceShroom*(curPlant-content);::fwrite(iceShroom-type, sizeof(int), 1, fp);::fwrite(iceShroom-frameNo, sizeof(int), 1, fp);::fwrite(iceShroom-No, sizeof(int), 1, fp);::fwrite(iceShroom-x, sizeof(int), 1, fp);::fwrite(iceShroom-y, sizeof(int), 1, fp);::fwrite(iceShroom-changeFrameCountDown, sizeof(int), 1, fp);::fwrite(iceShroom-frozenCountDown, sizeof(int), 1, fp);::fwrite(iceShroom-slowingCountDown, sizeof(int), 1, fp);break;}case GRAVEBUSTER_GRAVE1:{GraveBuster* graveBuster static_castGraveBuster*(curPlant-content);::fwrite(graveBuster-type, sizeof(int), 1, fp);::fwrite(graveBuster-frameNo, sizeof(int), 1, fp);::fwrite(graveBuster-No, sizeof(int), 1, fp);::fwrite(graveBuster-x, sizeof(int), 1, fp);::fwrite(graveBuster-y, sizeof(int), 1, fp);::fwrite(graveBuster-changeFrameCountDown, sizeof(int), 1, fp);break;}}curPlant curPlant-next;}int separator2 7654321;::fwrite(separator2, sizeof(int), 1, fp);NodeBang* curBang bangs.head;while (curBang! NULL){Bang* bang curBang-content;::fwrite(bang-No, sizeof(int), 1, fp);::fwrite(bang-x, sizeof(int), 1, fp);::fwrite(bang-y, sizeof(int), 1, fp);::fwrite(bang-countDown, sizeof(int), 1, fp);curBang curBang-next;}int separator3 357421;::fwrite(separator3, sizeof(int), 1, fp);NodeSun* curSun suns.head;while (curSun ! NULL){Sun* sun curSun-content;::fwrite(sun-x, sizeof(int), 1, fp);::fwrite(sun-y, sizeof(int), 1, fp);::fwrite(sun-frame, sizeof(int), 1, fp);::fwrite(sun-No, sizeof(int), 1, fp);::fwrite(sun-changeFrameCountDown, sizeof(int), 1, fp);::fwrite(sun-goToCount, sizeof(int), 1, fp);::fwrite(sun-goToCountFrame, sizeof(int), 1, fp);::fwrite(sun-tempX, sizeof(int), 1, fp);::fwrite(sun-tempY, sizeof(int), 1, fp);curSun curSun-next;}fclose(fp);
}// 精确延时函数(可以精确到 1ms精度 ±1ms)
// by yangw80yw80qq.com, 2011-5-4
void HpSleep(int ms)
{static clock_t oldclock clock(); // 静态变量记录上一次 tickoldclock ms * CLOCKS_PER_SEC / 1000; // 更新 tickif (clock() oldclock) // 如果已经超时无需延时oldclock clock();elsewhile (clock() oldclock) // 延时Sleep(1); // 释放 CPU 控制权降低 CPU 占用率
// Sleep(0); // 更高精度、更高 CPU 占用率
}void transparentImage(IMAGE* dstimg, int x, int y, IMAGE* srcimg)
{HDC dstDC GetImageHDC(dstimg);HDC srcDC GetImageHDC(srcimg);int w srcimg-getwidth();int h srcimg-getheight();BLENDFUNCTION bf { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };AlphaBlend(dstDC, x, y, w, h, srcDC, 0, 0, w, h, bf);
}void paintPlantsAndGraves()
{// 画植物和墓碑for (int i 0; i 5; i){for (int j 0; j 9; j){switch (mapState[i][j]){case GRASS:break;case GRAVE1:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[0]);break;}case GRAVE2:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[1]);break;}case GRAVE3:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[2]);break;}case GRAVE4:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[3]);break;}case GRAVE5:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[4]);break;}case GRAVE6:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[5]);break;}case GRAVE7:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[6]);break;}case GRAVE8:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[7]);break;}case POTATO:{transparentImage(NULL, xys[i][j].x, xys[i][j].y 37, potato);NodePlant* cur plants.head;while (cur ! NULL){if (cur-content-x i cur-content-y j){break;}else cur cur-next;}if (cur ! NULL){PotatoMine* potato static_castPotatoMine*(cur-content);potato-underCountDown--;if (potato-underCountDown 0){mapState[i][j] POTATOMINE;mciSendString(play ./Music/dirt_rise.mp3 from 0 , 0, 0, 0);}}break;}case POTATOMINE:{NodePlant* cur plants.head;while (cur ! NULL){if (cur-content-x i cur-content-y j)break;else cur cur-next;} if (cur ! NULL){transparentImage(NULL, xys[i][j].x, xys[i][j].y 40, potaotoMinePictures[cur-content-frameNo]);cur-content-changeFrameCountDown--;if (cur-content-changeFrameCountDown 0){cur-content-changeFrameCountDown 20;cur-content-frameNo;if (cur-content-frameNo 7){cur-content-frameNo 0;}}} break;}case POTATOBOOM:{transparentImage(NULL, xys[i][j].x - 25, xys[i][j].y 20, potatoBoom);NodePlant* cur plants.head;while (cur ! NULL){if (cur-content-x i cur-content-y j)break;else cur cur-next;}if (cur ! NULL){PotatoMine* potato static_castPotatoMine*(cur-content);potato-boomCountDown--;if (potato-boomCountDown 0){plants.DeleteNode(potato-No);mapState[i][j] GRASS;}} break;}case GRAVEBUSTER_GRAVE1:transparentImage(NULL, xys[i][j].x-5, xys[i][j].y, grave[0]);goto label;case GRAVEBUSTER_GRAVE2:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[1]);goto label;case GRAVEBUSTER_GRAVE3:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[2]);goto label;case GRAVEBUSTER_GRAVE4:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[3]);goto label;case GRAVEBUSTER_GRAVE5:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[4]);goto label;case GRAVEBUSTER_GRAVE6:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[5]);goto label;case GRAVEBUSTER_GRAVE7:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[6]);goto label;case GRAVEBUSTER_GRAVE8:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, grave[7]);goto label;{label:NodePlant* cur plants.head;while (cur ! NULL){if (cur-content-x i cur-content-y j)break;else cur cur-next;}if (cur ! NULL){transparentImage(NULL, xys[i][j].x - 10, xys[i][j].y - 10, gravebusterPictures[cur-content-frameNo]);cur-content-changeFrameCountDown--;if (cur-content-changeFrameCountDown 0){cur-content-changeFrameCountDown 10;cur-content-frameNo;if (cur-content-frameNo 27){plants.DeleteNode(cur-content-No);mapState[i][j] GRASS;graveNum--;if (graveNum 5){SunsFrequency 0.2;normalfrequency 0.003;coneheadfrequency 0.0035;bucketheadfrequency 0.0038;}else if (graveNum 3){SunsFrequency 0.4;normalfrequency0.006;coneheadfrequency0.0065;bucketheadfrequency0.0068;}}}} break;}case ICESHROOM:{NodePlant* cur plants.head;while (cur ! NULL){if (cur-content-x i cur-content-y j)break;else cur cur-next;}if (cur ! NULL){transparentImage(NULL, xys[i][j].x, xys[i][j].y 15, iceshroomPictures[cur-content-frameNo]);cur-content-changeFrameCountDown--;if (cur-content-changeFrameCountDown 0){cur-content-changeFrameCountDown 8;cur-content-frameNo;if (cur-content-frameNo 10){plants.DeleteNode(cur-content-No);mciSendString(play ./Music/shoop.mp3 from 0 , 0, 0, 0);mapState[i][j] 0;snowCountDown 20;NodeZombie* cur zombies.head;while (cur ! NULL){cur-content-isFrozen 200;cur cur-next;}}}} break;}}}}
}void addIce(IMAGE* targetImage, IMAGE* srcImage, int addRed 0, int addGreen 0, int addBlue 50)
{int srcImgWidth srcImage-getwidth(), srcImgHeight srcImage-getheight();targetImage-Resize(srcImgWidth, srcImgHeight);DWORD* pTargetBuffer GetImageBuffer(targetImage);DWORD* pSrcBuffer GetImageBuffer(srcImage);int allPixel srcImgHeight * srcImgWidth;#define RGBA(r, g, b, a) ((b) (g 8) (r 16) (a 24))for (int i 0; i allPixel; i){UCHAR r (UCHAR)GetRValue(pSrcBuffer[i]);UCHAR g (UCHAR)GetGValue(pSrcBuffer[i]);UCHAR b (UCHAR)GetBValue(pSrcBuffer[i]);r r addRed;r r 255 ? 255 : r;g g addGreen;g g 255 ? 255 : g;b b addBlue;b b 255 ? 255 : b;pTargetBuffer[i] (DWORD)RGBA(r, g, b, pSrcBuffer[i] 24);}
}void generateSunshine(int x, int y)
{// 一定概率产生3个阳光double p rand() / (double)RAND_MAX;if (p SunsFrequency){Sun* sunshine[3];for (int i 0; i 3; i){sunshine[i] new Sun(x 80 rand() % 100 - 50, y 60 rand() % 50 - 25);suns.InsertNode(sunshine[i]);}}
}void paintZombies()
{// 画僵尸NodeZombie *cur zombies.head, *next NULL;while (cur ! NULL){Zombie* zombieptr cur-content;if (zombieptr-location -150){cur cur-next;zombies.DeleteNode(zombieptr-No);continue;}if (zombieptr-emerge1walk2eat3 1){if (zombieptr-type NORMALZOMBIE)tmpImgnormalZombieEmergePictures[zombieptr-frameNo];else if (zombieptr-type CONEHEADZOMBIE)tmpImg coneheadZombieEmergePictures[zombieptr-frameNo];elsetmpImg bucketheadZombieEmergePictures[zombieptr-frameNo];transparentImage(NULL, zombieptr-location, xys[zombieptr-row][0].y - 40, tmpImg);zombieptr-frameNo--;if (zombieptr-frameNo 0){zombieptr-emerge1walk2eat3 2;}}else if (zombieptr-emerge1walk2eat3 2){if (zombieptr-type NORMALZOMBIE)tmpImg normalZombieWalkPictures[zombieptr-frameNo];else if (zombieptr-type CONEHEADZOMBIE)tmpImg coneheadZombieWalkPictures[zombieptr-frameNo];elsetmpImg bucketheadZombieWalkPictures[zombieptr-frameNo];if (zombieptr-isFrozen){addIce(tmpImg2, tmpImg);transparentImage(NULL, zombieptr-location, xys[zombieptr-row][0].y - 40, tmpImg2);}else if (zombieptr-isSlowed){addIce(tmpImg2, tmpImg);transparentImage(NULL, zombieptr-location, xys[zombieptr-row][0].y - 40, tmpImg2);zombieptr-changeFrameCountDown - 1;if (zombieptr-changeFrameCountDown 0){zombieptr-changeFrameCountDown 6;zombieptr-location - 1; zombieptr-frameNo;if (zombieptr-frameNo 46){zombieptr-frameNo 0;}}}else{transparentImage(NULL, zombieptr-location, xys[zombieptr-row][0].y - 40, tmpImg);zombieptr-changeFrameCountDown - 2;if (zombieptr-changeFrameCountDown 0){zombieptr-changeFrameCountDown 6;zombieptr-location - 2;zombieptr-frameNo;if (zombieptr-frameNo 46){zombieptr-frameNo 0;}}}}else if (zombieptr-emerge1walk2eat3 3){/*if (zombieptr-type NORMALZOMBIE)tmpImg normalZombieEatPictures[zombieptr-frameNo];else if (zombieptr-type CONEHEADZOMBIE)tmpImg coneheadZombieEatPictures[zombieptr-frameNo];else tmpImg bucketheadZombieEatPictures[zombieptr-frameNo];if (zombieptr-isFrozen) {addIce(tmpImg2, tmpImg);transparentImage(NULL, zombieptr-location, xys[zombieptr-row][0].y - 40, tmpImg2);}else if (zombieptr-isSlowed) {addIce(tmpImg2, tmpImg);transparentImage(NULL, zombieptr-location, xys[zombieptr-row][0].y - 40, tmpImg2);zombieptr-changeFrameCountDown - 1;if (zombieptr-changeFrameCountDown 0) {zombieptr-changeFrameCountDown 6;zombieptr-location - 1;zombieptr-frameNo;if (zombieptr-frameNo 46) {zombieptr-frameNo 0;}}}else {transparentImage(NULL, zombieptr-location, xys[zombieptr-row][0].y - 40, tmpImg);zombieptr-changeFrameCountDown - 2;if (zombieptr-changeFrameCountDown 0) {zombieptr-changeFrameCountDown 25;zombieptr-frameNo;}}*/}// 判断是否冻住if (zombieptr-isFrozen 0){zombieptr-isFrozen--;if (zombieptr-isFrozen 0) zombieptr-isSlowed 400;transparentImage(NULL, zombieptr-location100, xys[zombieptr-row][0].y70, iceTrap); }// 判断是否减速if (zombieptr-isSlowed 0){zombieptr-isSlowed--;}// 如果僵尸走到最左边且此行有除草机if (zombieptr-location -50 lawnmowers[zombieptr-row]-isOut 0){lawnmowers[zombieptr-row]-isActivated 1;mciSendString(play lawnmower from 0, 0, 0, 0);} 如果僵尸前面有植物//NodePlant* curPlant plants.head,*pre;//while (curPlant ! NULL)//{// Plant* plant curPlant-content;// if (zombieptr-row plant-x// zombieptr-location xys[plant-x][plant-y].x- 25// zombieptr-location xys[plant-x][plant-y-1].x-25)// {// if (zombieptr-emerge1walk2eat3 2)// {// zombieptr-emerge1walk2eat3 3;// zombieptr-frameNo 0;// mciSendString(play ./Music/chomp.mp3 from 0, 0, 0, 0);// }// if (zombieptr-emerge1walk2eat3 3 zombieptr-frameNo 9)// {// zombieptr-frameNo 0;// mciSendString(play ./Music/chomp.mp3 from 0, 0, 0, 0);// plant-HP--;// if (plant-HP 0)// {// pre curPlant;// curPlant curPlant-next;// plants.DeleteNode(pre-content-No);// zombieptr-emerge1walk2eat3 2;// continue;// }// }// }// curPlant curPlant-next;//}// 如果僵尸前面有除草机if (lawnmowers[zombieptr-row]-isOut 0 zombieptr-location lawnmowers[zombieptr-row]-location - 30){next cur-next;zombies.DeleteNode(zombieptr-No);generateSunshine(zombieptr-location, xys[zombieptr-row][0].y);cur next;continue;} cur cur-next;}
}void paintSuns()
{NodeSun *cur suns.head, *next;while (cur ! NULL){Sun* sun cur-content;transparentImage(NULL, sun-x, sun-y, sunPictures[sun-frame]);sun-changeFrameCountDown--;if (sun-changeFrameCountDown 0){sun-changeFrameCountDown 5;sun-frame;if (sun-frame 22)sun-frame 0;if (sun-goToCount 1 ){sun-x sun-tempX / 10 * sun-goToCountFrame;sun-y sun-tempY / 10 * sun-goToCountFrame;sun-goToCountFrame--;if (sun-goToCountFrame 0){next cur-next;suns.DeleteNode(sun-No);cur next;currentSunshine 25;continue;}}}cur cur-next;}
}void paintBangs()
{NodeBang* cur bangs.head,*pre;while (cur ! NULL){if (cur-content-countDown 0){cur-content-countDown--;transparentImage(NULL, cur-content-x, cur-content-y, bang);}pre cur;cur cur-next; if(pre-content-countDown0)bangs.DeleteNode(pre-content-No);}
}void paintCursor()
{if (cursor Chammer){// 如果没锤画正常角度锤子if (!isHitting)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, hammer[0]);else{// 画旋转锤子transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, hammer[hammerRadius]);hammerRadius;if (hammerRadius 13){hammerRadius 0;isHitting 0;}}}else if (cursor CpotatoMine)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, potaotoMinePictures[0]);else if (cursor Ciceshroom)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, iceshroomPictures[0]);elsetransparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, gravebusterPictures[0]);
}void randomZombies()
{// 随机产生僵尸for (int i 0; i 5; i){for (int j 3; j 9; j){if (1 mapState[i][j] mapState[i][j] 8){double p rand() / (double)RAND_MAX;if (p normalfrequency){NormalZombie* normalZombie new NormalZombie();normalZombie-row i;normalZombie-location xys[i][j].x-75;zombies.InsertNode(normalZombie);mciSendString(play ./Music/dirt_rise.mp3 from 0, 0, 0, 0);}else if (normalfrequency p p coneheadfrequency){ConeheadZombie* coneheadZombie new ConeheadZombie();coneheadZombie-row i;coneheadZombie-location xys[i][j].x-75;zombies.InsertNode(coneheadZombie);mciSendString(play ./Music/dirt_rise.mp3 from 0, 0, 0, 0);}else if (coneheadfrequency p p bucketheadfrequency){BucketheadZombie* bucketheadZombie new BucketheadZombie();bucketheadZombie-row i;bucketheadZombie-location xys[i][j].x-75;zombies.InsertNode(bucketheadZombie);mciSendString(play ./Music/dirt_rise.mp3 from 0, 0, 0, 0);}}}}// 随机呻吟声double p rand() / (double)RAND_MAX;if (p groanFrequency){int px rand() % 6 1;switch (px){case 1:mciSendString(play ./Music/groan.mp3 from 0, 0, 0, 0);break;case 2:mciSendString(play ./Music/groan2.mp3 from 0, 0, 0, 0);break;case 3:mciSendString(play ./Music/groan3.mp3 from 0, 0, 0, 0);break;case 4:mciSendString(play ./Music/groan4.mp3 from 0, 0, 0, 0);break;case 5:mciSendString(play ./Music/groan5.mp3 from 0, 0, 0, 0);break;case 6:mciSendString(play ./Music/groan6.mp3 from 0, 0, 0, 0);break;}}
}void paintNames()
{// 画出存档名称getFiles(./archives);RECT rect;setbkmode(TRANSPARENT);settextcolor(RGB(222, 186, 97));if (files.size() 5){settextstyle(20, 0, 华文隶书);rect { 268, 135, 538, 335 };drawtext(存档过多请删除archives, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);rect { 268, 175, 538, 375 };drawtext(文件夹下的存档并重启!, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);}else if (files.size() 0){settextstyle(40, 0, 华文隶书);rect { 268, 159, 538, 360 };drawtext(没有存档!, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);}else{int h 189;settextstyle(35, 0, 华文隶书);for (int i 0; i files.size(); i){rect { 268, h, 538, h 40 };drawtext(files[i].c_str(), rect, DT_CENTER);h 40;}}
}void drawHint()
{if (drawingHint !0){settextcolor(WHITE);settextstyle(40, 0, 隶书);if (drawingHint 1){drawtext(此处不能种植物, rect, DT_CENTER);}else if(drawingHint 2)drawtext(阳光不足, rect, DT_CENTER);hintCountDown--;if (hintCountDown 0){hintCountDown 70;drawingHint 0;}}
}void randomGraves()
{// 随机产生墓碑while (graveNum 6 || graveNum13){graveNum 0;for (int i 0; i 5; i){int num rand() % 4;for (int j 0; j num; j){int column rand() % 6 3;if (mapState[i][column] 0){mapState[i][column] rand() % 8 1;graveNum;}else j--;}}}
}void beginGame()
{// 如果是新游戏if (isNewGame){// 随机产生墓碑randomGraves();isNewGame 0;cursor Chammer;}mciSendString(open ./Music/Loonboon.mp3 alias BGM2, 0, 0, 0);mciSendString(play BGM2 repeat, 0, 0, 0);mciSendString(play ./Music/theZombiesareComing.mp3 from 0, 0, 0, 0);while (1){// 绘图cleardevice();// 画背景、植物条、菜单、阳光数putimage(0, 0, background);putimage(0, 0, plantsBar);transparentImage(NULL, 685, 0, menu);RECT r { 8, 63, 68, 85 }; // 12, 62, 68, 84settextstyle(20, 0, 微软雅黑, 0, 0, FW_BOLD, false, false, false);settextcolor(BLACK);drawtext(itoa(currentSunshine,sunshineNum,10), r, DT_CENTER);// 画植物和墓碑paintPlantsAndGraves();// 画僵尸paintZombies();// 画除草机for (int i 0; i 5; i){if (lawnmowers[i]-isOut 0){transparentImage(NULL, lawnmowers[i]-location, xys[i][0].y 45, lawnmower);}}drawHint(); // 画提示paintSuns(); // 画太阳paintBangs(); // 画 bangpaintCursor(); // 画鼠标// 画雪花if (snowCountDown 0){snowCountDown--;transparentImage(NULL, 0, 0, snow);}FlushBatchDraw();// 计算// 除草机状态for (int i 0; i 5; i){if (lawnmowers[i]-isActivated 1){lawnmowers[i]-location 5;if (lawnmowers[i]-location 800){lawnmowers[i]-isOut 1;}}}// 如果点了鼠标while (peekmessage(mousemsg, EM_MOUSE)){ if (mousemsg.message WM_LBUTTONDOWN){if (mousemsg.x 692 mousemsg.y 0 mousemsg.x 815 mousemsg.y 44){// 如果点击了菜单,存档退出writeArchive(username);goto stopGame;}if (cursor Chammer){// 如果鼠标是锤子// 如果点了土豆雷if (mousemsg.x 86 mousemsg.y 10 mousemsg.x 133 mousemsg.y 79){if (currentSunshine 25)cursor CpotatoMine;elsedrawingHint 2;}// 如果点了墓碑吞噬者else if (mousemsg.x 145 mousemsg.y 10 mousemsg.x 191 mousemsg.y 79){if (currentSunshine 75)cursor Cgravebuster;elsedrawingHint 2;}// 如果点了寒冰菇else if (mousemsg.x 204 mousemsg.y 10 mousemsg.x 253 mousemsg.y 79){if (currentSunshine 75)cursor Ciceshroom;elsedrawingHint 2;}else{hammerRadius 0;isHitting 1;mciSendString(play ./Music/hit.mp3 from 0, 0, 0, 0);NodeZombie* cur zombies.head;while (cur ! NULL){Zombie* zombie cur-content; if (mousemsg.x zombie-location 97 mousemsg.y xys[zombie-row][0].y - 40 mousemsg.x zombie-location 164 mousemsg.y xys[zombie-row][0].y zombie-height){// 如果锤到了僵尸僵尸减血或死亡 bangs.InsertNode(new Bang(mousemsg.x - 70, mousemsg.y - 30));zombie-HP--;if (zombie-HP 0){zombies.DeleteNode(zombie-No);generateSunshine(zombie-location, xys[zombie-row][0].y);}else if (zombie-HP 1)zombie-type NORMALZOMBIE; goto skipLittleWhile;}cur cur-next;}NodeSun* curSun suns.head;while (curSun ! NULL){Sun* sun curSun-content;if (mousemsg.x sun-x 20 mousemsg.y sun-y - 18 mousemsg.x sun-x 108 mousemsg.y sun-y 80){// 如果锤中太阳curSun-content-goToCount 1;mciSendString(play ./Music/sunshine.mp3 from 0, 0, 0, 0);goto skipLittleWhile;}curSun curSun-next;}}}// 如果鼠标是植物else{int i, j, isInPlantZone 0;for (i 0; i 5; i){for (j 0; j 9; j){if (mousemsg.x xys[i][j].x mousemsg.y xys[i][j].y mousemsg.x xys[i][j].x 80 mousemsg.y xys[i][j].y 100){isInPlantZone 1;break;}}if (isInPlantZone)break;}if ((cursor ! Cgravebuster mapState[i][j] ! GRASS) || isInPlantZone 0){drawingHint 1;continue;}switch (cursor){case CpotatoMine:{currentSunshine - 25;mapState[i][j] POTATO;PotatoMine* potatoMine new PotatoMine();potatoMine-x i;potatoMine-y j;plants.InsertNode(potatoMine);mciSendString(play ./Music/plant.mp3 from 0, 0, 0, 0);break;}case Ciceshroom:{currentSunshine - 75;mapState[i][j] ICESHROOM;IceShroom* iceshroom new IceShroom();iceshroom-x i;iceshroom-y j;plants.InsertNode(iceshroom);mciSendString(play ./Music/plant.mp3 from 0, 0, 0, 0);break;}case Cgravebuster:{if (mapState[i][j] 1 || mapState[i][j]8){drawingHint 1;continue;}currentSunshine - 75;switch (mapState[i][j]){case GRAVE1:mapState[i][j] GRAVEBUSTER_GRAVE1;break;case GRAVE2:mapState[i][j] GRAVEBUSTER_GRAVE2;break;case GRAVE3:mapState[i][j] GRAVEBUSTER_GRAVE3;break;case GRAVE4:mapState[i][j] GRAVEBUSTER_GRAVE4;break;case GRAVE5:mapState[i][j] GRAVEBUSTER_GRAVE5;break;case GRAVE6:mapState[i][j] GRAVEBUSTER_GRAVE6;break;case GRAVE7:mapState[i][j] GRAVEBUSTER_GRAVE7;break;case GRAVE8:mapState[i][j] GRAVEBUSTER_GRAVE8;break;default:continue;break;}GraveBuster* gravebuster new GraveBuster();gravebuster-x i;gravebuster-y j;plants.InsertNode(gravebuster);mciSendString(play ./Music/gravebusterchomp.mp3 from 0, 0, 0, 0);break;}}cursor Chammer;}}else if(mousemsg.message WM_RBUTTONDOWN){cursor Chammer;}}//判断土豆雷是否被触发for (int i 0; i 5; i){for (int j 0; j 9; j){if (mapState[i][j] POTATOMINE){NodeZombie* curZombie zombies.head, * pre NULL;while (curZombie ! NULL){ pre curZombie;curZombie curZombie-next;if (pre-content-row i pre-content-locationxys[i][j].x - 135 pre-content-location xys[i][j].x - 20){mapState[i][j] POTATOBOOM;mciSendString(play ./Music/potato_mine.mp3 from 0, 0, 0, 0);zombies.DeleteNode(pre-content-No);}}}}}//随机产生僵尸randomZombies();//判断输赢if (graveNum 0 zombies.headNULL){Win1Lose2 1;mciSendString(play ./Music/trophy.mp3 from 0, 0, 0, 0);goto stopGame;}NodeZombie* cur zombies.head;while (cur ! NULL){if (cur-content-location -150){Win1Lose2 2;mciSendString(play ./Music/losemusic.mp3 from 0, 0, 0, 0);goto stopGame;}cur cur-next;}skipLittleWhile://延时HpSleep(15);}stopGame:mciSendString(close BGM2, 0, 0, 0);
}void loadImages(IMAGE imgs[], char path[],int n,int begin)
{for (int i 0; i n; i){char tmpPath[200], frameNo[4];strcpy_s(tmpPath, 200, path);strcat(strcat(tmpPath, itoa(i begin, frameNo, 10)), .png);loadimage(imgs[i], tmpPath);}
}void loading()
{loadImages(grave, ./graphics/GraveStones/, 8, 1);loadImages(hammer, ./graphics/Screen/hammer/hammer, 13, 1);loadImages(sunPictures, ./graphics/Plants/Sun/Sun_, 22, 0);loadImages(potaotoMinePictures, ./graphics/Plants/PotatoMine/PotatoMine/PotatoMine_, 8, 0);loadImages(iceshroomPictures, ./graphics/Plants/IceShroom/IceShroom/IceShroom_, 11, 0);loadImages(gravebusterPictures, ./graphics/Plants/GraveBuster/GraveBuster-, 28, 1);loadImages(normalZombieWalkPictures, ./graphics/Zombies/NormalZombie/Zombie/Zombie-, 47, 1);loadImages(coneheadZombieWalkPictures, ./graphics/Zombies/ConeheadZombie/ConeheadZombie/ConeheadZombie-, 47, 1);loadImages(bucketheadZombieWalkPictures, ./graphics/Zombies/BucketheadZombie/BucketheadZombie/BucketheadZombie-, 47, 1);loadImages(normalZombieEmergePictures, ./graphics/Zombies/NormalZombie/ZombieEmerge/Zombie-, 20, 1);loadImages(coneheadZombieEmergePictures, ./graphics/Zombies/ConeheadZombie/ConeheadZombieEmerge/Zombie-, 20, 1);loadImages(bucketheadZombieEmergePictures, ./graphics/Zombies/BucketheadZombie/BucketheadZombieEmerge/Zombie-, 20, 1);loadImages(normalZombieEatPictures, ./graphics/Zombies/NormalZombie/ZombieAttack/ZombieAttack_, 10, 0);loadImages(coneheadZombieEatPictures, ./graphics/Zombies/ConeheadZombie/ConeheadZombieAttack/ConeheadZombieAttack_, 10, 0);loadImages(bucketheadZombieEatPictures, ./graphics/Zombies/BucketheadZombie/BucketheadZombieAttack/BucketheadZombieAttack_, 10, 0);loadimage(potatoBoom, ./graphics/Plants/PotatoMine/PotatoMineExplode/PotatoMineExplode_0.png);loadimage(potato, ./graphics/Plants/PotatoMine/PotatoMineInit/PotatoMineInit_0.png);loadimage(plantsBar, ./graphics/Screen/ChooserBackground.png);loadimage(background, ./graphics/Screen/Background.jpg);loadimage(selectID, ./graphics/Screen/selectID.png);loadimage(iceTrap, ./graphics/Plants/IceShroom/IceShroomTrap_0.png);loadimage(snow, ./graphics/Plants/IceShroom/IceShroomSnow_0.png);loadimage(menu, ./graphics/Screen/menu.png);loadimage(lawnmower, ./graphics/Screen/lawnmower.png);loadimage(loseGame, ./graphics/Screen/lose.png);loadimage(winGame, ./graphics/Screen/win.png);loadimage(bang, ./graphics/Screen/bang.png);mciSendString(open ./Music/chomp.mp3, 0, 0, 0);mciSendString(open ./Music/dirt_rise.mp3, 0, 0, 0);mciSendString(open ./Music/gravebusterchomp.mp3, 0, 0, 0);mciSendString(open ./Music/groan.mp3, 0, 0, 0);mciSendString(open ./Music/groan2.mp3, 0, 0, 0);mciSendString(open ./Music/groan3.mp3, 0, 0, 0);mciSendString(open ./Music/groan4.mp3, 0, 0, 0);mciSendString(open ./Music/groan5.mp3, 0, 0, 0);mciSendString(open ./Music/groan6.mp3, 0, 0, 0);mciSendString(open ./Music/hit.mp3, 0, 0, 0);mciSendString(open ./Music/lawnmower.mp3 alias lawnmower, 0, 0, 0);mciSendString(open ./Music/losemusic.mp3, 0, 0, 0);mciSendString(open ./Music/plant.mp3, 0, 0, 0);mciSendString(open ./Music/potato_mine.mp3, 0, 0, 0);mciSendString(open ./Music/shoop.mp3, 0, 0, 0);mciSendString(open ./Music/theZombiesareComing.mp3, 0, 0, 0);mciSendString(open ./Music/trophy.mp3, 0, 0, 0);mciSendString(open ./Music/sunshine.mp3, 0, 0, 0);
}int main()
{srand((unsigned)time(NULL));loading(); for (int i 0; i 5; i){for (int j 0; j 9; j){xys[i][j].x 40 j * 82;xys[i][j].y 70 i * 100;//cout xys[ i ][ j ]: xys[i][j].x , xys[i][j].y endl;;}}initgraph(820, 600);BeginBatchDraw();labelBGM:mciSendString(open ./Music/Cerebrawl.mp3 alias BGM1, 0, 0, 0);mciSendString(play BGM1 repeat, 0, 0, 0);label2:cleardevice();//背景putimage(0, 0, background);//对话框if (Win1Lose2 0){transparentImage(NULL, 177, 35, selectID);paintNames();}else if (Win1Lose2 1){transparentImage(NULL, 230, 140, winGame);}else if (Win1Lose2 2){transparentImage(NULL, 230, 140, loseGame);}FlushBatchDraw();while (1){getmessage(mousemsg, EM_MOUSE);if (mousemsg.message WM_LBUTTONDOWN){cout mousemsg.x , mousemsg.y endl;if (Win1Lose2 0){if (mousemsg.x 236 mousemsg.y 436 mousemsg.x 391 mousemsg.y 474){//点击了“没有我的名字”char s[10];InputBox(s, 10, 请输入你的姓名);init();writeArchive(s);goto label2;}else if (mousemsg.x 410 mousemsg.y 438 mousemsg.x 566 mousemsg.y 473){//点击了退出存档if (strcmp(username, ) ! 0)writeArchive(username);return 0;}else if (mousemsg.x 268 mousemsg.y 190 mousemsg.x 538 mousemsg.y 385){//点击了存档位置if (190 mousemsg.y mousemsg.y 229){if (0 files.size() files.size() 6)strcpy(username, (char*)files[0].c_str());else continue;}else if (229 mousemsg.y mousemsg.y 268){if (1 files.size() files.size() 6)strcpy(username, (char*)files[1].c_str());else continue;}else if (268 mousemsg.y mousemsg.y 307){if (2 files.size() files.size() 6)strcpy(username, (char*)files[2].c_str());else continue;}else if (307 mousemsg.y mousemsg.y 346){if (3 files.size() files.size() 6)strcpy(username, (char*)files[3].c_str());else continue;}else if (346 mousemsg.y mousemsg.y 385){if (4 files.size() files.size() 6)strcpy(username, (char*)files[4].c_str());else continue;}readArchive(username);mciSendString(close BGM1, 0, 0, 0);beginGame();if (Win1Lose2 0)goto labelBGM;else goto label2;}}else{if (mousemsg.x 297 mousemsg.y 331 mousemsg.x 500 mousemsg.y 369){init();mciSendString(close BGM1, 0, 0, 0);beginGame();if (Win1Lose2 0)goto labelBGM;else goto label2;}}}}getch();EndBatchDraw();closegraph();return 0;
}素材
邮箱地址在评论区里发给我我发给你。