基于EasyX的飞机大战

 简单介绍

本项目是基于EasyX图形库实现的一个益智类小游戏,要求需要安装EasyX图形库,建议使用Visual Studio 2022编写项目,其他的编译器(DevC++,Clion)也有尝试过但都不能很好的调用EasyX。整个代码长度大概在800行左右,使用的编程语言是C语言(但是保存文件还是要保存为C++,因为EasyX是针对C++文件的),可以作为各位的一个程序设计小练习或者课程设计大作业。

安装介绍

各位可以参考一些博客安装Visual Studio 2022以及EasyX,下面是链接(但我是之前安装的,也没有尝试过,或许是正确的吧)。

Visual Studio 2022安装教程

EasyX库安装教程

素材获取

素材一部分是自己做的,还有一部分是在网上找的音乐

链接:https://pan.baidu.com/s/1J3atOYWCx-_igr9L3lf-lA?pwd=0wih 
提取码:0wih

运行截图

这里需要自己建立一个word文档存放每一次的游戏结果

全部代码

#include <graphics.h>		// 引用图形库头文件
# include<conio.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <windows.h>		//Windows API函数头文件
#include <mmsystem.h>		//和下方的comment一起作为播放音乐必备
#pragma comment(lib,"winmm.lib")	
#pragma warning(disable :4996)		//将警报4996置为失效,保证C的传统函数有效如:scanf


int score = 0, pause = 1, grenade = 5, gg = 0;  //分数,暂停,手雷,游戏结束
IMAGE bk, img_play[2], img_bull[2], img_empty[2][2], use[2]; //背景图,飞机,子弹,大小敌机,双弹道具


enum MyEnum {
	width = 800,
	heighth = 590,
	bullet_num = 15, //子弹的数量
	empty_num = 10,
	Big,	//大敌机,Big = 11
	Small	//小敌机,small = 12
};  //基础的数据

//图形坐标等飞机数据
typedef struct {
	char name[100];
	double x, y; // 飞机的移动坐标
	bool alive;  //判断是否存活
	int usage1;  //判断是否捡到道具1,双弹轨道
	int width1, heighth1, hp, type;
}Data;

void load_image();
void Start(Data* p1, Data* p2);
void Gamestart1(Data* p1, Data* p2, Data empty[], Data bull[], Data bull3[]);//gamestart信息初始化
void Gamestart2(Data bull[], Data bull3[], Data* u, Data* u2);
void Surrender(Data* p1, Data* p2);	//头像函数
int Gameover1(Data empty[], Data* p1);	//判断飞机是否坠落
int Gameover2(Data empty[], Data* p2);
void put_image1(Data* p1, Data bull[], Data bull1[], Data bull2[]);
void put_image2(Data* p2, Data bull3[], Data bull4[], Data bull5[]);
void put_image3(Data empty[], Data* u, Data* u2);	//敌机的出现
void put_words(Data* p1, Data* p2);	//游戏过程中的文字显示
void play1(Data empty[], Data* p1, Data bull[], Data bull1[], Data bull2[]);//两个玩家攻击敌机(每攻击一次血量-1)
void play2(Data empty[], Data* p2, Data bull3[], Data bull4[], Data bull5[]);
void play3(Data empty[], Data* p1, Data* p2, Data* u, Data* u2);//游戏得分的增加以及道具的使用
void Playermove(double speed, Data* p1, Data* p2);
void Creatbullet1(Data* p1, Data bull[], Data bull1[], Data bull2[]);//生成子弹(通过判断有没有拥有道具)
void Creatbullet2(Data* p2, Data bull3[], Data bull4[], Data bull5[]);
// 需要按键(空格或L)的操作
void bulletstart(Data* p1, Data* p2, Data bull[], Data bull1[], Data bull2[], Data bull3[], Data bull4[], Data bull5[], Data empty[]);
// 以某种speed去移动
void emptymove(double speed, Data empty[]);
void Createmptyhp(int i, Data empty[]);
void Creatempty(Data empty[]);
void Usage(Data* u, Data* u2, Data bull[], Data bull3[], Data* p1, Data* p2);
void bullet_move(Data* p1, Data* p2, Data bull[], Data bull1[], Data bull2[], Data bull3[], Data bull4[], Data bull5[]);
void the_end();
void input_scores(Data* p1, Data* p2);


