最全C语言实现植物大战僵尸(完整版)_简易的植物大战僵尸c语言代码,2024年最新C C++程序员面试必备的知识点

2401_84976395 2024-07-06 16:05:04 阅读 82

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

<code>{

IMAGE\* img = &imgBallBlast[bullets[i].frameIndex];

putimagePNG(bullets[i].x, bullets[i].y, img);

}

else

{

putimagePNG(bullets[i].x, bullets[i].y, &imgBulletNormal);

}

}

}

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)

{

balls[i].used = false;

balls[i].status = SUNSHINE_COLLECT;

sunshine += 25;

mciSendString("play res/sunshine.mp3",0,0,0);//加载音乐文件

//设置阳光球的偏移量

balls[i].p1 = balls[i].pCur;

balls[i].p4 = vector2(262, 0);

balls[i].t = 0;

float distance = dis(balls[i].p1 - balls[i].p4);

float off = 8.0;

balls[i].speed = 1.0/(distance/off);

}

}

}

}

void userClick()

{

ExMessage msg;//参数是消息类型

static int status = 0;

//如果消息有值则保存在peekmessage函数中,即为真

if (peekmessage(&msg))

{

if (msg.message == WM_LBUTTONDOWN)//WM_LBUTTONDOWN左键按下去的意思

{

if (msg.x > 338 && msg.x < 338 + 65*ZHI_WU_COUNT && msg.y < 96)//定义坐标判断点击的是否为植物

{

int index = (msg.x - 338) / 65;

status = 1;

curZhiwu = index + 1;

}

else

{

collectSunshine(&msg);

}

}

else if (msg.message == WM_MOUSEMOVE&&status==1)//WM_MOUSEMOVE鼠标移动

{

//记录当前位置

curX = msg.x;

curY = msg.y;

}

//鼠标抬动植物就种下去

else if (msg.message == WM_LBUTTONUP)

{

if (msg.x > 256 && msg.y > 179 && msg.y < 489)

{

int row = (msg.y - 179) / 102;

int col = (msg.x - 256) / 81;

if (map[row][col].type == 0)

{

map[row][col].type = curZhiwu;

map[row][col].frameIndex = 0;

//int x = 256 + j \* 81;

//int y = 179 + i\*102+14;

map[row][col].x = 256 + col \* 81;

map[row][col].y = 179 + row \* 102+14;

}

}

curZhiwu = 0;

status = 0;

}

}

}

void creatSunshine()

