c语言基于easyx库的 飞机大战游戏(鼠标控制飞机移动,武器升级,boss发射散弹,boss血条等功能)

课设题目
实现功能:
飞机鼠标控制–飞机武器升级–敌机发射子弹–boss发射散弹–boss血条记录–我方多条生命
在这里插入图片描述在这里插入图片描述在这里插入图片描述

图片资源和源码在下面

链接:https://pan.baidu.com/s/1uTQVHAaWfWHXFg3p5zQ4KA
提取码:y606

源码:

#include <graphics.h>
#include <conio.h>
#include <math.h>
#include <stdio.h>
#pragma comment(lib,"Winmm.lib")						// 引用 Windows Multimedia API

#define High 800		// 游戏画面尺寸
#define Width 800

IMAGE img_bk;									// 背景图片
IMAGE img_planeNormal1, img_planeNormal2;		// 正常飞机图片
IMAGE img_planeExplode1, img_planeExplode2;     // 爆炸飞机图片
IMAGE img_enemyPlane1, img_enemyPlane2;			// 敌机图片
IMAGE boss1_a, boss1_b;							// boss图片
IMAGE bullet_lis[10][2];						// 我方飞机子弹图片

float e_speed[3] = { 0.4,0.5,0.6 };			//敌机随机飞行速度列表
int enemy_cnt = 5;							//同一画面最大敌机数量
int enemy_life = 3;							//敌机的生命值
int e_bullet_cnt = 20;						//同一画面最多敌机子弹数量
int bullet_type = 2;							//我方飞机子弹种类
int bullet_rank = 0;							//我方飞机now子弹等级 and 对应打boss的伤害为 bullet_rank+1 
int bullet_cnt = 20;				            //我方飞机最大子弹数量
int isExpolde = 0;								//飞机是否爆炸
int score = 0;									//得分

int b_bullet_cnt = 5;						//boss子弹同一画面最大数量
int time_cnt = 0;                           //用于控制boss子弹发射间隔

struct Plane {				//我方飞机属性
	float x, y;
	int life;
	float w, h;
}plane;

struct Bullet {				//我方飞机子弹属性
	float x, y;
	int life;
	float w, h;
}bullet[200];

struct Enemy {			    //敌机属性
	float x, y;
	int speed;									//准确来说敌机速度是e_speed[enemy.speed]
	int life;
	float w, h;
}enemy[20];

struct Enemy_bullet {	   //敌机子弹属性
	float x, y;    
	float speed;
	int life;
	float w, h;
}e_bullet[100];

struct Boss {				//boss属性
	float x, y;
	float w, h;
	float add_x, add_y;							//x,y轴移动速度
	int life;									//生命值大小
	int is_active;								//boss是否出现	
	int is_protect;
}boss;

struct Boss_bullet {		//boss子弹属性
	float x, y;
	float w, h;
	float add_x, add_y;
	int life;
}b_bullet[20][3];

void startup();										// 数据初始化(加载图片资源,初始化飞机属性)
void show();										// 画面刷新
void updateWithoutInput();							// 与用户输入无关的更新
void updateWithInput();								// 与用户输入有关的更新
void gameover();									//游戏结束

void reset_plane();									//设置我方飞机的初始属性
void reset_bullet();								//设置我方子弹 和 敌军子弹的大小
void reset_enemy(int i);							//设置敌机属性
void reset_e_bullet(Enemy a);						//设置敌机子弹属性
void reset_boss();									//设置boss属性
void reset_b_bullet(Boss_bullet a[3]);				//设置boss属性