//主函数
int main() {
	// 两个飞机,普通模式下飞机的子弹Bull和3,敌机,双弹模式下飞机的子弹1、2、4、5,Use1、2双弹模式的道具
	Data Player, Player2, Bull[bullet_num], Empty[empty_num], Use, Bull1[bullet_num], Bull2[bullet_num], Bull3[bullet_num], Bull4[bullet_num], Bull5[bullet_num], Use2;
	Data * p1 = &Player, * p2 = &Player2, *emp = Empty;
	Data * bu = Bull, * bu1 = Bull1, * bu2 = Bull2, * bu3 = Bull3, * bu4 = Bull4, * bu5 = Bull5;
	Data * u = &Use, * u2 = &Use2;

	//窗口创建
	load_image();	//加载图片
	Start(p1, p2);		//开始界面
	getchar();		//输入回车
	initgraph(width, heighth); //初始化图形界面
	Gamestart1(p1, p2, emp,bu,bu3);	//游戏开始
	Gamestart2(bu, bu3, u, u2);

	//双缓存绘图
	BeginBatchDraw();//先在内存中操作,知道遇到endbatchdraw才呈现在屏幕上
	while (Player.alive || Player2.alive) {
		Surrender(p1,p2);	//判断是否投降
		if (Gameover1(emp,p1))
			Player.alive = false;
		if (Gameover2(emp,p2))
			Player2.alive = false;
		put_image1(p1,bu,bu1,bu2);
		put_image2(p2,bu3,bu4,bu5);
		put_image3(emp, u, u2);
		put_words(p1,p2);
		FlushBatchDraw();//在这里需要继续呈现,所以用到了flushbatchdraw
		play1(emp,p1,bu,bu1,bu2);		//判断敌机是否存在
		play2(emp,p2,bu3,bu4,bu5);
		play3(emp,p1,p2,u,u2);
		static int t3 = 0, t4 = 0;//计时器
		//无堵塞时,无法控制按键P的次数,使用计时器来阻塞
		if (t4 - t3 > 200) {
			if (GetAsyncKeyState('P'))
				pause++;
			t3 = t4;
		}
		t4 = clock();
		//游戏的退出(在暂停模式下)
		if (pause % 2 == 0) {
			if (GetAsyncKeyState('E')) {
				gg = 1;
			}
		}
		if (pause % 2 != 0) {
			Playermove(0.5, p1, p2);
			bulletstart(p1,p2,bu,bu1,bu2,bu3,bu4,bu5,emp);
			emptymove(0.3,emp);
			//间隔900ms让敌机挨个生成
			static int t1 = 0, t2 = 0;//计时器
			if (t2 - t1 > 900) {
				Creatempty(emp);
				t1 = t2;
			}
			t2 = clock();
		}
		Usage(u,u2,bu,bu3,p1,p2);
		bullet_move(p1,p2,bu,bu1,bu2,bu3,bu4,bu5);
	}
	EndBatchDraw();

	the_end();
	input_scores(p1,p2);
	getchar();//回车游戏结束
	return 0;
}

//加载图片
void load_image() {
	//背景图
	loadimage(&bk, "D://飞机大战//飞机大战//飞机大战素材//background.jpg"); //背景图片
	//实现透明贴图
	loadimage(&img_play[0], "D://飞机大战//飞机大战//飞机大战素材//掩码图1.jpg"); //掩码图
	loadimage(&img_play[1], "D://飞机大战//飞机大战//飞机大战素材//素材1.jpg"); //源码图

	loadimage(&img_bull[0], "D://飞机大战//飞机大战//飞机大战素材//掩码图4.jpg"); //子弹的掩码图
	loadimage(&img_bull[1], "D://飞机大战//飞机大战//飞机大战素材//素材4.jpg"); //源码图

	loadimage(&img_empty[0][0], "D://飞机大战//飞机大战//飞机大战素材//掩码图5.jpg"); //小型敌机掩码图
	loadimage(&img_empty[0][1], "D://飞机大战//飞机大战//飞机大战素材//素材5.jpg"); //小型敌机源码图

	loadimage(&img_empty[1][0], "D://飞机大战//飞机大战//飞机大战素材//掩码图2.jpg"); //大型敌机
	loadimage(&img_empty[1][1], "D://飞机大战//飞机大战//飞机大战素材//素材2.jpg");//源码图

	loadimage(&use[0], "D://飞机大战//飞机大战//飞机大战素材//掩码图3.jpg"); //道具
	loadimage(&use[1], "D://飞机大战//飞机大战//飞机大战素材//素材3.jpg"); //道具
}

