当前位置: 首页 > news >正文

C语言游戏实战(12):植物大战僵尸(坤版)

植物大战僵尸

前言:

本游戏使用C语言和easyx图形库编写,通过这个项目我们可以深度的掌握C语言的各种语言特性和高级开发技巧,以及锻炼我们独立的项目开发能力,

在开始编写代码之前,我们需要先了解一下游戏的基本规则和功能:

游戏界面:游戏界面是一个矩形区域,玩家可以在区域内进行植物的放置和铲除等操作。

僵尸:僵尸会从游戏界面的右侧向左测移动,靠近植物后会停下来吃植物。

植物:不同的植物有不同的功能,在这里我们可以将植物分为三大类:

1. 生产型植物(如太阳花):这种植物的特点是在一定的时间生产出太阳,以增加太阳的产量。

2.发射型植物(如豌豆射手):这种植物的特点是发射相应类型的子弹,对僵尸产生伤害和特定的效果。

3. 爆炸性植物(火爆辣椒):这种植物的特点是对一定区域的所有僵尸产生高额伤害。(一次性植物)

接下来,我们将通过以下几个步骤来实现这个游戏:

初始化游戏界面。

实现僵尸的创建、僵尸的更新、僵尸吃植物的检测。

实现的植物的放置。

实现植物的功能:

对于生产型植物我们需要写出阳光的生产,以及阳光的收集操作。

对于发射型植物我们需要判断植物是否发射子弹,发射子弹后还需更新子弹、检测子弹与僵尸的碰撞。

对于爆炸型植物,我们需要判断僵尸是否在爆炸范围内,然后杀死在爆炸范围内的僵尸。

1. 初始化游戏界面

我们需要先将游戏地图、卡牌和卡牌槽绘制出来。可以利用windows自带的画图工具测出游戏地图的位置,从而将这些卡牌和卡牌槽放置到合适的位置。

//地图
putimage(-150, 0, &img);
//卡牌槽
putimagePNG(80, -10, &imgBar);	
//植物卡牌for (int i = 0; i < PLANT_COUNT + 2; i++){if(i==PLANT_COUNT)putimagePNG(163 + i * 65 + 8, -5, &imgCards[i]);elseputimagePNG(163 + i * 65, 0, &imgCards[i]);}

2.  放置植物

因为需要在这个9*5的草地区域内放置植物,所以我们得计算出每个草方块的位置。我利用画图软件测出每个草方块大约是长81、宽100个像素点。 第一个草方块距离游戏窗口大约101个像素点。

这样就可以得出每个草方块的位置:256 - 150 + col * 81;100 + row * 100 - 15; 

每个植物都有相似的特性,所以我们需要写一个放置植物信息的结构体。然后创建一个5*9的结构体数组,用来表示每个草方块上的植物。

enum {WAN_DOU, TAI_YANG, LA_JIAO, KUN_KUN, JIAN_GUO,HAN_BING_WAN_DOU, YING_TAO, SAN_TOU_WAN_DOU, PLANT_COUNT
};
struct plant
{int type;//植物类型int frameIndex;//植物动作帧//bool catched;//是否被吃int blood;//血量int shootTime;//植物子弹的射速int timer;//阳光生产的时间int x, y;//植物坐标bool shoot;//判断植物是否处于发射状态
};
struct plant map[5][9];

 在 Windows 编程中,我们可以利用下面的变量获取鼠标信息。

