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();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/329052.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OSPF路由聚合

原理概述 与RIP不同&#xff0c;OSPF不支持自动路由聚合&#xff0c;仅支持手动路由聚合。OSPF的路由聚合有两种机制&#xff1a;区域间路由聚合和外部路由聚合。区域间路由聚合必须配置在ABR路由器上&#xff0c;指的是ABR在把与自己直接相连区域&#xff08;Area&#xff09…

Dijkstra算法在《庆余年》中的应用:范闲的皇宫之旅

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

【探索数据结构】线性表之双链表

&#x1f389;&#x1f389;&#x1f389;欢迎莅临我的博客空间&#xff0c;我是池央&#xff0c;一个对C和数据结构怀有无限热忱的探索者。&#x1f64c; &#x1f338;&#x1f338;&#x1f338;这里是我分享C/C编程、数据结构应用的乐园✨ &#x1f388;&#x1f388;&…

MT3041 多项式变换求值

注意点&#xff1a; 1.使用单调栈 2.用ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);避免超时 3.此题除了ans最好不要用long long&#xff0c;如果a[]和b[]都是long long 类型&#xff0c;可能会超内存 4.ans (ans % p p) % p;防止负数 5.使用秦九韶算法计算指数…

【Linux】语言级文件接口与系统级文件接口

目录 前言 一、回顾C语言中的文件操作 二、认识文件缓冲区 三、Linux系统提供的文件接口 四、文件描述符fd简介 Linux下C语言文件接口简单模拟实现 前言 每个编程语言都有自己的文件操作方法&#xff0c;在不同的操作系统下相同的语言有相同的文件操作方法。这是如何实现…

声音转文本(免费工具)

声音转文本&#xff1a;解锁语音技术的无限可能 在当今这个数字化时代&#xff0c;信息的传递方式正以前所未有的速度进化。从手动输入到触控操作&#xff0c;再到如今的语音交互&#xff0c;技术的发展让沟通变得更加自然与高效。声音转文本&#xff08;Speech-to-Text, STT&…

git拉取项目前需要操作哪些?

1.输入 $ ssh-keygen -t rsa -C "秘钥说明" 按enter键 2.出现 ssh/id_rsa&#xff1a;(输入也可以不输入也可以) 然后按enter键 3.出现empty for no passphrase&#xff1a;(输入也可以不输入也可以) 然后按enter键 4.出现same passphrase again: (输入也可以不输入也…

异常检测 | PCA马氏距离异常值检测(Matlab)

异常检测 | PCA马氏距离异常值检测&#xff08;Matlab&#xff09; 目录 异常检测 | PCA马氏距离异常值检测&#xff08;Matlab&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab Pca 马氏距离异常值检测&#xff0c;剔除异常样本&#xff0c;置信椭圆可…

15:00面试,15:08就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

4. C++入门:内联函数、auto关键字、范围for及nullptr

内联函数 概念 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调用建立栈帧的开销&#xff0c;内联函数提升程序运行的效率 对比C的宏 C语言不足&#xff1a;宏 #define ADD(x, y) ((x)(y))int main() {int ret…

OpenFeign高级用法:缓存、QueryMap、MatrixVariable、CollectionFormat优雅地远程调用

码到三十五 &#xff1a; 个人主页 微服务架构中&#xff0c;服务之间的通信变得尤为关键。OpenFeign&#xff0c;一个声明式的Web服务客户端&#xff0c;使得REST API的调用变得更加简单和优雅。OpenFeign集成了Ribbon和Hystrix&#xff0c;具有负载均衡和容错的能力&#xff…

期权策略交易怎么做?怎么选择期权策略?

今天期权懂带你了解期权策略交易怎么做&#xff1f;怎么选择期权策略&#xff1f;期权交易是一种金融衍生品交易方式&#xff0c;它给予购买者在未来特定时间内以特定价格购买&#xff08;或出售&#xff09;标的资产的权利。 期权策略交易怎么做&#xff1f; 配对看跌期权&am…

vue+springboot实现echarts数据图统计

①vue项目修改配置 安装依赖&#xff1a; npm i echarts -S 修改路由index.js&#xff1a; import Vue from vue import VueRouter from vue-router import Manager from ../views/Manager.vue // 解决导航栏或者底部导航tabBar中的vue-router在3.0版本以上频繁点击菜单报错…

00.OpenLayers快速开始

00OpenLayers快速开始 官方文档&#xff1a; 快速开始&#xff1a;https://openlayers.org/doc/quickstart.html 需要node环境 一、设置新项目 npm create ol-app my-app cd my-app npm start第一个命令将创建一个名为 my-app​ 的目录&#xff08;如果您愿意&#xff0c;…

Python筑基之旅-MySQL数据库(一)

目录 一、MySQL数据库 1、简介 2、优点 2-1、开源和免费 2-2、高性能 2-3、可扩展性 2-4、易用性 2-5、灵活性 2-6、安全性和稳定性 2-7、丰富的功能 2-8、结合其他工具和服务 2-9、良好的兼容性和移植性 3、缺点 3-1、对大数据的支持有限 3-2、缺乏全文…

前端面试:项目细节重难点问题分享

面试官提问&#xff1a;我现在给你出一个项目实际遇到的问题&#xff1a;由于后端比较忙&#xff0c;所以我们这边的列表数据排序需要前端最近实现&#xff0c;那你会怎么实现排序呢&#xff1f; 答&#xff1a;我的回答&#xff1a;确实&#xff0c;数据都是由后端实现的&…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-19讲 串口实验UART

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

嵌入式硬件中PCB走线与过孔的电流承载能力分析

简介 使用FR4敷铜板PCBA上各个器件之间的电气连接是通过其各层敷着的铜箔走线和过孔来实现的。 由于不同产品、不同模块电流大小不同,为实现各个功能,设计人员需要知道所设计的走线和过孔能否承载相应的电流,以实现产品的功能,防止过流时产品烧毁。 文中介绍设计和测试FR4敷…

Windows系统安装OpenSSH使用VScode远程连接内网Linux服务器开发

文章目录 &#x1f4a1;推荐 前言1、安装OpenSSH2、VS Code配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网…

Nginx/阿里云/二级域名的配置和使用

阿里云域名解析配置如下&#xff1a; nginx配置如下&#xff1a; 访问地址&#xff1a; zhadmin.iotzzh.com image.png