//开始界面和操作介绍
void Start(Data* p1, Data* p2) {
	initgraph(width, heighth);	//改变窗口信息,wigth*heighth
	putimage(0, 0, &bk);	// https://blog.csdn.net/firetaker/article/details/5582376输出图像函数
	setbkmode(TRANSPARENT);	// https://blog.csdn.net/magicsutra/article/details/1886992文字背景透明
	settextcolor(RGB(rand() % 256, rand() % 256, rand() % 256));
	settextstyle(20, 0, "楷体");
	char intro[] = "玩法介绍";	//introduction
	char intro1[] = "玩家一:W-A-S-D移动,空格射击";
	char intro2[] = "玩家二:↑↓←→移动,L键射击";
	char intro3[] = "内置道具,请按回车,继续游戏";
	char intro4[] = "J键手雷,P键暂停,E键退出(暂停之后)";
	char intro5[] = "玩家一V键投降,玩家二M键投降";
	char* Int = intro, * Int1 = intro1, * Int2 = intro2,
		* Int3 = intro3, * Int4 = intro4, * Int5 = intro5;
	outtextxy(370, 150, Int); //注意汉字和英文字符所占的像素大小
	outtextxy(275, 190, Int1);	//汉字16*16,英文16*8
	outtextxy(275, 230, Int2);
	outtextxy(240, 270, Int4);
	outtextxy(275, 310, Int5);
	outtextxy(275, 350, Int3);
	InputBox(p1->name, 100, "请输入玩家一的用户名");
	InputBox(p2->name, 100, "请输入玩家二的用户名");
}

//敌方HP,初始化,20%的概率大敌机
void Createmptyhp(int i, Data empty[]) { //第i个敌机
	if (rand() % 10 <= 1) {
		empty[i].type = Big;
		empty[i].hp = 3;
		empty[i].width1 = 104;//初始化图片大小
		empty[i].heighth1 = 148;
	}
	else {
		empty[i].type = Small;
		empty[i].hp = 1;
		empty[i].heighth1 = 39;
		empty[i].width1 = 52;
	}
}

//初始化
void Gamestart1(Data* p1, Data* p2, Data empty[], Data bull[], Data bull3[]) {
	srand((int)time(NULL));  //实现随机
	//玩家信息初始化
	p1->x = width / 2 - 200;
	p1->y = heighth - 120;
	p1->usage1 = 0; //玩家未获得道具1
	p1->alive = true;
	p2->x = width / 2 + 100;
	p2->y = heighth - 120;
	p2->usage1 = 0; //玩家2未获得道具1
	p2->alive = true;
	//初始化子弹
	for (int i = 0; i < bullet_num; i++) {
		bull[i].alive = false;
		bull[i].x = 0;
		bull[i].y = 0;
		bull3[i].alive = 0;
		bull3[i].x = 0;
		bull3[i].y = 0;
	}
	//初始化敌机
	for (int i = 0; i < empty_num; i++) {
		empty[i].alive = false;
		Createmptyhp(i, empty);
	}

}
//初始化子弹
void Gamestart2(Data bull[], Data bull3[], Data* u, Data* u2) {
	for (int i = 0; i < bullet_num; i++) {
		bull[i].alive = false;
		bull[i].x = 0;
		bull[i].y = 0;
		bull3[i].alive = 0;
		bull3[i].x = 0;
		bull3[i].y = 0;
	}
	u->alive = false; //两个玩家的道具获取状态
	u2->alive = false;
}

//投降函数
void Surrender(Data* p1, Data* p2) {
	if (p1->alive) {
		if (GetAsyncKeyState('V'))
			p1->alive = false;
	}
	if (p2->alive) {
		if (GetAsyncKeyState('M'))
			p2->alive = false;
	}
}

//产生敌机
void Creatempty(Data empty[]) {
	for (int i = 0; i < empty_num; i++) {
		if (!empty[i].alive) {//Empty[i].alive = false,对应95行
			empty[i].alive = true;
			empty[i].y = 0;
			empty[i].x = rand() % (width - 60);
			Createmptyhp(i, empty);
			break;
		}
	}
}