ExMessage msg;
msg.message
ExMessage msg;
static int status = 0;
if (peekmessage(&msg))//判断有没有消息
{if (msg.message == WM_LBUTTONDOWN)//左键按下{//鼠标是否在卡牌的位置按下if (msg.x > 163 && msg.x < 163 + 65 * (PLANT_COUNT+2) && msg.y < 96){//mciSendString("play res/audio/bleep.mp3 alias BGM4", NULL, NULL, NULL);PlaySound("res/audio/bleep.wav", NULL, SND_FILENAME | SND_ASYNC);//PlaySound("res/sunshine.wav", NULL, SND_FILENAME | SND_ASYNC);int index = (msg.x - 163) / 65;//坤坤/*	if (index + 1 == KUN_KUN && sunshine >= 100){curPlant = index + 1;status = 1;curX = msg.x;curY = msg.y;sunshine -= 100;}*/curPlant = index + 1;status = 1;curX = msg.x;curY = msg.y;}}else if (msg.message == WM_MOUSEMOVE && status == 1)//鼠标移动{curX = msg.x;curY = msg.y;}else if (msg.message == WM_LBUTTONUP)//鼠标放下{if (msg.x > 256 - 150 && msg.x < Wide - 70 && msg.y > 100 && msg.y < 590){int row = (msg.y - 100) / 102;int col = (msg.x - 256 + 150 ) / 81;if (map[row][col].type == 0 && curPlant != PLANT_COUNT + 1 && curPlant != PLANT_COUNT + 2){//printf("%d\n", map[col][row].type);map[row][col].type = curPlant;map[row][col].frameIndex = 0;if(curPlant!=0)PlaySound("res/audio/coffee.wav", NULL, SND_FILENAME | SND_ASYNC);if (curPlant == 5)map[row][col].blood = KUNKUN_BLOOD * 50;elsemap[row][col].blood = KUNKUN_BLOOD;map[row][col].shootTime = 0;map[row][col].shoot = false;map[row][col].x = 256 - 150 + col * 81;map[row][col].y = 100 + row * 100 - 15;}else if (map[row][col].type != 0 && curPlant == PLANT_COUNT + 1){PlaySound("res/audio/coffee.wav", NULL, SND_FILENAME | SND_ASYNC);map[row][col].type = 0;map[row][col].blood = 0;}}}else if (msg.message == WM_RBUTTONDOWN)//鼠标右键{curPlant = 0;status = 0;}

3. 僵尸

 3.1 创建僵尸

僵尸也是和植物一样需要创建一个结构体存放信息。然后创建一个结构体数组,作为一个僵尸池,当需要创建一个僵尸时,我们就从这个池里取一个未被使用的僵尸。

struct zm
{int x, y;//僵尸的坐标int frameIndex;//僵尸动作帧bool used;//僵尸是否被使用int speed;//僵尸每一次移动的位移int row;//僵尸所在行int blood;//僵尸血量bool dead;//僵尸是否死亡bool eating;//僵尸是否在吃植物bool boom;//僵尸是否被炸死int zmSpeed;//僵尸的移动快慢
};
struct zm zms[ZM_MAX];
//找一个可用的僵尸
int i;
for (i = 0; i < zmMax && zms[i].used && zms[i].dead == false; i++);

到一定的时间就创建一个僵尸。


void createZM()
{if (zmCount >= zmCount_max)return;static int zmFre = 500;static int count = 0;//控制僵尸的生成快慢count++;if (count > zmFre){count = 0;zmFre = 200;int i = 0;int zmMax = sizeof(zms) / sizeof(zms[0]);for (i = 0; i < zmMax && zms[i].used && zms[i].dead == false; i++);if (i < zmMax){memset(&zms[i], 0, sizeof(zms[i]));zms[i].used = true;zms[i].speed = 2;zms[i].row = rand() % 5;zms[i].y = 100 + (zms[i].row) * 100 + 70;zms[i].x = Wide;zms[i].blood = ORDINARY_ZM_BLOOD;zms[i].dead = false;zms[i].boom = false;zms[i].zmSpeed = 4;zmCount++;}}
}

3. 2 检测僵尸对植物的伤害检测

僵尸靠近植物就将僵尸置为吃东西的状态,减植物的血量,当植物的血量小于等于0时,就去除植物。

void checkZM2Zhiwu()
{char name[64];int zCount = sizeof(zms) / sizeof(zms[0]);for (int i = 0; i < zCount; i++){//killCount = 0;if (zms[i].dead)continue;//zms[i].chomptime = 0;int row = zms[i].row;for (int j = 0; j < 9; j++){//if (map[row][j].type == 0)continue;//int zhiwuX = 101 + j * 81;int x1 = zhiwuX;int x2 = zhiwuX + 81;int x3 = zms[i].x + 100;if (x3 >= x1 && x3 <= x2){if (map[row][j].blood <= 0 || (map[row][j].type == 0 && zms[i].eating != false)){map[row][j].blood = 0;map[row][j].type = 0;zms[i].eating = false;//zms[i].frameIndex = 0;zms[i].speed = 3;}else if (map[row][j].type != 0){//mciSendString("play ZM_BGM repeat", NULL, NULL, NULL);//mciSendString("play name repeat", NULL, 0, NULL);zms[i].eating = true;zms[i].speed = 0;if (map[row][j].type != 3 && map[row][j].type != 7)map[row][j].blood--;//zms[i].frameIndex = 0;}}else if (x3 > 830){zms[i].eating = false;zms[i].speed = 3;}}}
}

4. 植物子弹

4.1 发射子弹

当僵尸出现在游戏界面时,与该僵尸同一行的发射性植物就发射出子弹。

同样需要创建一个结构体存放子弹的信息,然后创建一个子弹池。

//子弹
struct bullet
{double x, y;//子弹的坐标bool used;//子弹是否被使用int row;//子弹所在行int speed;//子弹速度bool blast;//是否发生爆炸int frameIndex;//帧序号
};
//坤坤
struct bullet bullets[1000];

 以坤坤为例:

void shoot()
{int lines[5] = { 0 };int bulletMax = sizeof(bullets) / sizeof(bullets[0]);int zmCount = sizeof(zms) / sizeof(zms[0]);int dangerX = Wide - 80;for (int i = 0; i < zmCount; i++){if (zms[i].dead == false && zms[i].x < dangerX && zms[i].x>100){lines[zms[i].row] = 1;}}for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){//坤坤if (map[i][j].type == KUN_KUN + 1 && lines[i]){map[i][j].shootTime++;if (map[i][j].shootTime > 20){map[i][j].shootTime = 0;//子弹池int k;for (k = 0; k < bulletMax && bullets[k].used; k++);if (k < bulletMax){map[i][j].frameIndex = 3;bullets[k].used = true;bullets[k].row = i;bullets[k].speed = 10;bullets[k].blast = false;bullets[k].frameIndex = 0;int zwX = 256 - 150 + j * 81;int zwY = 100 + i * 100 - 15;bullets[k].x = zwX + imgPlant[map[i][j].type - 1][0]->getwidth() - 10;bullets[k].y = zwY + 5;}}}}}
}

4. 2  更新子弹

不断的改变加子弹的横坐标,当子弹出游戏界面时,子弹就被置为未被使用。

以坤坤为例:

void updateBullets_kunkun()
{int countMax = sizeof(bullets) / sizeof(bullets[0]);for (int i = 0; i < countMax; i++){if (bullets[i].used){bullets[i].x += bullets[i].speed;if (bullets[i].x > Wide){bullets[i].used = false;}}}
}

 4.3 检测子弹对僵尸的伤害

当子弹靠近僵尸时减去僵尸的一定量血量,然后对僵尸造成一定的效果(例如,坤坤子弹的效果是击退僵尸,那么我们只需要更改僵尸的横坐标即可。),最后将子弹置为未被使用。

以坤坤为例:

void checkBullet2Zm_kunkun()
{int bCount = sizeof(bullets) / sizeof(bullets[0]);int zCount = sizeof(zms) / sizeof(zms[0]);for (int i = 0; i < bCount; i++){{for (int j = 0; j < zCount; j++){if (zms[j].used == false)continue;int x1 = zms[j].x + 80;int x2 = zms[j].x + 110;int x = bullets[i].x;if (zms[j].dead == false &&bullets[i].row == zms[j].row && x > x1 && x < x2 && bullets[i].used) {zms[j].blood -= 20;zms[j].x += 1;bullets[i].blast = true;bullets[i].speed = 0;//bullets[i].x = 0;if (zms[j].blood <= 0){killCount++;zms[j].dead = true;zms[j].speed = 0;zms[j].frameIndex = 0;}break;}}}}
}

 5. 爆炸性植物

爆炸性植物是一次性的,当植物的动作帧执行完最后一帧后植物就置为死亡,在爆炸范围内的僵尸也死亡。

以火爆辣椒为例:

void checkBoom2Zm()
{int zCount = sizeof(zms) / sizeof(zms[0]);for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){//火爆辣椒else if (map[i][j].type == LA_JIAO + 1){if (map[i][j].frameIndex > 7){for (int k = 0; k < zCount; k++){if (zms[k].used == false)continue;if (zms[k].row == i && zms[k].x < Wide - 80 - 70 && zms[k].dead == false){killCount++;zms[k].boom = true;zms[k].dead = true;zms[k].speed = 0;zms[k].frameIndex = 0;zms[k].blood = 0;}}if (map[i][j].frameIndex > 14){map[i][j].type = 0;map[i][j].frameIndex = 0;}}}}}
}

6. 小推车

 创建存放小车信息的结构体数组,小推车一条路一辆共5辆,所以我们只需写一个大小为5的结构体数组即可。

//小推车
struct car
{bool move;//是否处于移动状态int x, y;//位置bool used;//是否被使用
};
struct car cars[5];

放置小推车 

	for (int i = 0; i < 5; i++){cars[i].x = 50;cars[i].y = 100 + i * 100 - 15;cars[i].used = true;cars[i].move = false;}

检测小推车对小车的伤害 

当僵尸的横坐标小于等于小推车最左端的坐标时,小车置为移动状态,处于小推车左边的僵尸死亡。

void checkcars2Zm()
{for (int i = 0; i < 5; i++){int carsX = cars[i].x + 70;for (int j = 0; j < ZM_MAX; j++){if (zms[j].used && zms[j].dead == false && zms[j].row == i){int zmX = zms[j].x + 80;if (carsX > zmX && cars[i].used){if (cars[i].move == false)cars[i].move = true;else{killCount++;zms[j].dead = true;zms[j].speed = 0;zms[j].frameIndex = 0;}}}}}
}

更新小推车的位置

当小车被置为移动时,小推车开始移动。

void updatecar()
{for (int i = 0; i < 5; i++){if (cars[i].move){cars[i].x += 20;}if (cars[i].x > Wide){cars[i].move = false;cars[i].used = false;}}
}

源码:

test.cpp文件: 

#include"game.h"//判断文件是否存在
bool fileExist(const char* name)
{FILE* pf = fopen(name, "r");if (pf == NULL){return false;}else{fclose(pf);return true;}
}//初始化豌豆子弹的帧图片数组
void bulletsInit()
{//坤坤篮球loadimage(&imgBulletNormal, "res/bullets/basketball.png", 40, 40);memset(bullets, 0, sizeof(bullets));//初始化豌豆子弹的帧图片数组loadimage(&imgBallBlast[3], "res/bullets/PeaNormalExplode/PeaNormalExplode_0.png");for (int i = 0; i < 3; i++){float k = (i + 1) * 0.2;loadimage(&imgBallBlast[i], "res/bullets/PeaNormalExplode/PeaNormalExplode_0.png",imgBallBlast[3].getwidth() * k,imgBallBlast[3].getheight() * k, true);}//豌豆子弹loadimage(&imgBulletNormal_wandou, "res/bullets/bullet_normal.png");memset(bullets_wandou, 0, sizeof(bullets_wandou));//初始化豌豆子弹的帧图片数组loadimage(&imgBallBlast_wandou[3], "res/bullets/PeaNormalExplode/PeaNormalExplode_0.png");for (int i = 0; i < 3; i++){float k = (i + 1) * 0.2;loadimage(&imgBallBlast_wandou[i], "res/bullets/PeaNormalExplode/PeaNormalExplode_0.png",imgBallBlast_wandou[3].getwidth() * k,imgBallBlast_wandou[3].getheight() * k, true);}//寒冰豌豆子弹loadimage(&imgBulletNormal_hanbing, "res/bullets/PeaIce/PeaIce_0.png");memset(bullets_hanbing, 0, sizeof(bullets_hanbing));//初始化豌豆子弹的帧图片数组loadimage(&imgBallBlast_hanbing[3], "res/bullets/PeaNormalExplode/PeaNormalExplode_0.png");for (int i = 0; i < 3; i++){float k = (i + 1) * 0.2;loadimage(&imgBallBlast_hanbing[i], "res/bullets/PeaNormalExplode/PeaNormalExplode_0.png",imgBallBlast_hanbing[3].getwidth() * k,imgBallBlast_hanbing[3].getheight() * k, true);}//三头豌豆子弹loadimage(&imgBulletNormal_santou, "res/bullets/bullet_normal.png");memset(bullets_santou, 0, sizeof(bullets_santou));//初始化豌豆子弹的帧图片数组loadimage(&imgBallBlast_santou[3], "res/bullets/PeaNormalExplode/PeaNormalExplode_0.png");for (int i = 0; i < 3; i++){float k = (i + 1) * 0.2;loadimage(&imgBallBlast_santou[i], "res/bullets/PeaNormalExplode/PeaNormalExplode_0.png",imgBallBlast_santou[3].getwidth() * k,imgBallBlast_santou[3].getheight() * k, true);}
}void gameInit()
{char name[64];//音效mciSendString("open res/bg.mp3 alias BGM", NULL, NULL, NULL);mciSendString("open res/audio/UraniwaNi.mp3 alias BGM2", NULL, NULL, NULL);mciSendString("open res/audio/WateryGraves.mp3 alias BGM3", NULL, NULL, NULL);mciSendString("open res/audio/readysetplant.mp3 alias BGM4", NULL, NULL, NULL);mciSendString("open res/audio/chomp.mp3 alias ZM_BGM", NULL, NULL, NULL);loadimage(&img, "res/map/map0.jpg");loadimage(&imgBar, "res/bar5.png");//loadimage(&imgnotify, "res/screen/PanelBackground.png");memset(imgPlant, 0, sizeof(imgPlant));memset(map, 0, sizeof(map));memset(cars, 0, sizeof(cars));//开场动画for (int i = 0; i < 29; i++){sprintf_s(name, sizeof(name), "res/yuanshen/%d.png", i + 1);loadimage(&imgopena[i], name, 1196, 670);}//植物卡牌for (int i = 0; i < PLANT_COUNT + 2; i++){sprintf_s(name, sizeof(name), "res/Cards/card_%d.png", i + 1);loadimage(&imgCards[i], name,64,89);for (int j = 0; j < 20; j++){sprintf_s(name, sizeof(name), "res/zhiwu/%d/%d.png",i , j + 1);//先判断文件是否存在if (fileExist(name)){imgPlant[i][j] = new IMAGE;if (i != 3){loadimage(imgPlant[i][j], name);}else{loadimage(imgPlant[i][j], name,65,100);}}else{break;}}}memset(balls, 0, sizeof(balls));for (int i = 0; i < 29; i++){sprintf_s(name, sizeof(name), "res/sunshine/%d.png", i + 1);loadimage(&imgSunshineBall[i], name);}curPlant = 0;sunshine = 50;initgraph(Wide, Hight);//设置字体LOGFONT f;gettextstyle(&f);f.lfHeight = 30;f.lfWeight = 15;strcpy(f.lfFaceName, "Segoe UI Black");f.lfQuality = ANTIALIASED_QUALITY;//抗锯齿效果settextstyle(&f);setbkmode(TRANSPARENT);//字体透明setcolor(BLACK);//初始化子弹的帧图片数组bulletsInit();//初始化僵尸数据memset(zms, 0, sizeof(zms));for (int i = 0; i < 22; i++){sprintf_s(name, sizeof(name), "res/zm/%d.png", i + 1);loadimage(&imgZm[i], name);}killCount = 0;zmCount = 0;gameStatus = GOING;//初始化僵尸for (int i = 0; i < 38; i++){sprintf_s(name, sizeof(name), "res/zm_dead/%d.png",i + 1);loadimage(&imgZMDead[i], name);}for (int i = 0; i < 21; i++){sprintf_s(name, sizeof(name), "res/zm_eat/%d.png", i + 1);loadimage(&imgZMEat[i], name);}for (int i = 0; i < 11; i++){sprintf_s(name, sizeof(name), "res/zm_stand/%d.png", i + 1);loadimage(&imgZmStand[i], name);}for (int i = 0; i < 20; i++){sprintf_s(name, sizeof(name), "res/zm_dead2/%d.png", i + 1);loadimage(&imgzmboom[i], name);}//小推车loadimage(&imgcar, "res/Screen/car.png");for (int i = 0; i < 5; i++){cars[i].x = 50;cars[i].y = 100 + i * 100 - 15;cars[i].used = true;cars[i].move = false;}//StartButtonloadimage(&imgready, "res/Screen/Boom.png");
}void drawZm()
{int zmCount = sizeof(zms) / sizeof(zms[0]);for (int i = 0; i < zmCount; i++){if (zms[i].used){//IMAGE* img = (zms[i].dead) ? &imgZMDead[zms[i].frameIndex] : &imgZm[zms[i].frameIndex];IMAGE* img = NULL;if (zms[i].dead){if (zms[i].boom == true)img = &imgzmboom[zms[i].frameIndex];elseimg = &imgZMDead[zms[i].frameIndex];}else if (zms[i].eating) img = &imgZMEat[zms[i].frameIndex];else img = &imgZm[zms[i].frameIndex];putimagePNG(zms[i].x, zms[i].y - img->getheight(), img);}}
}void drawSunshine()
{int ballMax = sizeof(balls) / sizeof(balls[0]);for (int i = 0; i < ballMax; i++){//if (balls[i].used || balls[i].xoff)if(balls[i].used){IMAGE* img = &imgSunshineBall[balls->frameIndex];//putimagePNG(balls[i].x, balls[i].y, img);putimagePNG(balls[i].pCur.x, balls[i].pCur.y, img);}}
}void drawBullets_kunkun()
{int bulletsMax = sizeof(bullets) / sizeof(bullets[0]);for (int i = 0; i < bulletsMax; i++){if (bullets[i].used) {if (bullets[i].blast) {IMAGE* img = &imgBallBlast[bullets[i].frameIndex];putimagePNG(bullets[i].x, bullets[i].y - 10, img);}else {putimagePNG(bullets[i].x, bullets[i].y, &imgBulletNormal);}}}
}void drawBullets_wandou()
{int bulletsMax = sizeof(bullets_wandou) / sizeof(bullets_wandou[0]);for (int i = 0; i < bulletsMax; i++){if (bullets_wandou[i].used) {if (bullets_wandou[i].blast) {IMAGE* img = &imgBallBlast_wandou[bullets_wandou[i].frameIndex];putimagePNG(bullets_wandou[i].x, bullets_wandou[i].y, img);}else {putimagePNG(bullets_wandou[i].x, bullets_wandou[i].y, &imgBulletNormal_wandou);}}}
}void drawBullets_hanbing()
{int bulletsMax = sizeof(bullets_hanbing) / sizeof(bullets_hanbing[0]);for (int i = 0; i < bulletsMax; i++){if (bullets_hanbing[i].used) {if (bullets_hanbing[i].blast) {IMAGE* img = &imgBallBlast_hanbing[bullets_hanbing[i].frameIndex];putimagePNG(bullets_hanbing[i].x, bullets_hanbing[i].y, img);}else {putimagePNG(bullets_hanbing[i].x, bullets_hanbing[i].y, &imgBulletNormal_hanbing);}}}
}void drawBullets_santou()
{int bulletsMax = sizeof(bullets_santou) / sizeof(bullets_santou[0]);for (int i = 0; i < bulletsMax; i++){if (bullets_santou[i].used) {if (bullets_santou[i].blast) {IMAGE* img = &imgBallBlast_santou[bullets_santou[i].frameIndex];putimagePNG(bullets_santou[i].x, bullets_santou[i].y, img);}else {putimagePNG(bullets_santou[i].x, bullets_santou[i].y, &imgBulletNormal_santou);}}}
}void drawBullets()
{//坤坤drawBullets_kunkun();//豌豆drawBullets_wandou();//寒冰豌豆drawBullets_hanbing();//三头豌豆drawBullets_santou();
}void show()//渲染游戏画面
{BeginBatchDraw();putimage(-150, 0, &img);putimagePNG(80, -10, &imgBar);char scoreText[8];char scoreText1[16];sprintf_s(scoreText, sizeof(scoreText), "%d", sunshine);sprintf_s(scoreText1, sizeof(scoreText1), "Wave %d zombies", wava_count);//sprintf_s(name, sizeof(name), "res/yuanshen/%d.png", i + 1);outtextxy(105, 60, scoreText);outtextxy(700, 570, scoreText1);//outtextxy(700, 570, "s");//小推车for (int i = 0; i < 5; i++){if(cars[i].used)putimagePNG(cars[i].x, cars[i].y, &imgcar);}//植物卡牌for (int i = 0; i < PLANT_COUNT + 2; i++){if(i==PLANT_COUNT)putimagePNG(163 + i * 65 + 8, -5, &imgCards[i]);elseputimagePNG(163 + i * 65, 0, &imgCards[i]);}//植物for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){if (map[i][j].type > 0){/*int x = 256 - 150 + j * 81;int y = 100 + i * 100 - 15;*/int PlantType = map[i][j].type - 1;int index = map[i][j].frameIndex;if (map[i][j].type != 4 && map[i][j].type != YING_TAO + 1 && map[i][j].type != LA_JIAO + 1){putimagePNG(map[i][j].x, map[i][j].y, imgPlant[PlantType][index]);}else if (map[i][j].type == YING_TAO + 1){if (index == 8)putimagePNG(map[i][j].x - 75, map[i][j].y-35, imgPlant[PlantType][index]);elseputimagePNG(map[i][j].x - 22, map[i][j].y, imgPlant[PlantType][index]);}else if (map[i][j].type == LA_JIAO + 1){if (index > 7)putimagePNG(100, map[i][j].y - 35, imgPlant[PlantType][index]);elseputimagePNG(map[i][j].x, map[i][j].y, imgPlant[PlantType][index]);}else{putimagePNG(map[i][j].x + 5, map[i][j].y - 20, imgPlant[PlantType][index]);}}}}//渲染子弹drawBullets();//铲子if (curPlant != PLANT_COUNT + 1){IMAGE* img = imgPlant[8][0];putimagePNG(163 + 8 * 65 + 8, 0, img);}//僵尸drawZm();//渲染拖动中的植物if (curPlant > 0){IMAGE* img = imgPlant[curPlant - 1][0];putimagePNG(curX - img->getwidth() / 2, curY - img->getheight() / 2, img);}//渲染阳光drawSunshine();EndBatchDraw();
}void collectSunshine(ExMessage* msg)
{int count = sizeof(balls) / sizeof(balls[0]);int w = imgSunshineBall[0].getwidth();int h = imgSunshineBall[0].getheight();for (int i = 0; i < count; i++){if (balls[i].used){//int x = balls[i].x;//int y = balls[i].y;int x = balls[i].pCur.x;int y = balls[i].pCur.y;if (msg->x > x && msg->x<x + w&& msg->y>y && msg->y < y + h){sunshine += 25;//balls[i].used = false;balls[i].status = SUNSHINE_COLLECT;//音效//mciSendString("play res/sunshine.mp3", 0, 0, 0);//不支持MP3格式PlaySound("res/sunshine.wav", NULL, SND_FILENAME | SND_ASYNC);balls[i].p1 = balls[i].pCur;balls[i].p4 = vector2(100, 0);balls[i].t = 0;float distance = dis(balls[i].p1 - balls[i].p4);float off = 8;balls[i].speed = 1.0 / (distance / off);break;/*float destX = 0;float destY = 262;float angle = atan((y - destY) / (x - destX));balls[i].xoff = 4 * cos(angle);balls[i].yoff = 4 * sin(angle);*/}}}
}void userClick()
{ExMessage msg;static int status = 0;if (peekmessage(&msg))//判断有没有消息{if (msg.message == WM_LBUTTONDOWN)//左键按下{if (msg.x > 163 && msg.x < 163 + 65 * (PLANT_COUNT+2) && msg.y < 96){//mciSendString("play res/audio/bleep.mp3 alias BGM4", NULL, NULL, NULL);PlaySound("res/audio/bleep.wav", NULL, SND_FILENAME | SND_ASYNC);//PlaySound("res/sunshine.wav", NULL, SND_FILENAME | SND_ASYNC);int index = (msg.x - 163) / 65;//坤坤/*	if (index + 1 == KUN_KUN && sunshine >= 100){curPlant = index + 1;status = 1;curX = msg.x;curY = msg.y;sunshine -= 100;}*/curPlant = index + 1;status = 1;curX = msg.x;curY = msg.y;}else{collectSunshine(&msg);}}else if (msg.message == WM_MOUSEMOVE && status == 1)//鼠标移动{curX = msg.x;curY = msg.y;}else if (msg.message == WM_LBUTTONUP)//鼠标放下{if (msg.x > 256 - 150 && msg.x < Wide - 70 && msg.y > 100 && msg.y < 590){int row = (msg.y - 100) / 102;int col = (msg.x - 256 + 150 ) / 81;if (map[row][col].type == 0 && curPlant != PLANT_COUNT + 1 && curPlant != PLANT_COUNT + 2){//printf("%d\n", map[col][row].type);map[row][col].type = curPlant;map[row][col].frameIndex = 0;if(curPlant!=0)PlaySound("res/audio/coffee.wav", NULL, SND_FILENAME | SND_ASYNC);if (curPlant == 5)map[row][col].blood = KUNKUN_BLOOD * 50;elsemap[row][col].blood = KUNKUN_BLOOD;map[row][col].shootTime = 0;map[row][col].shoot = false;map[row][col].x = 256 - 150 + col * 81;map[row][col].y = 100 + row * 100 - 15;}else if (map[row][col].type != 0 && curPlant == PLANT_COUNT + 1){PlaySound("res/audio/coffee.wav", NULL, SND_FILENAME | SND_ASYNC);map[row][col].type = 0;map[row][col].blood = 0;}else if (curPlant == PLANT_COUNT + 2){if (zmCount >= ZM_MAX)return;int i = 0;int zmMax = sizeof(zms) / sizeof(zms[0]);for (i = 0; i < zmMax && zms[i].used; i++);if (i < zmMax){PlaySound("res/audio/coffee.wav", NULL, SND_FILENAME | SND_ASYNC);memset(&zms[i], 0, sizeof(zms[i]));zms[i].used = true;zms[i].speed = 2;zms[i].row = row;zms[i].y = 100 + (zms[i].row) * 100 + 70;zms[i].x = 256 - 150 + (col - 1) * 81;zms[i].blood = ORDINARY_ZM_BLOOD;zms[i].dead = false;zms[i].boom = false;zms[i].zmSpeed = 4;zmCount++;}}}}else if (msg.message == WM_RBUTTONDOWN){curPlant = 0;status = 0;}}
}void createSunshine()
{static int count = 0;static int fre = 200;count++;if (count >= fre){fre = 200 + rand() % 200;count = 0;//从阳光池取一个可以使用的int ballMax = sizeof(balls) / sizeof(balls[0]);int i;for (i = 0; i < ballMax && balls[i].used; i++);if (i >= ballMax)return;balls[i].used = true;balls[i].frameIndex = 0;/*	balls[i].x = 160 + rand() % 600;balls[i].y = 60;balls[i].destY = (rand() % 4) * 90 + 160;*/balls[i].timer = 0;/*	balls[i].xoff = 0;balls[i].yoff = 0;*/balls[i].status = SUNSHINE_DOWN;balls[i].t = 0;balls[i].p1 = vector2(160 + rand() % 600, 60);balls[i].p4 = vector2(balls[i].p1.x, (rand() % 4) * 90 + 160);int off = 2;float distance = balls[i].p4.y - balls[i].p1.y;balls[i].speed = 1.0 / (distance / off);}int ballMax = sizeof(balls) / sizeof(balls[0]);//向日葵生产阳光for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){if (map[i][j].type == TAI_YANG + 1){map[i][j].timer++;if (map[i][j].timer > 100){map[i][j].timer = 0;int k;for (k = 0; k < ballMax && balls[k].used; k++);if (k >= ballMax)return;balls[k].used = true;balls[k].p1 = vector2(map[i][j].x, map[i][j].y);int w = (40 + rand() % 50) * (rand() % 2 ? 1 : -1);balls[k].p4 = vector2(map[i][j].x + w,map[i][j].y + imgPlant[TAI_YANG][0]->getheight() - imgSunshineBall[0].getheight());balls[k].p2 = vector2(balls[k].p1.x + w * 0.3, balls[k].p1.y - 100);balls[k].p3 = vector2(balls[k].p1.x + w * 0.7, balls[k].p1.y - 100);balls[k].status = SUNSHINE_RPODUCT;balls[k].speed = 0.05;balls[k].t = 0;}}}}}void updatSunshine()
{int ballMax = sizeof(balls) / sizeof(balls[0]);for (int i = 0; i < ballMax; i++){if (balls[i].used){balls[i].frameIndex = (balls[i].frameIndex + 1) % 29;if (balls[i].status == SUNSHINE_DOWN){struct sunshineBall* sun = &balls[i];sun->t += sun->speed;sun->pCur = sun->p1 + sun->t * (sun->p4 - sun->p1);if (sun->t >= 1){sun->status = SUNSHINE_GROUND;sun->timer = 0;}}else if (balls[i].status == SUNSHINE_GROUND){balls[i].timer++;if (balls[i].timer > 100){balls[i].used = false;balls[i].timer = 0;}}else if (balls[i].status == SUNSHINE_COLLECT){struct sunshineBall* sun = &balls[i];sun->t += sun->speed;sun->pCur = sun->p1 + sun->t * (sun->p4 - sun->p1);if (sun->t > 1){sun->used = false;sunshine += 25;}}else if (balls[i].status == SUNSHINE_RPODUCT){struct sunshineBall* sun = &balls[i];sun->t += sun->speed;sun->pCur = calcBezierPoint(sun->t,sun->p1, sun->p2, sun->p3, sun->p4);if (sun->t > 1){sun->status = SUNSHINE_GROUND;sun->timer = 0;}}}}
}int mciZmTime = 0;
void createZM()
{if (zmCount >= zmCount_max)return;static int zmFre = 5000000;static int count = 0;count++;if (count > zmFre){if (mciZmTime == 0){mciSendString("play res/audio/awooga.mp3", 0, 0, 0);mciZmTime++;}count = 0;zmFre = 202 - 20 * wava_count;int i = 0;int zmMax = sizeof(zms) / sizeof(zms[0]);for (i = 0; i < zmMax && zms[i].used && zms[i].dead == false; i++);if (i < zmMax){memset(&zms[i], 0, sizeof(zms[i]));zms[i].used = true;zms[i].speed = 2;zms[i].row = rand() % 5;zms[i].y = 100 + (zms[i].row) * 100 + 70;zms[i].x = Wide;zms[i].blood = ORDINARY_ZM_BLOOD;zms[i].dead = false;zms[i].boom = false;zms[i].zmSpeed = 4;zmCount++;}}
}int zmSpeed = 6;
void updateZM()
{int zmMax = sizeof(zms) / sizeof(zms[0]);static int count[ZM_MAX] = { 0 };//更新僵尸的位置for (int i = 0; i < zmMax; i++){count[i]++;if (count[i] >= (gameStatus == GOING ? zms[i].zmSpeed : zmSpeed)){//printf("%d ", (gameStatus == GOING ? zms[i].zmSpeed : zmSpeed));count[i] = 0;if (zms[i].used){if (zms[i].dead){zms[i].frameIndex++;if (zms[i].boom == true){if (zms[i].frameIndex >= 20){//printf("%d ", killCount);zms[i].used = false;zms[i].row = 0;//killCount++;if (killCount >= ZM_MAX)gameStatus = WIN;else if (killCount >= zmCount_max){wava_count++;zmCount_max *= 2;killCount = 0;zmCount = 0;}}}else{if (zms[i].frameIndex >= 38){//printf("%d ", killCount);zms[i].used = false;zms[i].row = 0;if (killCount >= ZM_MAX)gameStatus = WIN;else if (killCount >= zmCount_max){wava_count++;zmCount_max *= 2;killCount = 0;zmCount = 0;}}}}else if (zms[i].eating){//mciSendString("play res/audio/chomp.mp3", 0, 0, 0);//mciSendString("play res/audio/chompsoft.mp3", 0, 0, 0);zms[i].frameIndex = (zms[i].frameIndex + 1) % 21;}else{zms[i].frameIndex++;if (zms[i].frameIndex >= 22){zms[i].frameIndex = 0;}}zms[i].x -= zms[i].speed;if (zms[i].x < 0){//printf("GAME OVER\n");//MessageBox(NULL, "over", "over", 0);//待优化//exit(0);//待优化gameStatus = FAIL;}}}}
}void shoot()
{int lines[5] = { 0 };int bulletMax = sizeof(bullets) / sizeof(bullets[0]);int bulletMax_wandou = sizeof(bullets_wandou) / sizeof(bullets_wandou[0]);int bulletMax_hanbing = sizeof(bullets_hanbing) / sizeof(bullets_hanbing[0]);int bulletMax_santou = sizeof(bullets_santou) / sizeof(bullets_santou[0]);int zmCount = sizeof(zms) / sizeof(zms[0]);int dangerX = Wide - 80;for (int i = 0; i < zmCount; i++){if (zms[i].dead == false && zms[i].x < dangerX && zms[i].x>100){lines[zms[i].row] = 1;}}for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){//坤坤if (map[i][j].type == KUN_KUN + 1 && lines[i]){map[i][j].shootTime++;if (map[i][j].shootTime > 20){map[i][j].shootTime = 0;int k;for (k = 0; k < bulletMax && bullets[k].used; k++);if (k < bulletMax){map[i][j].frameIndex = 3;bullets[k].used = true;bullets[k].row = i;bullets[k].speed = 10;bullets[k].blast = false;bullets[k].frameIndex = 0;int zwX = 256 - 150 + j * 81;int zwY = 100 + i * 100 - 15;bullets[k].x = zwX + imgPlant[map[i][j].type - 1][0]->getwidth() - 10;bullets[k].y = zwY + 5;}}}//豌豆else if (map[i][j].type == WAN_DOU + 1 && lines[i]){map[i][j].shootTime++;if (map[i][j].shootTime > 35){map[i][j].shootTime = 0;int k;for (k = 0; k < bulletMax_wandou && bullets_wandou[k].used; k++);if (k < bulletMax_wandou){//map[i][j].shoot = true;//if(map[i][j].frameIndex > 1)map[i][j].frameIndex = 2;bullets_wandou[k].used = true;bullets_wandou[k].row = i;bullets_wandou[k].speed = 8;bullets_wandou[k].blast = false;bullets_wandou[k].frameIndex = 0;int zwX = 256 - 150 + j * 81;int zwY = 100 + i * 100 - 15;bullets_wandou[k].x = zwX + imgPlant[map[i][j].type - 1][0]->getwidth() - 10;bullets_wandou[k].y = zwY + 5;}}}//寒冰豌豆else if (map[i][j].type == HAN_BING_WAN_DOU + 1 && lines[i]){map[i][j].shootTime++;if (map[i][j].shootTime > 35){map[i][j].shootTime = 0;int k;for (k = 0; k < bulletMax_hanbing && bullets_hanbing[k].used; k++);if (k < bulletMax_hanbing){//map[i][j].shoot = true;//if(map[i][j].frameIndex > 1)map[i][j].frameIndex = 4;bullets_hanbing[k].used = true;bullets_hanbing[k].row = i;bullets_hanbing[k].speed = 10;bullets_hanbing[k].blast = false;bullets_hanbing[k].frameIndex = 0;int zwX = 256 - 150 + j * 81;int zwY = 100 + i * 100 - 15;bullets_hanbing[k].x = zwX + imgPlant[map[i][j].type - 1][0]->getwidth() - 10;bullets_hanbing[k].y = zwY + 5;}}}//三头豌豆else if (map[i][j].type == SAN_TOU_WAN_DOU + 1 && lines[i]){map[i][j].shootTime++;if (map[i][j].shootTime > 35){map[i][j].shootTime = 0;int k;for (int b = 0; b < 3; b++){for (k = 0; k < bulletMax_santou && bullets_santou[k].used; k++);if (k < bulletMax_santou){//map[i][j].shoot = true;//if(map[i][j].frameIndex > 1)//map[i][j].frameIndex = 2;bullets_santou[k].used = true;bullets_santou[k].row = i;bullets_santou[k].speed = 8;bullets_santou[k].blast = false;bullets_santou[k].frameIndex = 0;int zwX = 256 - 150 + j * 81;int zwY = 100 + i * 100 - 15;bullets_santou[k].x = zwX + imgPlant[map[i][j].type - 1][0]->getwidth() - 30;bullets_santou[k].y = zwY + 16;direction_santou[k] = b;row_santou[k] = i;}}}}}}
}void updateBullets_kunkun()
{int countMax = sizeof(bullets) / sizeof(bullets[0]);for (int i = 0; i < countMax; i++){if (bullets[i].used){//static double angle = 0;bullets[i].x += bullets[i].speed;//angle += bullets[i].speed;//bullets[i].y += 10;//bullets[i].x += bullets[i].speed;if (bullets[i].x > Wide){bullets[i].used = false;}//待完善if (bullets[i].blast){bullets[i].frameIndex++;if (bullets[i].frameIndex >= 4){bullets[i].used = false;}}}}
}void updateBullets_wandou()
{int countMax_wandou = sizeof(bullets_wandou) / sizeof(bullets_wandou[0]);for (int i = 0; i < countMax_wandou; i++){if (bullets_wandou[i].used){//static double angle = 0;bullets_wandou[i].x += bullets_wandou[i].speed;//angle += bullets[i].speed;//bullets[i].y += 10;//bullets[i].x += bullets[i].speed;if (bullets_wandou[i].x > Wide){bullets_wandou[i].used = false;}//待完善if (bullets_wandou[i].blast){bullets_wandou[i].frameIndex++;if (bullets_wandou[i].frameIndex >= 4){bullets_wandou[i].used = false;}}}}
}void updateBullets_hanbing()
{int countMax_hanbing = sizeof(bullets_hanbing) / sizeof(bullets_hanbing[0]);for (int i = 0; i < countMax_hanbing; i++){if (bullets_hanbing[i].used){//static double angle = 0;bullets_hanbing[i].x += bullets_hanbing[i].speed;//angle += bullets[i].speed;//bullets[i].y += 10;//bullets[i].x += bullets[i].speed;if (bullets_hanbing[i].x > Wide){bullets_hanbing[i].used = false;}//待完善if (bullets_hanbing[i].blast){bullets_hanbing[i].frameIndex++;if (bullets_hanbing[i].frameIndex >= 4){bullets_hanbing[i].used = false;}}}}
}void updateBullets_santou()
{int countMax_santou = sizeof(bullets_santou) / sizeof(bullets_santou[0]);for (int i = 0; i < countMax_santou; i++){if (bullets_santou[i].used){if (direction_santou[i] == MIDDLE){//static double angle = 0;bullets_santou[i].x += bullets_santou[i].speed;//bullets[i].x += bullets[i].speed;if (bullets_santou[i].x > Wide){bullets_santou[i].used = false;}	}else if (direction_santou[i] == UP){int destY = 85 + (row_santou[i] - 1) * 100;//int zwX = 256 - 150 + j * 81;float angle = atan(0.6);bullets_santou[i].x += bullets_santou[i].speed;bullets_santou[i].y -= bullets_santou[i].speed * tan(angle);//printf("%d\n", row_santou[i]);//printf("destY = %d\n", destY);//printf("bullets[i].y = %lf\n", bullets[i].y);if (bullets_santou[i].y <= destY + 16){direction_santou[i] = MIDDLE;}}else if (direction_santou[i] == DOWN){int destY = 85 + (row_santou[i] + 1) * 100;float angle = atan(0.6);bullets_santou[i].x += bullets_santou[i].speed;bullets_santou[i].y += bullets_santou[i].speed * tan(angle);if (bullets_santou[i].y >= destY + 16){direction_santou[i] = MIDDLE;}}//待完善if (bullets_santou[i].blast){bullets_santou[i].frameIndex++;if (bullets_santou[i].frameIndex >= 4){bullets_santou[i].used = false;}}}}
}void updateBullets()
{//坤坤updateBullets_kunkun();//豌豆射手updateBullets_wandou();//寒冰豌豆updateBullets_hanbing();//三头豌豆updateBullets_santou();
}void checkBullet2Zm_kunkun()
{int bCount = sizeof(bullets) / sizeof(bullets[0]);int zCount = sizeof(zms) / sizeof(zms[0]);for (int i = 0; i < bCount; i++){//if (bullets[i].used || bullets[i].blast == false){for (int j = 0; j < zCount; j++){if (zms[j].used == false)continue;int x1 = zms[j].x + 80;int x2 = zms[j].x + 110;int x = bullets[i].x;if (zms[j].dead == false &&bullets[i].row == zms[j].row && x > x1 && x < x2 && bullets[i].used) {zms[j].blood -= 20;zms[j].x += 1;bullets[i].blast = true;bullets[i].speed = 0;//bullets[i].x = 0;if (zms[j].blood <= 0){killCount++;zms[j].dead = true;zms[j].speed = 0;zms[j].frameIndex = 0;}break;}}}}
}void checkBullet2Zm_wandou()
{int bCount = sizeof(bullets_wandou) / sizeof(bullets_wandou[0]);int zCount = sizeof(zms) / sizeof(zms[0]);for (int i = 0; i < bCount; i++){//if (bullets[i].used || bullets[i].blast == false)for (int j = 0; j < zCount; j++){if (zms[j].used == false)continue;int x1 = zms[j].x + 80;int x2 = zms[j].x + 110;int x = bullets_wandou[i].x;if (zms[j].dead == false &&bullets_wandou[i].row == zms[j].row && x > x1 && x < x2 && bullets_wandou[i].used) {zms[j].blood -= 20;bullets_wandou[i].blast = true;bullets_wandou[i].speed = 0;//bullets_wandou[i].x = 0;if (zms[j].blood <= 0){killCount++;zms[j].dead = true;zms[j].speed = 0;zms[j].frameIndex = 0;}break;}}}
}void checkBullet2Zm_hanbing()
{int bCount = sizeof(bullets_hanbing) / sizeof(bullets_hanbing[0]);int zCount = sizeof(zms) / sizeof(zms[0]);for (int i = 0; i < bCount; i++){//if (bullets[i].used || bullets[i].blast == false)for (int j = 0; j < zCount; j++){if (zms[j].used == false)continue;int x1 = zms[j].x + 80;int x2 = zms[j].x + 110;int x = bullets_hanbing[i].x;if (zms[j].dead == false &&bullets_hanbing[i].row == zms[j].row && x > x1 && x < x2 && bullets_hanbing[i].used) {zms[j].blood -= 20;zms[j].zmSpeed = 7;bullets_hanbing[i].blast = true;bullets_hanbing[i].speed = 0;//bullets_hanbing[i].x = 0;if (zms[j].blood <= 0){killCount++;zms[j].dead = true;zms[j].speed = 0;zms[j].frameIndex = 0;zms[j].zmSpeed = 4;}break;}}}
}void checkBullet2Zm_santou()
{int bCount = sizeof(bullets_santou) / sizeof(bullets_santou[0]);int zCount = sizeof(zms) / sizeof(zms[0]);for (int i = 0; i < bCount; i++){bullets_santou[i].row = (bullets_santou[i].y - 85+5) / 100;//if (bullets[i].used || bullets[i].blast == false)for (int j = 0; j < zCount; j++){//100 + i * 100 - 15if (zms[j].used == false)continue;int x1 = zms[j].x + 80;int x2 = zms[j].x + 110;int x = bullets_santou[i].x;if (zms[j].dead == false &&bullets_santou[i].row == zms[j].row && x > x1 && x < x2 && bullets_santou[i].used) {zms[j].blood -= 20;bullets_santou[i].blast = true;bullets_santou[i].speed = 0;//bullets_santou[i].x = 0;if (zms[j].blood <= 0){killCount++;zms[j].dead = true;zms[j].speed = 0;zms[j].frameIndex = 0;zms[j].zmSpeed = 4;}break;}}}
}void checkBullet2Zm()
{//坤坤checkBullet2Zm_kunkun();//豌豆checkBullet2Zm_wandou();//寒冰豌豆checkBullet2Zm_hanbing();//三头豌豆checkBullet2Zm_santou();
}void checkBoom2Zm()
{int zCount = sizeof(zms) / sizeof(zms[0]);for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){//樱桃if (map[i][j].type == YING_TAO + 1){if (map[i][j].frameIndex > 8){PlaySound("res/audio/cherrybomb.wav", NULL, SND_FILENAME | SND_ASYNC);//map[row][col].x = 256 - 150 + col * 81;//map[row][col].y = 100 + row * 100 - 15;map[i][j].type = 0;map[i][j].frameIndex = 0;int x1 = 100 + 81 * (j - 1);int x2 = 100 + 81 * (j + 2);int y1 = 85 + (i - 1) * 100;int y2 = 85 + (i + 2) * 100;for (int k = 0; k < zCount; k++){if (zms[k].used == false)continue;int zmX = zms[k].x + imgZm[0].getwidth() / 2;int zmY = zms[k].y;if (zmX <= x2 && zmX >= x1 && zmY >= y1 && zmY <= y2 && zms[k].dead == false){killCount++;zms[k].boom = true;zms[k].dead = true;zms[k].speed = 0;zms[k].frameIndex = 0;zms[k].blood = 0;}}}}//火爆辣椒else if (map[i][j].type == LA_JIAO + 1){if (map[i][j].frameIndex > 7){if (map[i][j].frameIndex == 8)PlaySound("res/audio/firepea.wav", NULL, SND_FILENAME | SND_ASYNC);for (int k = 0; k < zCount; k++){if (zms[k].used == false)continue;if (zms[k].row == i && zms[k].x < Wide - 80 - 70 && zms[k].dead == false){killCount++;zms[k].boom = true;zms[k].dead = true;zms[k].speed = 0;zms[k].frameIndex = 0;zms[k].blood = 0;}}if (map[i][j].frameIndex > 14){map[i][j].type = 0;map[i][j].frameIndex = 0;}}}}}
}void checkZM2Zhiwu()
{int chomp = 0;//mciSendString("play ZM_BGM repeat", NULL, NULL, NULL);char name[64];int bCount = sizeof(bullets) / sizeof(bullets[0]);int zCount = sizeof(zms) / sizeof(zms[0]);for (int i = 0; i < zCount; i++){//killCount = 0;if (zms[i].dead)continue;//zms[i].chomptime = 0;int row = zms[i].row;for (int j = 0; j < 9; j++){//if (map[row][j].type == 0)continue;//int zhiwuX = 101 + j * 81;int x1 = zhiwuX;int x2 = zhiwuX + 81;int x3 = zms[i].x + 100;if (x3 >= x1 && x3 <= x2){if (map[row][j].blood <= 0 || (map[row][j].type == 0 && zms[i].eating != false)){map[row][j].blood = 0;map[row][j].type = 0;zms[i].eating = false;//zms[i].frameIndex = 0;zms[i].speed = 3;}else if (map[row][j].type != 0){//mciSendString("play ZM_BGM repeat", NULL, NULL, NULL);//mciSendString("play name repeat", NULL, 0, NULL);zms[i].eating = true;zms[i].speed = 0;if (map[row][j].type != 3 && map[row][j].type != 7)map[row][j].blood--;//zms[i].frameIndex = 0;}if (zms[i].eating && chomp == 0)chomp = 1;}else if (x3 > 830){zms[i].eating = false;zms[i].speed = 3;}}}static int chomp_time = 0;chomp_time++;if (chomp&&chomp_time>20){chomp_time = 0;PlaySound("res/audio/chomp.wav", NULL, SND_FILENAME | SND_ASYNC);//mciSendString("play ZM_BGM", NULL, NULL, NULL);//printf("1 ");}
}void checkcars2Zm()
{for (int i = 0; i < 5; i++){int carsX = cars[i].x + 70;for (int j = 0; j < ZM_MAX; j++){if (zms[j].used && zms[j].dead == false && zms[j].row == i){int zmX = zms[j].x + 80;if (carsX > zmX && cars[i].used){if (cars[i].move == false)cars[i].move = true;else{killCount++;zms[j].dead = true;zms[j].speed = 0;zms[j].frameIndex = 0;}}}}}
}void collistionCheck()
{//子弹对僵尸的检测checkBullet2Zm();//僵尸对植物的检测checkZM2Zhiwu();//爆炸对植物的检测checkBoom2Zm();//小推车对僵尸的检测checkcars2Zm();
}void updatecar()
{for (int i = 0; i < 5; i++){if (cars[i].move){cars[i].x += 20;}if (cars[i].x > Wide){cars[i].move = false;cars[i].used = false;}}
}void updateGame()
{srand((unsigned)time(NULL));static int count = 0;count++;if (count > 4){count = 0;for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){if (map[i][j].type > 0){map[i][j].frameIndex++;int PlantType = map[i][j].type - 1;int index = map[i][j].frameIndex;if (map[i][j].shoot){if (map[i][j].frameIndex > 1){map[i][j].shoot = false;}}else{if (imgPlant[PlantType][index] == NULL){map[i][j].frameIndex = 0;}}}}}}createSunshine();//创建阳光updatSunshine();//更新阳光状态createZM();//创建僵尸updateZM();//更新僵尸状态shoot();//发射豌豆子弹updateBullets();//更新子弹collistionCheck();//实现豌豆子弹的碰撞检测updatecar();//更新小推车
}void menu()
{mciSendString("play BGM", NULL, NULL, NULL);IMAGE imgBg, imgMenu1, imgMenu2;loadimage(&imgBg, "res/menu.png");loadimage(&imgMenu1, "res/menu2.png");loadimage(&imgMenu2, "res/menu1.png");int flag = 0;while (1){BeginBatchDraw();putimage(0, 0, &imgBg);putimagePNG(474, 75, flag ? &imgMenu1 : &imgMenu2);ExMessage msg;if (peekmessage(&msg)){if (msg.message == WM_LBUTTONDOWN &&msg.x > 474 && msg.x < 474 + 300 &&msg.y>75 && msg.y < 75 + 140){flag = 1;PlaySound("res/audio/bleep.wav", NULL, SND_FILENAME | SND_ASYNC);}else if (msg.message == WM_LBUTTONUP && flag == 1){EndBatchDraw();break;}}EndBatchDraw();}
}void viewScence()
{mciSendString("play BGM3", NULL, NULL, NULL);//开头场景时僵尸的位置vector2 points[9] = {{550,80},{530,160},{630,170},{530,200},{515,270},{565,370},{605,340},{705,280},{690,340}};int index[9];for (int i = 0; i < 9; i++){index[i] = rand() % 11;}int count = 0;for (int i = 0; i >= -500; i-=3){BeginBatchDraw();putimage(i, 0, &img);count++;for (int k = 0; k < 9; k++){putimagePNG(points[k].x + 500 + i,points[k].y, &imgZmStand[index[k]]);if (count >= 10){index[k] = (index[k] + 1) % 11;} }if (count >= 10)count = 0;EndBatchDraw();Sleep(10);}for (int i = 0; i < 60; i++){BeginBatchDraw();putimage(-500, 0, &img);for (int k = 0; k < 9; k++){putimagePNG(points[k].x, points[k].y, &imgZmStand[index[k]]);index[k] = (index[k] + 1) % 11;}EndBatchDraw();Sleep(50);}for (int i = -500; i <= -150; i += 2){BeginBatchDraw();putimage(i, 0, &img);count++;for (int k = 0; k < 9; k++){putimagePNG(points[k].x + 500 + i,points[k].y, &imgZmStand[index[k]]);if (count >= 10){index[k] = (index[k] + 1) % 11;}if (count >= 10) count = 0;}EndBatchDraw();Sleep(10);}}void barsDown()
{int height = imgBar.getheight();for (int y = -height; y <= -10; y++){BeginBatchDraw();putimagePNG(80, y, &imgBar);for (int i = 0; i < PLANT_COUNT + 2; i++){putimagePNG(163 + i * 65, y + 10, &imgCards[i]);}EndBatchDraw();Sleep(10);}for (int i = 0; i < 5; i++){putimagePNG(50, 100 + i * 100 - 15, &imgcar);}mciSendString("close BGM3", NULL, 0, NULL);mciSendString("play BGM4", NULL, NULL, NULL);Sleep(1000);putimagePNG(450 - imgready.getwidth()/2, 300 - imgready.getheight()/2, &imgready);Sleep(200);
}void failScence()
{for (int i = -150; i <= -100; i += 1){BeginBatchDraw();//zmSpeed = 6;putimage(i, 0, &img);//show();drawZm();//updateGame();createZM();//创建僵尸updateZM();//更新僵尸状态EndBatchDraw();Sleep(50);}
}bool checkOver()
{int ret = false;if (gameStatus == WIN){mciSendString("close BGM2", NULL, NULL, NULL);loadimage(0, "res/win2.png");mciSendString("play res/win.mp3", 0, 0, 0);ret = true;}else if (gameStatus == FAIL){mciSendString("close BGM2", NULL, NULL, NULL);mciSendString("play res/lose.mp3", 0, 0, 0);failScence();Sleep(500);loadimage(0, "res/fail2.png");ret = true;}return ret;
}void OpeningAnimation()
{mciSendString("play res/audio/yuanshen.mp3", 0, 0, 0);for (int i = 0; i < 29; i++){BeginBatchDraw();putimage(-148, -35, &imgopena[i]);EndBatchDraw();Sleep(50);}Sleep(4000);
}int main()
{//加载游戏画面gameInit();//开场动画OpeningAnimation();menu();mciSendString("close BGM", NULL, 0, NULL);//游戏开始时的场景切换viewScence();//游戏开始时卡牌和卡牌槽的下落barsDown();int timer = 0;bool flag = true;mciSendString("play BGM2 repeat", NULL, NULL, NULL);while (1){//用户操作userClick();//游戏更新时间timer += getDelay();if (timer > 20){flag = true;timer = 0;}if (flag){flag = false;//绘制游戏画面show();//更新游戏画面updateGame();if(checkOver()) break;}}closegraph;system("pause");return 0;
}

game.h文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1#include<easyx.h>
#include<stdio.h>
#include<time.h>
#include<math.h>
#include"tools.h"
#include<mmsystem.h>
#include"vector2.h"
#pragma comment(lib,"winmm.lib")#define Wide 900
#define Hight 600
#define KUNKUN_BLOOD 100//非坚果植物的血量
#define ORDINARY_ZM_BLOOD 1270*3//僵尸血量
#define ZM_MAX 1024//创建僵尸的最大数量enum {WAN_DOU, TAI_YANG, LA_JIAO, KUN_KUN, JIAN_GUO,HAN_BING_WAN_DOU, YING_TAO, SAN_TOU_WAN_DOU, PLANT_COUNT
};
IMAGE img;//地图
IMAGE imgBar;//卡牌槽
IMAGE imgCards[PLANT_COUNT + 2];//卡牌
IMAGE* imgPlant[PLANT_COUNT + 2][20];//植物动作
IMAGE imgZmStand[11];//开场僵尸的站立
IMAGE imgcar;//小推车
IMAGE imgopena[29];//开场动画
IMAGE imgready;
IMAGE imgnotify;int curX, curY;//当前选中植物,在移动过程中植物的坐标
int curPlant;// 0:没有选中,1:选中了第一种种植物
int sunshine;enum { GOING, WIN, FAIL };
int killCount;//已经杀掉的僵尸个数
int zmCount;//已经出现的僵尸个数
int zmCount_max = 1;//每波出现的僵尸数量
int gameStatus;//游戏的状态
int wava_count = 1;//第wava_count波僵尸struct plant
{int type;//植物类型int frameIndex;//植物动作帧//bool catched;//是否被吃int blood;//血量int shootTime;//植物子弹的射速int timer;//阳光生产的时间int x, y;//植物坐标bool shoot;//判断植物是否处于发射状态
};
struct plant map[5][9];enum { SUNSHINE_DOWN, SUNSHINE_GROUND, SUNSHINE_COLLECT, SUNSHINE_RPODUCT };struct sunshineBall
{int x, y;int frameIndex;//当前显示的图片帧序号int destY;//飘落的目标位置的y坐标bool used;//是否在使用int timer;float xoff;float yoff;float t;//贝塞尔曲线的时间点vector2 p1, p2, p3, p4;vector2 pCur;//当前时刻阳光球的位置float speed;int status;
};//10个阳光球
struct sunshineBall balls[10];
IMAGE imgSunshineBall[29];struct zm
{int x, y;//僵尸的坐标int frameIndex;//僵尸动作帧bool used;//僵尸是否被使用int speed;//僵尸每一次移动的位移int row;//僵尸所在行int blood;//僵尸血量bool dead;//僵尸是否死亡bool eating;//僵尸是否在吃植物bool boom;//僵尸是否被炸死int zmSpeed;//僵尸的移动快慢
};
struct zm zms[ZM_MAX];
IMAGE imgZm[22];
IMAGE imgZMDead[38];
IMAGE imgzmboom[20];
IMAGE imgZMEat[21];//子弹
struct bullet
{double x, y;//子弹的坐标bool used;//子弹是否被使用int row;//子弹所在行int speed;//子弹速度bool blast;//是否发生爆炸int frameIndex;//帧序号
};
//坤坤
struct bullet bullets[10000];
IMAGE imgBulletNormal;
IMAGE imgBallBlast[4];
//豌豆
struct bullet bullets_wandou[200];
IMAGE imgBallBlast_wandou[4];
IMAGE imgBulletNormal_wandou;
//寒冰豌豆
struct bullet bullets_hanbing[200];
IMAGE imgBallBlast_hanbing[4];
IMAGE imgBulletNormal_hanbing;
//三头豌豆
struct bullet bullets_santou[200];
IMAGE imgBallBlast_santou[4];
IMAGE imgBulletNormal_santou;
int direction_santou[200];
int row_santou[200];//三头豌豆发射子弹时所在的行数
enum { MIDDLE, UP, DOWN };//小推车
struct car
{bool move;//是否处于移动状态int x, y;//位置bool used;//是否被使用
};
struct car cars[5];
/*
* 增加植物的步骤:
* 1. 创建子弹的相关变量
* 2. 加载植物子弹图片
* 3. 渲染植物子弹
* 4. 发射植物子弹
* 5. 检查植物子弹与僵尸的碰撞
* 6. 更新植物子弹
*/

vector2.cpp文件(贝塞尔曲线)

//头文件要求
#include <cmath>
#include "vector2.h"//加法
vector2 operator +(vector2 x, vector2 y) { return vector2(x.x + y.x, x.y + y.y ); 
}//减法
vector2 operator -(vector2 x, vector2 y) {return vector2(x.x - y.x, x.y - y.y);
}// 乘法
vector2 operator *(vector2 x, vector2 y) {return vector2(x.x * y.x - x.y * y.y, x.y * y.x + x.x * y.y);
}// 乘法
vector2 operator *(vector2 y, float x) {return vector2(x*y.x, x*y.y);
}vector2 operator *(float x, vector2 y) {return vector2(x * y.x, x * y.y);
}//叉积
long long cross(vector2 x, vector2 y) { return x.y * y.x - x.x * y.y; }//数量积 点积
long long dot(vector2 x, vector2 y) { return x.x * y.x + x.y * y.y; }//四舍五入除法
long long dv(long long a, long long b) {//注意重名!!! return b < 0 ? dv(-a, -b): (a < 0 ? -dv(-a, b): (a + b / 2) / b);
}//模长平方
long long len(vector2 x) { return x.x * x.x + x.y * x.y; }//模长
long long dis(vector2 x) { return sqrt(x.x * x.x + x.y * x.y); }//向量除法
vector2 operator /(vector2 x, vector2 y) {long long l = len(y);return vector2(dv(dot(x, y), l), dv(cross(x, y), l));
}//向量膜
vector2 operator %(vector2 x, vector2 y) { return x - ((x / y) * y); }//向量GCD 
vector2 gcd(vector2 x, vector2 y) { return len(y) ? gcd(y, x % y) : x; }vector2 calcBezierPoint(float t, vector2 p0, vector2 p1, vector2 p2, vector2 p3) {float u = 1 - t;float tt = t * t;float uu = u * u;float uuu = uu * u;float ttt = tt * t;vector2 p = uuu * p0;p = p + 3 * uu * t * p1;p = p + 3 * u * tt * p2;p = p + ttt * p3;return p;
}

vector2.h文件

#pragma once//头文件要求
#include <cmath>struct vector2 {vector2(int _x=0, int _y=0) :x(_x), y(_y) {}vector2(int* data) :x(data[0]), y(data[1]){}long long x, y;
};//加法
vector2 operator +(vector2 x, vector2 y);//减法
vector2 operator -(vector2 x, vector2 y);// 乘法
vector2 operator *(vector2 x, vector2 y);
vector2 operator *(vector2, float);
vector2 operator *(float, vector2);//叉积
long long cross(vector2 x, vector2 y);//数量积 点积
long long dot(vector2 x, vector2 y);//四舍五入除法
long long dv(long long a, long long b);//模长平方
long long len(vector2 x);//模长
long long dis(vector2 x);//向量除法
vector2 operator /(vector2 x, vector2 y);//向量膜
vector2 operator %(vector2 x, vector2 y);//向量GCD 
vector2 gcd(vector2 x, vector2 y);vector2 calcBezierPoint(float t, vector2 p0, vector2 p1, vector2 p2, vector2 p3);

tools.cpp文件(透明贴图)

#include "tools.h"// 载入PNG图并去透明部分
void _putimagePNG(int  picture_x, int picture_y, IMAGE* picture) //x为载入图片的X坐标,y为Y坐标
{DWORD* dst = GetImageBuffer();    // GetImageBuffer()函数,用于获取绘图设备的显存指针,EASYX自带DWORD* draw = GetImageBuffer();DWORD* src = GetImageBuffer(picture); //获取picture的显存指针int picture_width = picture->getwidth(); //获取picture的宽度,EASYX自带int picture_height = picture->getheight(); //获取picture的高度,EASYX自带int graphWidth = getwidth();       //获取绘图区的宽度,EASYX自带int graphHeight = getheight();     //获取绘图区的高度,EASYX自带int dstX = 0;    //在显存里像素的角标// 实现透明贴图 公式: Cp=αp*FP+(1-αp)*BP , 贝叶斯定理来进行点颜色的概率计算for (int iy = 0; iy < picture_height; iy++){for (int ix = 0; ix < picture_width; ix++){int srcX = ix + iy * picture_width; //在显存里像素的角标int sa = ((src[srcX] & 0xff000000) >> 24); //0xAArrggbb;AA是透明度int sr = ((src[srcX] & 0xff0000) >> 16); //获取RGB里的Rint sg = ((src[srcX] & 0xff00) >> 8);   //Gint sb = src[srcX] & 0xff;              //Bif (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight){dstX = (ix + picture_x) + (iy + picture_y) * graphWidth; //在显存里像素的角标int dr = ((dst[dstX] & 0xff0000) >> 16);int dg = ((dst[dstX] & 0xff00) >> 8);int db = dst[dstX] & 0xff;draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16)| ((sg * sa / 255 + dg * (255 - sa) / 255) << 8)| (sb * sa / 255 + db * (255 - sa) / 255);}}}
}// 适用于 y <0 以及x<0的任何情况
void putimagePNG(int x, int y, IMAGE* picture) {IMAGE imgTmp, imgTmp2, imgTmp3;int winWidth = getwidth();int winHeight = getheight();if (y < 0) {SetWorkingImage(picture);getimage(&imgTmp, 0, -y,picture->getwidth(), picture->getheight() + y);SetWorkingImage();y = 0;picture = &imgTmp;}else if (y >= getheight() || x >= getwidth()) {return;}else if (y + picture->getheight() > winHeight) {SetWorkingImage(picture);getimage(&imgTmp, x, y, picture->getwidth(), winHeight - y);SetWorkingImage();picture = &imgTmp;}if (x < 0) {SetWorkingImage(picture);getimage(&imgTmp2, -x, 0, picture->getwidth() + x, picture->getheight());SetWorkingImage();x = 0;picture = &imgTmp2;}if (x > winWidth - picture->getwidth()) {SetWorkingImage(picture);getimage(&imgTmp3, 0, 0, winWidth - x, picture->getheight());SetWorkingImage();picture = &imgTmp3;}_putimagePNG(x, y, picture);
}int getDelay() {static unsigned long long lastTime = 0;unsigned long long currentTime = GetTickCount();if (lastTime == 0) {lastTime = currentTime;return 0;}else {int ret = currentTime - lastTime;lastTime = currentTime;return ret;}
}

tools.cpp文件 

#pragma once
#include <graphics.h>void putimagePNG(int  picture_x, int picture_y, IMAGE* picture);
int getDelay();

相关文章:

C语言游戏实战(12):植物大战僵尸(坤版)

植物大战僵尸 前言&#xff1a; 本游戏使用C语言和easyx图形库编写&#xff0c;通过这个项目我们可以深度的掌握C语言的各种语言特性和高级开发技巧&#xff0c;以及锻炼我们独立的项目开发能力&#xff0c; 在开始编写代码之前&#xff0c;我们需要先了解一下游戏的基本规则…...

提权方式及原理汇总

一、Linux提权 1、SUID提权 SUID&#xff08;设置用户ID&#xff09;是赋予文件的一种权限&#xff0c;它会出现在文件拥有者权限的执行位上&#xff0c;具有这种权限的文件会在其执行时&#xff0c;使调用者暂时获得该文件拥有者的权限。 为可执行文件添加suid权限的目的是简…...

【leetcode----二叉树中的最大路径和】

二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点 root &#xff0c…...

Rust: 编译过程中链接器 `cc` 没有找到

这个错误信息表明在编译过程中链接器 cc 没有找到。cc 通常是 C 编译器的符号链接&#xff0c;它指向系统上的实际 C 编译器&#xff0c;如 gcc 或 clang。这个错误通常意味着你的系统缺少必要的编译工具链。 要解决这个问题&#xff0c;你需要确保你的系统上安装了 C 编译器。…...

【vue-3】动态属性绑定v-bind

1、文本动态绑定&#xff1a; <input type"text" v-bind:value"web.url"> 简写&#xff1a; <input type"text" :value"web.url"> 2、文字样式动态绑定 <b :class"{textColor:web.fontStatus}">vue学…...

Rust:多线程环境下使用 Mutex<T> 还是 Arc<Mutex<T>> ?

在 Rust 中&#xff0c;Mutex 本身不是线程不安全的&#xff1b;它提供了内部的线程同步机制。然而&#xff0c;如果你想在多线程环境中共享同一个 Mutex&#xff0c;你需要确保这个 Mutex 可以被多个线程访问。为此&#xff0c;你通常需要使用 Arc<Mutex<T>>。Arc…...

关于如何创建一个可配置的 SpringBoot Web 项目的全局异常处理

前情概要 这个问题其实困扰了我一周时间&#xff0c;一周都在 Google 上旅游&#xff0c;我要如何动态的设置 RestControllerAdvice 里面的 basePackages 以及 baseClasses 的值呢&#xff1f;经过一周的时间寻求无果之后打算决定放弃的我终于找到了一些关键的线索。 当然在此…...

docker三种自定义网络(虚拟网络) overlay实现原理

docker提供了三种自定义网络驱动&#xff1a;bridge、overlay、macvlan。 bridge驱动类似默认的bridge网络模式。 overlay和macvlan是用于创建跨主机网络。 支持自定义网段、网关&#xff0c;docker network create --subnet 172.77.0.0/24 --gateway 172.77.0.1 my_n…...

C#上位机1ms级高精度定时任务

precisiontimer 安装扩展包 添加引用 完整代码 using PrecisionTiming;using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; us…...

盘点28个免费域名申请大全

盘点28个免费域名申请大全 免费域名推荐学习使用&#xff0c;免费就意味着没任何保障。 名称稳定时间支持解析模式后缀格式说明地址EU.org28 年NS.eu.org/. 国家简写.eu.org需要审核&#xff0c;稳定性高&#xff0c;限制少&#xff0c;国内访问有问题&#xff0c;可 CFeu.orgp…...

【vue】封装的天气展示卡片,在线获取天气信息

源码 <template><div class"sen_weather_wrapper"><div class"sen_top_box"><div class"sen_left_box"><div class"sen_top"><div class"sen_city">山东</div><qctc-time cl…...

【MySQL】库的操作和表的操作

库的操作和表的操作 一、库的操作1、创建数据库(create)2、字符集和校验规则&#xff08;1&#xff09;查看系统默认字符集以及校验规则&#xff08;2&#xff09;查看数据库支持的字符集&#xff08;3&#xff09;查看数据库支持的字符集校验规则&#xff08;4&#xff09;校验…...

【学习笔记】后端(Ⅰ)—— NodeJS(Ⅱ)

NodeJS 3、进阶篇 —— Express框架 3.1、Express 框架介绍 3.2、Express 框架初体验 3.3、使用 3.4、中间件 3.5、托管静态文件 3.6、获取表单数据 3.7、防盗链 3.8、路由模式化 3.8、EJS 模板引擎 3.9、express-generator…...

VMware报平台不支持虚拟化Win10家庭版关闭Hyper-V及内核隔离

1.BIOS中开启虚拟化功能 2.启动或关闭程序中找不到Hyper-v 停止 hypervisorlaunchtype&#xff08;Windows Hyper-V 启动加载器&#xff09; 以管理员的身份打开命令行窗口&#xff0c;运行如下命令&#xff0c;关闭停止 Windows Hyper-V 启动加载器 开启 Windows Hyper-V 启…...

简单介绍十款可以免费使用的API测试工具

API开发应该是后端开发最常见的工作&#xff0c;而调试和测试API是非常关键的&#xff0c;这篇文章简单介绍几款常用的工具以供大家参考。 SoapUI SoapUI是很老牌的工具的&#xff0c;在之前Webservice盛行的时候经常会用到。 现在官方推出了Pro版本的ReadyAPI&#xff0c;但要…...

非授权人员进入报警系统

非授权人员进入报警系统基于智能视频分析技术和深度学习技术&#xff0c;非授权人员进入报警系统通过现场已经装好的监控摄像头针对人体进行精准检测&#xff0c;并根据设置的禁入区范围进行判断。通过图像处理和人体识别算法&#xff0c;非授权人员进入报警系统可以在实时监测…...

Mysql基础教程(03):AND

MySQL AND 运算符的用法 本文介绍了 MySQL 中如何在 WHERE 子句中使用 AND 运算符组合多个查询条件过滤查询数据。 当使用 SELECT 查询数据时&#xff0c;如果 WHERE 子句中有多个条件&#xff0c;可以根据需要使用 AND, OR, 或者 NOT 运算符将他们组合起来。本文主要介绍 AN…...

为什么要使用 eval

调用 eval 方法的原因是为了确保模型在进行预测时使用正确的配置。在训练过程中&#xff0c;某些层&#xff08;如 Dropout 层&#xff09;的行为是为了正则化而设计的&#xff0c;它们会在每次迭代中随机丢弃一些神经元的输出。而在评估模式下&#xff0c;这些层将不再随机丢弃…...

BCD编码(8421)介绍

概念 BCD (Binary-Coded Decimal) 是一种二进制的数字编码形式&#xff0c;其特点每个十进制数位用4个二进制位来表示。 在网络IO中&#xff0c;你传输一个数字类型最少需要一字节&#xff0c;传输两个数字类型最少需要两字节&#xff0c;但是当你使用BCD编码后传输&#xff…...

前端javascript包管理,npm升级用pnpm

一 pnpm 介绍 pnpm&#xff08;Package Manager&#xff09;是一个快速、节省磁盘空间的 JavaScript 包管理器&#xff0c;它是 Node.js 生态系统中 npm 的一个替代品。pnpm 解决了传统包管理工具在处理依赖时的一些痛点&#xff0c;特别是关于存储空间使用和依赖地狱的问题。…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...