{

static int count = 0;

static int fre = 400;

count++;

if (count >= fre )

{

fre = 200 + rand() % 200;

count = 0;//满了计数器清0

//从阳光池中去一个可以使用的

int ballMax = sizeof(balls) / sizeof(balls[0]);

int i = 0;

for (i = 0; i < ballMax && balls[i].used; i++);

if (i >= ballMax) return;//阳光池满了

balls[i].used = true;

balls[i].frameIndex = 0;

//balls[i].x = 260 + rand() % (900 - 260);

//balls[i].y = 60;

//balls[i].destY = 200 + (rand() % 4) * 90;

balls[i].timer = 0;

//balls[i].xoff = 0;

//balls[i].yoff = 0;

balls[i].status = SUNSHINE_DOWN;

balls[i].p1 = vector2(260 + rand() % (900 - 260), 60);

balls[i].p4 = vector2(balls[i].p1.x, 200 + (rand() % 4) * 90);

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 < 3; i++)

{

for (int j = 0; j < 9; j++)

{

if (map[i][j].type == XIANG_RI_KUI + 1)

{

map[i][j].timer++;

}

if (map[i][j].timer > 200)

{

map[i][j].timer = 0;

int k = 0;

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 = (100 + rand() % 50) \* (rand() % 2 ? 1 : -1);

balls[k].p4 = vector2(map[i][j].x+w,

map[i][j].y+imgZhiwu[XIANG_RI_KUI][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 updateSunshine()//更新阳光

{

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

}

}

balls[i].frameIndex=(balls[i].frameIndex+1)%29;

if (balls[i].timer == 0)

{

balls[i].y += 2;

}

if (balls[i].y >= balls[i].destY)

{

//balls[i].used = false;

balls[i].timer++;

if (balls[i].timer > 100)

{

balls[i].used = false;

}

}

}

}

}

void creatZM()

{

static int zmFre = 500;

static int count = 0;

count++;

if (count > zmFre)

{

count = 0;

zmFre = rand() % 200 + 300;

}

int i=0;

int zmMax=sizeof(zms)/sizeof(zms[0]);

for (i = 0; i < zmMax && zms[i].used; i++);

if (i < zmMax)

{

memset(&zms[i],0,sizeof(zms[i]));

zms[i].used = true;

zms[i].x = WIN_WIDTH;

zms[i].row = rand() % 3;

zms[i].y = 172 + (1 + zms[i].row) * 100;

zms[i].speed = 1;

zms[i].blood = 100;

zms[i].dead = false;

}

}

void updataZM()

{

int zmMax = sizeof(zms) / sizeof(zms[0]);

static int count = 0;

count++;

if (count > 2)

{

count = 0;

//更新僵尸的位置

for (int i = 0; i < zmMax; i++)

{

if (zms[i].used)

{

zms[i].x -= zms[i].speed;

if (zms[i].x < 170)

{

printf("GAME OVER\n");

MessageBox(NULL, "over", "over", 0);//待优化

exit(0);

}

}

}

}

static int count2 = 0;

count2++;

if (count2 > 4)

{

count2 = 0;

for (int i = 0; i < zmMax; i++)

{

if (zms[i].used)

{

if (zms[i].dead)

{

zms[i].frameIndex++;

if (zms[i].frameIndex >= 20)

{

zms[i].used = false;

}

}

else if (zms[i].eating)

{

zms[i].frameIndex= (zms[i].frameIndex + 1) % 21;

}

else

{

zms[i].frameIndex = (zms[i].frameIndex + 1) % 22;

}

}

}

}

}

void shoot()

{

int lines[3] = { 0 };

int zmCount = sizeof(zms) / sizeof(zms[0]);

int bulletMax = sizeof(bullets) / sizeof(bullets[0]);

int dangerX = WIN_WIDTH - imgZM[0].getwidth();

for (int i = 0; i < zmCount; i++)

{

if (zms[i].used && zms[i].x < dangerX)

{

lines[zms[i].row] = 1;

}

}

for (int i = 0; i < 3; i++)

{

for (int j = 0; j < 9; j++)

{

if (map[i][j].type == WAN_DOU + 1&&lines[i])

{

static int count = 0;

count++;

if (count > 20)

{

count = 0;

int k = 0;

for (k = 0; k < bulletMax && bullets[k].used; k++);

if (k < bulletMax)

{

bullets[k].used = true;

bullets[k].row = i;

bullets[k].speed = 6;

bullets[k].blast = false;

bullets[k].frameIndex = 0;

int zwX = 256 + j \* 81;

int zwY = 179 + i \* 102 + 14;

bullets[k].x = zwX + imgZhiwu[map[i][j].type - 1][0]->getwidth() - 10;

bullets[k].y = zwY+5;

}

}

}

}

}

}

void updataBullets()

{

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 > WIN_WIDTH)

{

bullets[i].used = false;

}

//子弹的碰撞爆炸

if (bullets[i].blast)

{

bullets[i].frameIndex++;

if (bullets[i].frameIndex >= 4)

{

bullets[i].used = false;

}

}

}

}

}

void checkBullet2Zm()

{

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 == false || bullets[i].blast)

{

continue;

}

for (int k = 0; k < zCount; k++)