//输出图片,去掉白边
void put_image1(Data* p1, Data bull[], Data bull1[], Data bull2[]) {
	putimage(0, 0, &bk);
	//玩家一
	if (p1->alive) {
		putimage(p1->x, p1->y, &img_play[0], NOTSRCERASE);  //掩码图,putimage(left,top,buf,op)
		putimage(p1->x, p1->y, &img_play[1], SRCINVERT);  //源码图
	}
	//子弹,player.usage1判断双弹模式
	if (p1->usage1 == 0) {
		for (int i = 0; i < bullet_num; i++) {
			if (bull[i].alive) {
				putimage(bull[i].x, bull[i].y, &img_bull[0], NOTSRCERASE);
				putimage(bull[i].x, bull[i].y, &img_bull[1], SRCINVERT);
			}
		}
	}
	else {
		for (int i = 0; i < bullet_num; i++) {
			if (bull1[i].alive) {
				putimage(bull1[i].x, bull1[i].y, &img_bull[0], NOTSRCERASE);
				putimage(bull1[i].x, bull1[i].y, &img_bull[1], SRCINVERT);
			}
			if (bull2[i].alive) {
				putimage(bull2[i].x, bull2[i].y, &img_bull[0], NOTSRCERASE);
				putimage(bull2[i].x, bull2[i].y, &img_bull[1], SRCINVERT);
			}
		}
	}
}
//玩家2
void put_image2(Data* p2, Data bull3[], Data bull4[], Data bull5[]) {
	if (p2->alive) {
		putimage(p2->x, p2->y, &img_play[0], NOTSRCERASE);  //掩码图
		putimage(p2->x, p2->y, &img_play[1], SRCINVERT);  //源码图
	}
	// 玩家2的子弹
	if (p2->usage1 == 0) {
		for (int i = 0; i < bullet_num; i++) {
			if (bull3[i].alive) {
				putimage(bull3[i].x, bull3[i].y, &img_bull[0], NOTSRCERASE);
				putimage(bull3[i].x, bull3[i].y, &img_bull[1], SRCINVERT);
			}
		}
	}
	else {
		for (int i = 0; i < bullet_num; i++) {
			if (bull4[i].alive) {
				putimage(bull4[i].x, bull4[i].y, &img_bull[0], NOTSRCERASE);
				putimage(bull4[i].x, bull4[i].y, &img_bull[1], SRCINVERT);
			}
			if (bull5[i].alive) {
				putimage(bull5[i].x, bull5[i].y, &img_bull[0], NOTSRCERASE);
				putimage(bull5[i].x, bull5[i].y, &img_bull[1], SRCINVERT);
			}
		}
	}
}

//敌机和道具的出现
void put_image3(Data empty[], Data* u, Data* u2) {
	// 敌机出现
	for (int i = 0; i < empty_num; i++) {
		if (empty[i].alive) {
			if (empty[i].type == Big) {
				putimage(empty[i].x, empty[i].y, &img_empty[1][0], NOTSRCERASE);
				putimage(empty[i].x, empty[i].y, &img_empty[1][1], SRCINVERT);
			}
			else {
				putimage(empty[i].x, empty[i].y, &img_empty[0][0], NOTSRCERASE);
				putimage(empty[i].x, empty[i].y, &img_empty[0][1], SRCINVERT);
			}
		}
	}
	//道具出现
	if (u->alive) {
		putimage(u->x, u->y, &use[0], NOTSRCERASE);
		putimage(u->x, u->y, &use[1], SRCINVERT);
	}
	if (u2->alive) {
		putimage(u2->x, u2->y, &use[0], NOTSRCERASE);
		putimage(u2->x, u2->y, &use[1], SRCINVERT);
	}
}

//文字显示
void put_words(Data* p1, Data* p2) {
	//打印分数
	char scores[100] = "";
	sprintf(scores, "当前分数:%d", score);		//sprintf函数的使用
	outtextxy(0, 20, scores);
	setbkmode(TRANSPARENT);		//透明模式的文字
	settextcolor(BLUE);
	settextstyle(20, 0, "楷体");
	char tip[100] = "";
	sprintf(tip, "已获得双弹道加成");
	if (p1->usage1 || p2->usage1) {
		outtextxy(0, 80, tip);
	}
	if (p1->alive) {
		outtextxy(p1->x + 25, p1->y - 20, p1->name);
	}
	if (p2->alive) {
		outtextxy(p2->x + 25, p2->y - 20, p2->name);
	}
	char tip2[100] = "";
	sprintf(tip2, "当前手雷数量:%d", grenade);
	outtextxy(0, 50, tip2);
	char tips[100] = "";
	if (pause % 2 == 0) {
		sprintf(tips, "游戏已暂停");
		outtextxy(360, 250, tips);
	}
}

//敌机移动
void emptymove(double speed, Data empty[]) {
	for (int i = 0; i < empty_num; i++) {
		if (empty[i].alive) {
			empty[i].y += speed;
			if (empty[i].y >= heighth) {
				empty[i].alive = false;
			}
		}
	}
}