int is_crash(Enemy a, Bullet b);					//子弹--敌机碰撞检测
int is_crash_boss(Boss a, Bullet b);				//子弹--boss碰撞检测
int is_crash_plane(Plane a, Enemy_bullet b);		//我方--敌机子弹碰撞检测
int is_crash_boss_plane(Plane a, Boss_bullet b);	//我方--boss子弹碰撞检测

				
int main()
{
	startup();						// 数据初始化	
	while (1)					    // 游戏循环执行
	{
		show();						// 显示画面
		updateWithoutInput();		// 与用户输入无关的更新
		updateWithInput();			// 与用户输入有关的更新
		if (isExpolde == 1) break;
	}
	gameover();						// 游戏结束、后续处理
	return 0;
}
void startup()										// 数据初始化(加载图片资源,初始化飞机属性)
{
	mciSendString("open image/game_music.mp3 alias bkmusic", NULL, 0, NULL);//打开背景音乐
	mciSendString("play bkmusic repeat", NULL, 0, NULL);  // 循环播放
	initgraph(Width, High);
	loadimage(&img_bk, "image/back2.jpg", 800, 800);
	loadimage(&img_planeNormal1, "image/plane1.jpg");
	loadimage(&img_planeNormal2, "image/plane2.jpg");

	loadimage(&img_enemyPlane1, "image/enemyPlane1.jpg");
	loadimage(&img_enemyPlane2, "image/enemyPlane2.jpg");
	loadimage(&img_planeExplode1, "image/planeExplode_1.jpg");
	loadimage(&img_planeExplode2, "image/planeExplode_2.jpg");
	loadimage(&bullet_lis[0][0], "image/bullet1_a.jpg");
	loadimage(&bullet_lis[0][1], "image/bullet1_b.jpg");
	loadimage(&bullet_lis[1][0], "image/bullet2_a.jpg");
	loadimage(&bullet_lis[1][1], "image/bullet2_b.jpg");
	loadimage(&bullet_lis[2][0], "image/bullet3_a.jpg");
	loadimage(&bullet_lis[2][1], "image/bullet3_b.jpg");

	loadimage(&boss1_a, "image/boss_a.jpg");
	loadimage(&boss1_b, "image/boss_b.jpg");

	reset_plane();										//我方飞机的初始化
	reset_boss();										//boss的初始化
	reset_bullet();										//子弹(我方+敌人)的初始化
	for (int i = 0; i < enemy_cnt; i++)					//敌机的初始化
	{
		enemy[i].h = 135;
		enemy[i].w = 92;
		reset_enemy(i);
	}
	BeginBatchDraw();
}
void show()											//
{
	putimage(0, 0, &img_bk);		// 显示背景	
	if (isExpolde == 0)
	{
		int tx = 91;
		int ty = 106;
		putimage(plane.x - tx / 2, plane.y - ty / 2, &img_planeNormal1, NOTSRCERASE); // 显示正常飞机	
		putimage(plane.x - tx / 2, plane.y - ty / 2, &img_planeNormal2, SRCINVERT);

		if (boss.is_active == 1)									//如果出现boss
		{
			putimage(boss.x, boss.y, &boss1_a, NOTSRCERASE);		//绘制boss
			putimage(boss.x, boss.y, &boss1_b, SRCINVERT);

			for (int k = 0; k < b_bullet_cnt; k++)					//绘制boss子弹
			{
				for (int i = 0; i < 3; i++)
				{
					if (b_bullet[k][i].life == 0) continue;
					putimage(b_bullet[k][i].x, b_bullet[k][i].y, &bullet_lis[0][0], NOTSRCERASE);
					putimage(b_bullet[k][i].x, b_bullet[k][i].y, &bullet_lis[0][1], SRCINVERT);
				}
			}
																	//绘制boss血条
			setlinecolor(BLACK);				//设置当前画线颜色
			rectangle(100, 5, Width - 100, 20);
			setfillcolor(RED);					//设置当前填充颜色。
			if (boss.life < 0) boss.life = 0;
			solidrectangle(100, 5,100+ boss.life*(Width - 200)*0.01, 20);
		}
		for (int i = 0; i < bullet_cnt; i++)						//绘制我方飞机子弹
		{
			if (bullet[i].life == 0) continue;
			putimage(bullet[i].x - bullet[i].w / 2, bullet[i].y, &bullet_lis[bullet_rank][0], NOTSRCERASE); 
			putimage(bullet[i].x - bullet[i].w / 2, bullet[i].y, &bullet_lis[bullet_rank][1], SRCINVERT);
		}


		for (int i = 0; i < enemy_cnt; i++)							//绘制敌机
		{
			putimage(enemy[i].x, enemy[i].y, &img_enemyPlane1, NOTSRCERASE);	   
			putimage(enemy[i].x, enemy[i].y, &img_enemyPlane2, SRCINVERT);

		}
		for (int i = 0; i < e_bullet_cnt; i++)					   //绘制敌机子弹
		{
			if (e_bullet[i].life == 0) continue;
			putimage(e_bullet[i].x, e_bullet[i].y, &bullet_lis[0][0], NOTSRCERASE); // 显示敌机子弹
			putimage(e_bullet[i].x, e_bullet[i].y, &bullet_lis[0][1], SRCINVERT);
		}
	}
	else
	{
		putimage(plane.x - 50, plane.y - 60, &img_planeExplode1, NOTSRCERASE);      // 显示爆炸飞机	
		putimage(plane.x - 50, plane.y - 60, &img_planeExplode2, SRCINVERT);
	}
	outtextxy(Width*0.30, High*0.95, "得分:");
	char s[5];
	sprintf(s, "%d", score);
	outtextxy(Width*0.40, High*0.95, s);

	outtextxy(Width*0.55, High*0.95, "生命:");
	sprintf(s, "%d", plane.life);
	outtextxy(Width*0.65, High*0.95, s);
	FlushBatchDraw();
	Sleep(2);
}
void updateWithoutInput()
{
	if (isExpolde == 0)
	{
		time_cnt++;											//算是boss子弹的计时器吧
		if (boss.is_active == 1)							//如果出现boss			
		{
			if (boss.y < 25)								//boss的前摇(装逼进场)
			{
				boss.y += boss.add_y;
			}
			else
			{
				boss.x += boss.add_x;						//boss的左右摇摆
				if (boss.x + boss.w > Width || boss.x < 0)
				{
					boss.add_x = 0 - boss.add_x;
				}
			}

			for (int k = 0; k < b_bullet_cnt; k++)			//boss子弹的移动
			{
				for (int i = 0; i < 3; i++)
				{
					if (b_bullet[k][i].life == 0) continue;
					if (b_bullet[k][i].y < Width - 10)
					{
						b_bullet[k][i].x += b_bullet[k][i].add_x;
						b_bullet[k][i].y += b_bullet[k][i].add_y;
					}
					else
					{
						b_bullet[k][i].life = 0;			//如果boss子弹超出边界 消失它
					}
				}
			}
			if (time_cnt % 400 == 0)						//boss不定时发射子弹
			{
				for (int k = 0; k < b_bullet_cnt; k++)
				{											//找到消失状态的子弹 发射它
					if (b_bullet[k][0].life == 0 && b_bullet[k][1].life == 0 && b_bullet[k][2].life == 0)
					{
						reset_b_bullet(b_bullet[k]);
						break;
					}

				}

			}
			for (int k = 0; k < b_bullet_cnt; k++)			//boss子弹和我方飞机的碰撞检测
			{
				for (int i = 0; i < 3; i++)
				{
					if (b_bullet[k][i].life == 0) continue;
					if (is_crash_boss_plane(plane, b_bullet[k][i]) == 1)
					{
						plane.life -= 1;
						b_bullet[k][i].life = 0;			//如果boss某个子弹碰撞了 那这个子弹要消失
					}
				}
			}
		}

		for (int i = 0; i < bullet_cnt; i++)				//我方子弹的移动
		{
			if (bullet[i].life == 0)	continue;
			if (bullet[i].y > 0)
			{
				bullet[i].y -= 2;
			}
			else											//如果子弹超出边界 让他消失
			{
				bullet[i].life = 0;
			}
		}
		for (int i = 0; i < enemy_cnt; i++)				 //敌机的移动
		{
			if (enemy[i].y < High - 25)
			{
				enemy[i].y = enemy[i].y + e_speed[enemy[i].speed];
			}
			else
			{
				reset_enemy(i);
			}
		}
		for (int i = 0; i < e_bullet_cnt; i++)			    //敌方子弹的移动
		{
			if (e_bullet[i].life == 0) continue;
			if (e_bullet[i].y < High - 10)
			{
				e_bullet[i].y += e_bullet[i].speed;
			}
			else
			{		
				e_bullet[i].life = 0;						//如果子弹超出边界 让他消失
			}
		}

	
		for (int i = 0; i < e_bullet_cnt; i++)			   //敌方子弹和我方飞机的碰撞检测
		{
			if (e_bullet[i].life == 0) continue;
			if (is_crash_plane(plane, e_bullet[i]) == 1)
			{
				plane.life -= 1;
				e_bullet[i].life = 0;
			}
		}
		for (int i = 0; i < bullet_cnt; i++)			 //我方子弹和boss碰撞检测
		{
			if (bullet[i].life == 0)	continue;
			if (boss.is_active == 0 || boss.life < 0) break;

			if (is_crash_boss(boss, bullet[i]) == 1)
			{
				boss.life -= (bullet_rank + 1);
				bullet[i].life = 0;
			}
		}	
		for (int i = 0; i < enemy_cnt; i++)				 //我方子弹和敌机的检测
		{
			for (int j = 0; j < bullet_cnt; j++)
			{
				if (bullet[j].life == 0) continue;
				if (is_crash(enemy[i], bullet[j]) == 1)  // 子弹击中敌机
				{

					bullet[j].life = 0;					//子弹消失
					if (enemy[i].life <= 1)				//判断敌机的生命值够不够
					{
						reset_enemy(i);					//重置敌机
						mciSendString("close gemusic", NULL, 0, NULL); // 先把前面一次的音乐关闭
						mciSendString("open image/gotEnemy.mp3 alias gemusic", NULL, 0, NULL); // 打开音乐
						mciSendString("play gemusic", NULL, 0, NULL); // 仅播放一次
						score++;
						if (score == 2)					//如果分数等于2 武器进化
						{
							bullet_rank += 1;
							reset_bullet();				//更新进化武器的图片
						}
						else if (score == 4)			//如果分数等于4 武器进化	
						{
							bullet_rank += 1;
							reset_bullet();				//更新进化武器的图片
						}
						if (score > 0 && score % 5 == 0 && score % 2 != 0)
						{
							mciSendString("close 5music", NULL, 0, NULL); // 先把前面一次的音乐关闭
							mciSendString("open image/5.mp3 alias 5music", NULL, 0, NULL); // 打开音乐
							mciSendString("play 5music", NULL, 0, NULL); // 仅播放一次
						}
						if (score % 10 == 0)
						{
							mciSendString("close 10music", NULL, 0, NULL); // 先把前面一次的音乐关闭
							mciSendString("open image/10.mp3 alias 10music", NULL, 0, NULL); // 打开音乐
							mciSendString("play 10music", NULL, 0, NULL); // 仅播放一次
						}

						if (score >= 6)				//达到一定分数 出现boss
						{
							boss.is_active = 1;
							enemy_cnt = 0;			//boss出现 同时减少其他小敌机
							for (int p = 0; p < e_bullet_cnt; p++)		//之前敌机发射的子弹消失
							{
								e_bullet[p].life = 0;
							}
						}
					}
					else
					{
						enemy[i].life -= 1;
					}
				}
			}

		}
	}
}
void updateWithInput()
{
	if (isExpolde == 0)
	{
		MOUSEMSG m;		// 定义鼠标消息
		while (MouseHit())  //这个函数用于检测当前是否有鼠标消息
		{
			m = GetMouseMsg();
			if (m.uMsg == WM_MOUSEMOVE)
			{
				// 飞机的位置等于鼠标所在的位置
				plane.x = m.x;
				plane.y = m.y;
			}
			else if (m.uMsg == WM_LBUTTONDOWN)
			{
				// 按下鼠标左键,发射子弹
				for (int i = 0; i < bullet_cnt; i++)
				{
					if (bullet[i].life == 0)
					{
						bullet[i].x = plane.x;
						bullet[i].y = plane.y - 53;
						bullet[i].life = 1;
						break;
					}
				}
				mciSendString("close fgmusic", NULL, 0, NULL); // 先把前面一次的音乐关闭
				mciSendString("open image/f_gun.mp3 alias fgmusic", NULL, 0, NULL); // 打开音乐
				mciSendString("play fgmusic", NULL, 0, NULL); // 仅播放一次
			}
		}
	}
}
void gameover()
{
	EndBatchDraw();
	_getch();
	closegraph();
}
void reset_plane()							//设置我方飞机的初始属性
{
	plane.x = Width * 0.5;
	plane.y = High * 0.7;
	plane.w = 91;
	plane.h = 106;
	plane.life = 10;								 //我方飞机的初始生命值
}
void reset_bullet()							//重置我方子弹 和 敌军子弹的大小
{
	for (int i = 0; i < bullet_cnt; i++)
	{
		if (bullet_rank == 0)
		{
			bullet[i].w = 8;
			bullet[i].h = 20;
		}
		else if (bullet_rank == 1)
		{
			bullet[i].w = 40;
			bullet[i].h = 36;
		}
		else if (bullet_rank == 2)
		{
			bullet[i].w = 65;
			bullet[i].h = 40;
		}
	}
	for (int i = 0; i < e_bullet_cnt; i++)
	{
		e_bullet[i].w = 8;
		e_bullet[i].h = 20;
	}
}
void reset_enemy(int i)									//设置敌机属性
{
	enemy[i].x = rand() % Width;
	enemy[i].y = -200;
	enemy[i].speed = rand() % 3;
	enemy[i].life = enemy_life;
	reset_e_bullet(enemy[i]);						//开始时生成一个敌人 就附加子弹
}
void reset_e_bullet(Enemy a)						//设置敌机子弹属性
{
	for (int i = 0; i < e_bullet_cnt; i++)
	{
		if (e_bullet[i].life == 0)
		{
			e_bullet[i].x = a.x + a.w / 2;
			e_bullet[i].y = a.y + a.h;
			e_bullet[i].speed = e_speed[a.speed] + 0.3;
			e_bullet[i].life = 1;
			break;
		}
	}
}
void reset_boss()									//设置boss属性
{
	boss.w = 200;
	boss.h = 213;
	boss.x = Width / 2 - boss.w / 2;
	boss.y = 0 - boss.h;
	boss.life = 100;
	boss.add_x = 0.7;
	boss.add_y = 0.3;
}
void reset_b_bullet(Boss_bullet a[3])				//设置boss属性
{
	for (int i = 0; i < 3; i++)
	{
		a[i].x = boss.x + boss.w / 2;
		a[i].y = boss.y + boss.h;
		a[i].add_y = 0.5;
		a[i].w = 8;
		a[i].h = 20;
		a[i].life = 1;
	}
	a[0].add_x = -0.5;
	a[1].add_x = 0;
	a[2].add_x = 0.5;
}
int is_crash(Enemy a, Bullet b)							//子弹和敌机是否相撞
{
	int rex = (a.w + b.w) / 2;
	int rey = (a.h + b.h) / 2;

	int lx = abs((int)(a.x + a.w / 2 - b.x - b.w / 2));
	int ly = abs((int)(a.y + a.h / 2 - b.y - b.h / 2));
	if (lx < rex &&ly < rey)
	{
		return 1;
	}
	return 0;
}
int is_crash_boss(Boss a, Bullet b)						//子弹和boss是否相撞
{
	int rex = (a.w + b.w) / 2;
	int rey = (a.h + b.h) / 2;

	int lx = abs((int)(a.x + a.w / 2 - b.x - b.w / 2));
	int ly = abs((int)(a.y + a.h / 2 - b.y - b.h / 2));
	if (lx < rex &&ly < rey)
	{
		return 1;
	}
	return 0;
}
int is_crash_plane(Plane a, Enemy_bullet b)				//敌机子弹是否和我方飞机相撞
{
	a.x -= a.w / 2;
	a.y -= a.h / 2;
	int rex = (a.w + b.w) / 2;
	int rey = (a.h + b.h) / 2;

	int lx = abs((int)(a.x + a.w / 2 - b.x - b.w / 2));
	int ly = abs((int)(a.y + a.h / 2 - b.y - b.h / 2));
	if (lx < rex &&ly < rey)
	{
		return 1;
	}
	return 0;
}
int is_crash_boss_plane(Plane a, Boss_bullet b)			//boss子弹是否和我方飞机相撞
{
	a.x -= a.w / 2;
	a.y -= a.h / 2;
	int rex = (a.w + b.w) / 2;
	int rey = (a.h + b.h) / 2;

	int lx = abs((int)(a.x + a.w / 2 - b.x - b.w / 2));
	int ly = abs((int)(a.y + a.h / 2 - b.y - b.h / 2));
	if (lx < rex &&ly < rey)
	{
		return 1;
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章