{

//if (zms[i].used == false) continue;

if (zms[k].used == false) continue;

int x1 = zms[k].x + 80;

int x2 = zms[k].x + 110;

int x = bullets[i].x;

if (zms[k].dead == false && bullets[i].row == zms[k].row && x > x1 && x < x2)

{

zms[k].blood -= 20;

bullets[i].blast = true;

bullets[i].speed = 0;

if (zms[k].blood <= 0)

{

zms[k].dead = true;

zms[k].speed = 0;

zms[k].frameIndex = 0;

}

break;

}

}

}

}

void checkZm2Zhiwu()

{

int zCount = sizeof(zms) / sizeof(zms[0]);

for (int i = 0; i < zCount; i++)

{

if (zms[i].dead) continue;

int row = zms[i].row;

for (int k = 0; k < 9; k++)

{

if (map[row][k].type == 0)

{

continue;

}

int ZhiWuX = 256 + k \* 81;

int x1 = ZhiWuX + 10;

int x2 = ZhiWuX + 60;

int x3 = zms[i].x + 80;

if (x3 > x1 && x3 < x2)

{

if (map[row][k].catched)

{

map[row][k].deadTime++;

if (map[row][k].deadTime > 100)

{

map[row][k].deadTime = 0;

map[row][k].type = 0;

zms[i].eating = false;

zms[i].frameIndex = 0;

zms[i].speed = 1;

}

}

else

{

map[row][k].catched = true;

map[row][k].deadTime = 0;

zms[i].eating = true;

zms[i].speed = 0;

zms[i].frameIndex = 0;

}

}

}

}

}

void collisionCheck()

{

checkBullet2Zm();

checkZm2Zhiwu();

}

void updateGame()

{

for (int i = 0; i < 3; i++)

{

for (int j = 0; j < 9; j++)

{

if (map[i][j].type > 0)

{

map[i][j].frameIndex++;

int Zhiwutype = map[i][j].type - 1;

int index = map[i][j].frameIndex;

if (imgZhiwu[Zhiwutype][index] == NULL)

{

map[i][j].frameIndex = 0;

}

}

}

}

creatSunshine();//创建阳光

updateSunshine();//更新阳光状态

creatZM();//创建僵尸

updataZM();//更新僵尸的状态

shoot();//发射豌豆子弹

updataBullets();//更新豌豆子弹

collisionCheck();//实现豌豆子弹和僵尸的碰撞

}

void startUI()

{

IMAGE imgBg,imgMenu1,imgMenu2;

loadimage(&imgBg,“res/menu.png”);

loadimage(&imgMenu1, “res/menu1.png”);

loadimage(&imgMenu2, “res/menu2.png”);

int flag = 0;

while (1)

{

BeginBatchDraw();

putimage(0,0,&imgBg);

putimagePNG(474, 75, flag ? &imgMenu2 : &imgMenu1);//如果flag=0,那么加载第二个菜单,

//就是鼠标点击冒险模式后冒险模式的图标会暗淡下来

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;

//鼠标松开

//EndBatchDraw();//渲染一下

}

else if (msg.message == WM_LBUTTONUP&&flag)//鼠标抬起

{

return;

}

}

EndBatchDraw();

}

}

int main(void)

{

gameInit();//进入游戏的程序函数

startUI();//菜单函数

int timer = 0;

bool flag = true;

while (1)

{

userClick();

timer += getDelay();

if (timer > 20)

{

flag = true;

timer = 0;

}

if (flag)

{

flag = false;

updateWindow();

updateGame();

}

}

system(“pause”);

return 0;

}

接着是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里的R

int sg = ((src[srcX] & 0xff00) >> 8); //G

int sb = src[srcX] & 0xff; //B

if (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.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里的R

int sg = ((src[srcX] & 0xff00) >> 8); //G

int sb = src[srcX] & 0xff; //B

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

}

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

(), winHeight - y);

SetWorkingImage();

picture = &imgTmp;

}

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

}

[外链图片转存中…(img-33vIczlJ-1715814397208)]

[外链图片转存中…(img-ZTbbo7OK-1715814397209)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。