//玩家1生成子弹
void Creatbullet1(Data* p1, Data bull[], Data bull1[], Data bull2[]) {
	//普通模式
	if (p1->usage1 == 0) {
		for (int i = 0; i < bullet_num; i++) {
			if (!bull[i].alive) {//Bull[i].alive == false
				bull[i].alive = true;
				bull[i].x = p1->x + 43;
				bull[i].y = p1->y;
				break;
			}
		}
	}
	//双弹模式
	else {
		for (int i = 0; i < bullet_num; i++) {
			if (!bull1[i].alive) {
				bull1[i].alive = true;
				bull1[i].x = p1->x + 37;
				bull1[i].y = p1->y;
				break;//跳出循环,非常重要
			}
		}
		for (int i = 0; i < bullet_num; i++) {
			if (!bull2[i].alive) {
				bull2[i].alive = true;
				bull2[i].x = p1->x + 49;
				bull2[i].y = p1->y;
				break;
			}
		}
	}
}


//玩家二生成子弹
void Creatbullet2(Data* p2, Data bull3[], Data bull4[], Data bull5[]) {
	//普通模式
	if (p2->usage1 == 0) {
		for (int i = 0; i < bullet_num; i++) {
			if (!bull3[i].alive) {
				bull3[i].alive = true;
				bull3[i].x = p2->x + 43;
				bull3[i].y = p2->y;
				break;
			}
		}
	}
	//双弹模式
	else {
		for (int i = 0; i < bullet_num; i++) {
			if (!bull4[i].alive) {
				bull4[i].alive = true;
				bull4[i].x = p2->x + 37;
				bull4[i].y = p2->y;
				break;
			}
		}
		for (int i = 0; i < bullet_num; i++) {
			if (!bull5[i].alive) {
				bull5[i].alive = true;
				bull5[i].x = p2->x + 49;
				bull5[i].y = p2->y;
				break;
			}
		}
	}
}


//子弹移动
void bullet_move(Data* p1, Data* p2, Data bull[], Data bull1[], Data bull2[], Data bull3[], Data bull4[], Data bull5[]) {
	//玩家1
	//普通模式
	if (p1->usage1 == 0) {
		for (int i = 0; i < bullet_num; i++) {
			if (bull[i].alive) {
				bull[i].y -= 1;
				if (bull[i].y <= 0) {
					bull[i].alive = false;
				}
			}
		}
	}
	//双弹模式
	else {
		for (int i = 0; i < bullet_num; i++) {
			if (bull1[i].alive) {
				bull1[i].y -= 1;
				if (bull1[i].y <= 0) {
					bull1[i].alive = false;
				}
			}
		}
		for (int i = 0; i < bullet_num; i++) {
			if (bull2[i].alive) {
				bull2[i].y -= 1;
				if (bull2[i].y <= 0) {
					bull2[i].alive = false;
				}
			}
		}
	}
	//玩家2
	//普通模式
	if (p2->usage1 == 0) {
		for (int i = 0; i < bullet_num; i++) {
			if (bull3[i].alive) {
				bull3[i].y -= 1;
				if (bull3[i].y <= 0) {
					bull3[i].alive = false;
				}
			}
		}
	}
	//双弹模式
	else {
		for (int i = 0; i < bullet_num; i++) {
			if (bull4[i].alive) {
				bull4[i].y -= 1;
				if (bull4[i].y <= 0) {
					bull4[i].alive = false;
				}
			}
		}
		for (int i = 0; i < bullet_num; i++) {
			if (bull5[i].alive) {
				bull5[i].y -= 1;
				if (bull5[i].y <= 0) {
					bull5[i].alive = false;
				}
			}
		}
	}
}


//飞机移动,按键移动
void Playermove(double speed, Data* p1, Data* p2) {
	//不使用_kihib()防止阻塞,导致移动的不顺畅
	if (GetAsyncKeyState('W') && 0x57) {	//https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-getasynckeystate?redirectedfrom=MSDN
		if (p1->y > 0)
			p1->y -= speed;//上面的y坐标小
	}
	if (GetAsyncKeyState('S') && 0x53) {		//getasynckeystate函数好像&按与操作符没用
		if (p1->y + 120 < heighth)
			p1->y += speed;
	}
	if (GetAsyncKeyState('A') && 0x41) {
		if (p1->x + 50 > 0)
			p1->x -= speed;
	}
	if (GetAsyncKeyState('D') && 0x44) {
		if (p1->x + 60 < width)
			p1->x += speed;
	}
	//玩家2移动实现
	if (GetAsyncKeyState(VK_UP) && 0x8000) {
		if (p2->y > 0)
			p2->y -= speed;//上面的y坐标小
	}
	if (GetAsyncKeyState(VK_DOWN) && 0x8000) {
		if (p2->y + 120 < heighth)
			p2->y += speed;
	}
	if (GetAsyncKeyState(VK_LEFT) && 0x8000) {
		if (p2->x + 50 > 0)
			p2->x -= speed;
	}
	if (GetAsyncKeyState(VK_RIGHT) && 0x8000) {
		if (p2->x + 60 < width)
			p2->x += speed;
	}
}
void bulletstart(Data* p1, Data* p2, Data bull[], Data bull1[], Data bull2[], Data bull3[], Data bull4[], Data bull5[], Data empty[]) {
	//发射子弹
	//定时器原理https://blog.csdn.net/Faith_cxz/article/details/122388113
	static int t1 = 0, t2 = 0;
	//space间隔>350ms执行
	if (p1->alive) {
		if (GetAsyncKeyState(VK_SPACE) && t2 - t1 > 350) {
			mciSendString("close gun", 0, 0, 0);
			mciSendString("open D://飞机大战//子弹音效.mp3 alias gun", 0, 0, 0);	//子弹音乐
			mciSendString("play gun", 0, 0, 0);
			Creatbullet1(p1, bull, bull1, bull2);
			t1 = t2;
		}
		t2 = clock();
	}
	//玩家2
	if (p2->alive) {
		static int t5 = 0, t6 = 0;
		if (GetAsyncKeyState('L') && t6 - t5 > 350) {
			mciSendString("close gun", 0, 0, 0);
			mciSendString("open D://飞机大战//子弹音效.mp3 alias gun", 0, 0, 0);	//插入音乐
			mciSendString("play gun", 0, 0, 0);
			Creatbullet2(p2, bull3, bull4, bull5);
			t5 = t6;
		}
		t6 = clock();
	}
	//使用手雷
	static int t3 = 0, t4 = 0;
	if (GetAsyncKeyState('J') && t4 - t3 > 350) {
		if (grenade > 0) {
			grenade--;
			mciSendString("close w", 0, 0, 0);
			mciSendString("open D://飞机大战//手雷.mp3 alias w", 0, 0, 0);
			mciSendString("play w", 0, 0, 0);
			for (int i = 0; i < empty_num; i++) {
				if (empty[i].alive) {
					empty[i].hp--;
				}
			}//手雷效果:全部血量-1
		}
		t3 = t4;
	}
	t4 = clock();
}

//击中敌机

void play1(Data empty[], Data* p1, Data bull[], Data bull1[], Data bull2[]) {
	for (int i = 0; i < empty_num; i++) {
		if (!empty[i].alive)
			continue;		//敌机首先存在
		for (int j = 0; j < bullet_num; j++) {
			if (p1->usage1 == 0) {//单轨道
				if (!bull[j].alive)
					continue;
				if (bull[j].x > empty[i].x - 10 && bull[j].x<empty[i].x + empty[i].width1 && bull[j].y>empty[i].y && bull[j].y < empty[i].y + empty[i].heighth1) {
					bull[j].alive = false;
					empty[i].hp--;
				}
			}
			else {
				if (!bull1[j].alive)
					continue;
				if (bull1[j].x > empty[i].x - 10 && bull1[j].x<empty[i].x + empty[i].width1 && bull1[j].y>empty[i].y && bull1[j].y < empty[i].y + empty[i].heighth1) {
					bull1[j].alive = false;
					empty[i].hp--;
				}
				if (!bull2[j].alive)
					continue;
				if (bull2[j].x > empty[i].x - 10 && bull2[j].x<empty[i].x + empty[i].width1 && bull2[j].y>empty[i].y && bull2[j].y < empty[i].y + empty[i].heighth1) {
					bull2[j].alive = false;
					empty[i].hp--;
				}
			}
		}
	}
}

void play2(Data empty[], Data* p2, Data bull3[], Data bull4[], Data bull5[]) {
	for (int i = 0; i < empty_num; i++) {
		if (!empty[i].alive)
			continue;		//敌机首先存在
		//玩家2
		for (int j = 0; j < bullet_num; j++) {
			if (p2->usage1 == 0) {
				if (!bull3[j].alive)
					continue;
				if (bull3[j].x > empty[i].x - 10 && bull3[j].x<empty[i].x + empty[i].width1 && bull3[j].y>empty[i].y && bull3[j].y < empty[i].y + empty[i].heighth1) {
					bull3[j].alive = false;
					empty[i].hp--;
				}
			}
			else {
				if (!bull4[j].alive)
					continue;
				if (bull4[j].x > empty[i].x - 10 && bull4[j].x<empty[i].x + empty[i].width1 && bull4[j].y>empty[i].y && bull4[j].y < empty[i].y + empty[i].heighth1) {
					bull4[j].alive = false;
					empty[i].hp--;
				}
				if (!bull5[j].alive)
					continue;
				if (bull5[j].x > empty[i].x - 10 && bull5[j].x<empty[i].x + empty[i].width1 && bull5[j].y>empty[i].y && bull5[j].y < empty[i].y + empty[i].heighth1) {
					bull5[j].alive = false;
					empty[i].hp--;
				}
			}
		}
	}
}

void play3(Data empty[], Data* p1, Data* p2, Data* u, Data* u2) {
	for (int i = 0; i < empty_num; i++) {
		if (!empty[i].alive)
			continue;		//敌机首先存在
		if (empty[i].hp <= 0) {
			if (empty[i].type == Big)
				score += 50;
			else
				score += 10;
			//产生道具(双弹道)
			if ((p1->usage1 == 0 && p1->alive == true) || (p2->usage1 == 0 && p2->alive == true)) {
				if (rand() % 21 <= 1) {
					if (!(u->alive)) {
						u->x = empty[i].x;
						u->y = empty[i].y;
						u->alive = true;
					}
				}
				if (rand() % 21 <= 1 && u->alive == false) {
					if (!(u2->alive)) {
						u2->x = empty[i].x;
						u2->y = empty[i].y;
						u2->alive = true;
					}
				}
			}
			empty[i].alive = false;
			mciSendString("close YI", 0, 0, 0);
			mciSendString("open D://飞机大战//敌机爆炸.mp3 alias YI", 0, 0, 0);	//敌机爆炸
			mciSendString("play YI", 0, 0, 0);
		}
	}
}

//双弹道
void Usage(Data* u, Data* u2, Data bull[], Data bull3[], Data* p1, Data* p2) {
	if (u->alive == true && p1->usage1 == 0) {
		for (int i = 0; i < bullet_num; i++) {
			if (bull[i].x > (u->x - 50) && bull[i].x<(u->x + 50) && bull[i].y>(u->y) && bull[i].y < (u->y + 50) && bull[i].alive == true) {
				bull[i].alive = false;
				p1->usage1 = 1;
				u->alive = false;
				mciSendString("close cc", 0, 0, 0);
				mciSendString("open D://飞机大战//双弹道.mp3 alias cc", 0, 0, 0);
				mciSendString("play cc", 0, 0, 0);
			}
		}
	}
	//玩家2
	if (u->alive == true && p2->usage1 == 0) {
		for (int i = 0; i < bullet_num; i++) {
			if (bull3[i].x > (u->x - 50) && bull3[i].x<(u->x + 50) && bull3[i].y>(u->y) && bull3[i].y < (u->y + 50) && bull3[i].alive == true) {
				bull3[i].alive = false;
				p2->usage1 = 1;
				u->alive = false;
				mciSendString("close cc", 0, 0, 0);
				mciSendString("open D://飞机大战//双弹道.mp3 alias cc", 0, 0, 0);
				mciSendString("play cc", 0, 0, 0);
			}
		}
	}
	if (u2->alive == true && p2->usage1 == 0) {
		for (int i = 0; i < bullet_num; i++) {
			if (bull3[i].x > (u2->x - 50) && bull3[i].x<(u2->x + 50) && bull3[i].y>(u2->y) && bull3[i].y < (u2->y + 50) && bull3[i].alive == true) {
				bull3[i].alive = false;
				p2->usage1 = 1;
				u2->alive = false;
				mciSendString("close cc", 0, 0, 0);
				mciSendString("open D://飞机大战//双弹道.mp3 alias cc", 0, 0, 0);
				mciSendString("play cc", 0, 0, 0);
			}
		}
	}
	if (u2->alive == true && p1->usage1 == 0) {
		for (int i = 0; i < bullet_num; i++) {
			if (bull[i].x > (u2->x - 50) && bull[i].x<(u2->x + 50) && bull[i].y>(u2->y) && bull[i].y < (u2->y + 50) && bull[i].alive == true) {
				bull[i].alive = false;
				p1->usage1 = 1;
				u2->alive = false;
				mciSendString("close cc", 0, 0, 0);
				mciSendString("open D://飞机大战//双弹道.mp3 alias cc", 0, 0, 0);
				mciSendString("play cc", 0, 0, 0);
			}
		}
	}
}

//游戏结束
int Gameover1(Data empty[], Data* p1) {
	for (int i = 0; i < empty_num; i++) {
		if (!empty[i].alive)
			continue;
		if (p1->x + 50 > empty[i].x && p1->x<empty[i].x + empty[i].width1 + 50 && p1->y>empty[i].y && p1->y < empty[i].y + empty[i].heighth1) {
			return 1;
		}
	}
	if (gg) {
		return 1;
	}
	return 0;
}

int Gameover2(Data empty[], Data* p2) {
	for (int i = 0; i < empty_num; i++) {
		if (!empty[i].alive)
			continue;
		if (p2->x + 50 > empty[i].x && p2->x<empty[i].x + empty[i].width1 + 50 && p2->y>empty[i].y && p2->y < empty[i].y + empty[i].heighth1) {
			return 1;
		}
	}
	if (gg) {
		return 1;
	}
	return 0;
}

//结束界面
void the_end() {
	initgraph(width, heighth);
	putimage(0, 0, &bk);
	char scores[100] = "";
	char word[100] = "";
	setbkmode(TRANSPARENT);
	settextcolor(RGB(rand() % 256, rand() % 256, rand() % 256));
	settextstyle(20, 0, "楷体");
	sprintf(word, "游戏结束");
	outtextxy(370, 250, word);
	sprintf(scores, "您的最终成绩是:%d", score);
	outtextxy(330, 310, scores);
}
void input_scores(Data* p1, Data* p2) {
	FILE* fp;
	fp = fopen("D://飞机大战//游戏结果.txt", "a");
	fprintf(fp, "%s , %s 两个玩家得分为: %d\n", p1->name, p2->name, score);
	fclose(fp);
}//输出得分

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在 easyx 飞机大战中,发射激光的实现需要以下几个步骤: 1. 定义激光的结构体,包括激光的坐标、速度、颜色、是否有效等属性。 2. 玩家飞机发射激光的实现,可以在玩家按下特定按键时,在玩家飞机的位置创建一个激光,并将其加入到激光数组中。 3. 激光的移动实现,每帧更新激光的坐标位置,将超出窗口范围或者已经击中敌机的激光标记为无效。 4. 检测激光是否与敌机相撞,如果相撞,则将激光标记为无效,并将敌机的生命值减少。 下面是一个简单的示例代码,展示了如何实现激光的发射和移动: ```cpp struct Laser { int x, y; // 激光的坐标 int speed; // 激光的速度 COLORREF color; // 激光的颜色 bool valid; // 激光是否有效 }; const int MAX_LASER_NUM = 20; Laser lasers[MAX_LASER_NUM]; // 激光数组 void shootLaser() { for (int i = 0; i < MAX_LASER_NUM; i++) { if (!lasers[i].valid) { lasers[i].x = player.x; lasers[i].y = player.y - 20; // 发射位置在飞机上方 lasers[i].speed = 10; lasers[i].color = RED; lasers[i].valid = true; break; } } } void updateLasers() { for (int i = 0; i < MAX_LASER_NUM; i++) { if (lasers[i].valid) { lasers[i].y -= lasers[i].speed; if (lasers[i].y < 0) { lasers[i].valid = false; } else { for (int j = 0; j < MAX_ENEMY_NUM; j++) { if (enemies[j].valid && IsCollided(enemies[j], lasers[i])) { enemies[j].valid = false; lasers[i].valid = false; break; } } } } } } ``` 注意,这只是一个简单的示例代码,实际实现中还需要考虑更多细节,如激光与敌机的碰撞检测、激光的发射速度、激光的数量限制等等。 ### 回答2: 在EasyX飞机大战游戏中,发射激光可以通过简单的编程实现。具体操作如下: 1. 在游戏中选择一个飞机作为主角飞机,在主循环中捕获键盘事件。 2. 使用GetAsyncKeyState函数来检测玩家是否按下了空格键,如果按下,则表示发射激光。 3. 在按下空格键后,创建一个激光对象,具体可以使用一个自定义的结构体来表示激光,该结构体包括激光的坐标、速度和绘制标志等属性。 4. 将新创建的激光对象添加到一个激光对象数组中,用来保存当前所有的激光对象。 5. 在主循环中更新激光对象数组中的所有激光对象,根据激光的速度更新激光的坐标位置。 6. 在主循环中绘制激光对象数组中的所有激光对象,根据激光的坐标位置在游戏窗口中绘制激光。 7. 在绘制激光时,可以使用EasyX提供的绘图函数实现,比如使用Line函数绘制一条直线来表示激光。 通过以上步骤,就可以在EasyX飞机大战游戏中实现激光的发射效果。玩家按下空格键后,会在飞机前方出现一个激光,随着时间的推移,激光会向前移动并逐渐消失。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值