c++课程设计:飞机大战(图形化界面)

飞机大战.cpp

#include <iostream>
#include <graphics.h>
#include <time.h>
#include <vector>
#include "Plane.h"
#include "runtime.h"
using namespace std;

int main()
{
	bool sign = false;						//标记我方爆炸效果显示
	bool state = false;						//记录游戏结束时的状态
	bool boss_sign = false;					//BOSS标记
	MUSIC music;							//音乐对象
	Plane_my myplane;					//我方飞机对象
	vector<Plane_enemy> enemy_planevec;			//敌人飞机对象数组
	PIMAGE gamebackground = newimage();			//背景图片

	begingame();							//游戏开始界面
	playmusic(music);						//播放音乐函数
	srand(time(NULL));						//随机种子,随机数用在敌人飞机xy坐标与飞机属性上
	getimage(gamebackground, "F:\\visual studio projects\\飞机大战\\图片素材\\背景2.png");
	setimage(500, 800, gamebackground);			//设置背景图片大小
	

	for (int i = 0; i < 2; i++)//产生1个小兵
	{
		Plane_enemy enemy_plane(rand() % 2 + 1);//敌人只可能出现小兵和精英兵
		enemy_planevec.push_back(enemy_plane);	//插入进数组
	}

	while (true)//死循环,直到游戏结束
	{
		putimage(0, 0, gamebackground);			//输出背景图片
		//遍历所有敌人
		for (vector<Plane_enemy>::iterator it = enemy_planevec.begin(); it != enemy_planevec.end(); it++)
		{
			if (it->getenemy_prop() == 4 && it->gethealth() <= 50)	//如果击败最终BOSS游戏胜利
			{
				state = true;				//游戏以胜利状态退出
				delimage(gamebackground);						//释放背景图片对象
				endgame(state, myplane);			//游戏结束界面
				return 0;
			}

			it->move();						//敌方飞机移动

			if (it->setgetp_y() >= 760)
			{
				it->setgetp_x() = rand() % 380;
				it->setgetp_y() = -(rand() % 101 + 200);
			}

			//判断每一个敌人的飞机的子弹是否和我方飞机坐标重合
			enemy_bullet_hit(it, myplane, sign, myplane.setgetlifenum());
		}

		if (myplane.setgetscore()==0 % 10 && myplane.setgetscore()!=0)		//得分是10的倍数且不为0的时候额外增加一个敌人
		{
			Plane_enemy enemy_plane(rand() % 2 + 1);	//敌人只可能出现小兵和精英兵
			enemy_planevec.push_back(enemy_plane);		//插入进数组
			myplane.setgetscore()++;				//得分额外加1
			myplane.setgetshieldnum() += 2;		//获得两次护盾使用次数
		}

		if (myplane.move(enemy_planevec, sign) == true)		//我方飞机移动,参数为敌人飞机数组、标记、返回真时表示我方飞机阵亡,以失败退出游戏
		{//返回值为true时,以游戏失败状态退出循环
			state = false;
			endgame(state,myplane);
		}

		//得分到达上限则清空所有敌人,挑战最终BOSS
		if ((myplane.setgetscore()) >= 120 && boss_sign==false)		//得分大于120且标记为false时执行产生最终boss
		{
			enemy_planevec.clear();				//清空所有敌人
			myplane.setgetunskillnum()++;	//必杀次数+1
			Plane_enemy enemy_plane(4);				//BOSS
			enemy_planevec.push_back(enemy_plane);	//将BOSS插入进敌人数组中
			boss_sign = true;					//只执行一次这段if代码
		}

		delay_fps(60);
	}

	return 0;
}

runtime.h

#pragma once
#include <graphics.h>
#include "Plane.h"

void setimage(int pwidth, int pheight, PIMAGE img_1);//设置图片对象宽高函数
void begingame();//游戏开始
void endgame(bool sign, Plane_my& myplane);//游戏结束界面
void enemy_bullet_hit(vector<Plane_enemy>::iterator it, Plane_my& myplane, bool& sign, int& lifenum);//判断敌方子弹与我方飞机重合函数
void playmusic(MUSIC& music);//播放音乐函数

Plane.h

#pragma once
#include <graphics.h>
#include <ctime>
#include <vector>
using namespace std;


struct bulxy//子弹
{
	int b_x;
	int b_y;			
	int prop;//子弹的属性
};

class Plane//飞机类
{
public:
	int health;							//飞机血量
	int getwidth();						//获取飞机宽
	int getheight();					//获取飞机高
	Plane();
protected:
	int width, height;					//飞机的宽高
	int p_x, p_y;						//飞机横纵坐标
	clock_t now_1;						//发射子弹开始时间
	clock_t now_2;						//发射子弹后时间
	int timediff;						//发射子弹时间差 now_2 - 1
	int sign;							//区分飞机变量

	bulxy temp;							//用于向数组中插入结构
	vector <bulxy> bullvec;				//子弹动态数组
};

class Plane_enemy : public Plane
{
public:
	int& setgetp_x();					//获取和修改敌人飞机xy坐标值
	int& setgetp_y();
	int getenemy_prop();					//获取和敌人的prop属性*****
	int gethealth();					//获取敌人血量值
	vector<bulxy>& getenemy_bullvec();	//获取敌人的子弹数组
	Plane_enemy(int prop);				//根据参数,为敌人飞机对象初始化坐标、血量、图片信息
	void move();						//敌人移动

private:
	PIMAGE enemy_img_1;		//敌人小兵
	PIMAGE bulletimg;		//子弹图片对象
	int planeprop;					//飞机属性
	int speed_x, speed_y;		//子弹速度每帧x轴和y轴移动单位数
	int attack;						//敌机攻速(攻击间隔)

	inline void pushlaunch();			//向数组插入\新建子弹
	inline void attackspeed();			//子弹发射速度
	inline void laumoveunit();			//子弹速度函数
	inline void laudire();				//子弹移动方向函数
	inline void laushow();				//显示子弹函数
	inline void laudelete();			//删除越界子弹函数
	void planlaunch();					//封装所有子弹相关函数
};

class Plane_my :public Plane
{
private:
	const PIMAGE findplaneimg;	//我方飞机图片对象
	const PIMAGE bulletimg;	//子弹图片对象
	const PIMAGE shieldimg;	//护盾图片对象
	const PIMAGE shieldicon;	//护盾图标
	const PIMAGE unskillimg;	//必杀图片对象
	const PIMAGE unskillicon;	//必杀图标
	char key;							//接收键值
	int inerdis;						//飞机惯性走的距离
	bool sign;						//是否播放爆炸效果
	int atemp;							//记录子弹爆炸效果的次数
	int btarg_x, btarg_y;			//记录集中敌人的子弹位置
	int btemp;							//记录自身爆炸效果的次数
	int score;							//游戏得分
	bool shieldsign;				//标记护盾开启
	clock_t shiledtime_1;				//记录护盾时间
	clock_t shiledtime_2;
	int shieldnum;						//护盾使用次数
	bool unskillsign;				//标记必杀开启
	clock_t unskilltime_1;				//记录必杀时间
	clock_t unskilltime_2;
	int unskillnum;						//必杀技使用次数
	bool upgrade;					//飞机是否已升级
	int lifenum;						//我方飞机的生命数量
	PIMAGE explimgarr[3];			//爆炸效果图片对象数组
	int i;								//用于循环
	MUSIC music;							//音乐对象

	
	void alterbullplan();//升级飞机和子弹外观
	
	void pushlaunch();//新建子弹
	
	inline void launmove();//子弹移动
	
	void launch();//发射子弹,参数区分不同的飞机和图片
	
	void beattack(vector<Plane_enemy>& enemy_planevec, bool& explsign);//攻击敌人与被敌人攻击
	
	void twoskill(vector<Plane_enemy>& enemy_planevec);//两个技能
	
	void controlmove();//飞机接收键值移动
	
	void putInterface();//输出界面信息

public:
	
	Plane_my();//构造初始化图片和坐标等,只会执行一次
	
	~Plane_my();//析构释放图片对象内存
	vector<bulxy> getlaunxy();		//获取我方飞机子弹的坐标数组
	int& setgetplane_x();		//获取或设置坐标
	int& setgetplane_y();
	int& setgetscore();		//获取或设置得分
	char& setgetkey();			//获取或设置键值
	int& setgetshieldnum();			//获取或设置护盾使用次数
	int& setgetunskillnum();		//获取或设置必杀使用次数
	int& setgetlifenum();			//获取或设置我方飞机生命数
	//飞机移动
	bool move(vector<Plane_enemy>& enemy_planevec, bool& explsign);//飞机移动函数,包括升级等操作
};

runtime.cpp

#include <iostream>
#include <graphics.h>
#include "Plane.h"
#include "runtime.h"
using namespace std;

void setimage(int pwidth, int pheight, PIMAGE img_1)
{
	int whidth = getwidth(img_1), height = getheight(img_1);
	PIMAGE tempimg = newimage(pwidth, pheight);

	putimage(tempimg, 0, 0, pwidth, pheight, img_1, 0, 0, whidth, height);	//将原本img中的图像拉伸绘制到img_2中

	getimage(img_1, tempimg, 0, 0, pwidth, pheight);		 //img再获取temp中的图像

	delimage(tempimg);
}

void begingame()
{
	initgraph(500, 760, INIT_RENDERMANUAL);	//初始化图形界面,手动渲染模式
	setcaption("飞机大战");

	PIMAGE beginimg = newimage();
	getimage(beginimg, "F:\\visual studio projects\\飞机大战\\图片素材\\背景.png");
	setimage(540, 760, beginimg);

	PIMAGE planetextimg = newimage();
	getimage(planetextimg, "F:\\visual studio projects\\飞机大战\\图片素材\\字体.png");
	setimage(500, 340, planetextimg);

	putimage(0, 0, beginimg);

	putimage_withalpha(NULL, planetextimg, 0, 0);

	setfont(26, 0, "楷体");
	setcolor(YELLOW);	
	setbkmode(1);//文字背景色透明
	outtextxy(150, 400, "鼠标点击以开始");

	mouse_msg msg = { 0 };				//接收开始游戏的鼠标信息

	while (true)
	{
		msg = getmouse();				//获取一条鼠标信息

		if (msg.is_left()) break;
	}

	delimage(beginimg);	
	delimage(planetextimg);
}


void endgame(bool sign, Plane_my& myplane)
{
	PIMAGE winbackimg = newimage();	
	getimage(winbackimg, "F:\\visual studio projects\\飞机大战\\图片素材\\游戏结束背景.png");
	setimage(500, 760, winbackimg);
	putimage(0, 0, winbackimg);

	setfont(64, 0, "楷体");
	sign ? outtextxy(186, 120, "胜利!") : outtextxy(186, 120, "失败!");
	setfont(36, 0, "楷体");

	myplane.setgetscore() += rand() % 10;
	xyprintf(162, 220, "最终得分:%d", myplane.setgetscore());
	delimage(winbackimg);
	while (true) delay_fps(1);
	exit(0);
}

void enemy_bullet_hit(vector<Plane_enemy>::iterator it, Plane_my& myplane, bool& sign, int& lifenum)
{
	for (vector<bulxy>::iterator ait = it->getenemy_bullvec().begin(); ait != it->getenemy_bullvec().end(); ait++)
		if (ait->b_x >= myplane.setgetplane_x() && ait->b_x <= myplane.setgetplane_x() + 80 &&
			ait->b_y + 18 >= myplane.setgetplane_y() && ait->b_y + 18 <= myplane.setgetplane_y() + 86 ||
			ait->b_x + 18 >= myplane.setgetplane_x() && ait->b_x + 18 <= myplane.setgetplane_x() + 80 &&
			ait->b_y + 18 >= myplane.setgetplane_y() && ait->b_y + 18 <= myplane.setgetplane_y() + 86)
		{
			myplane.health -= 50;
			it->getenemy_bullvec().erase(ait);	//删除敌人的该子弹

			if (myplane.health <= 0 && lifenum >= 0)
			{
				myplane.setgetplane_x() = 210;	//坐标重置
				myplane.setgetplane_y() = 660;
				myplane.health = 400;			//血量重置
				lifenum--;						//生命-1
				myplane.setgetkey() = 0;		//键值重置
			}

			sign = true;	//爆炸效果标记开启
			break;
		}
}

void playmusic(MUSIC& music)
{
	music.OpenFile("F:\\visual studio projects\\飞机大战\\音乐\\back.wav");
	music.Play(1);
}

Plane.cpp

#include "Plane.h"
#include "runtime.h"
#include <iostream>
#include <graphics.h>
#include <vector>
using namespace std;

int Plane::getheight()//飞机高
{
	return height;
}

int Plane::getwidth()//飞机宽
{
	return width;
}

Plane::Plane()//构造函数
{
	health = 0;
	width = 0;
	height = 0;
	p_x = 0;
	p_y = 0;
	now_1 = clock();
	now_2 = 0;
	timediff = 0;
	sign = 0;
	temp.b_x = 0;
	temp.b_y = 0;
	temp.prop = 0;
}

void Plane_enemy::move()
{
	planlaunch();		//发射子弹


	if ((p_y + height) <= 0) {//血量
		switch (planeprop)
		{
		case 1:
			health = 150; break;
		case 2:
			health = 250; break;
		case 3:
			health = 440; break;
		case 4:
			health = 20000;
		}
	}
	//根据飞机不同属性确定飞机移动速度
	switch (planeprop)
	{
	case 1:
	case 2:		//大小兵
		p_y += 2; break;
	case 3:		//精英飞机
		p_y++; break;
	case 4:		//最终BOSS	仅缓慢移动一小段距离
		if (p_y <= -120) p_y++;
	}
	putimage_withalpha(NULL, enemy_img_1, p_x, p_y);	//显示飞机图片
}

inline void Plane_enemy::attackspeed()
{
	now_2 = clock();

	timediff = now_2 - now_1;	//通过上一次发射子弹时间减去当前时间计算出已发射子弹的时间

	switch (planeprop)			//根据不同飞机,设定飞机发射子弹后多长时间再发射一枚子弹
	{
	case 1: //小兵
		attack = 800; break;
	case 2: //大兵
		attack = 700; break;
	case 3:	//小BOSS
		attack = 650; break;
	case 4:	//最终BOSS
		attack = 300;
	}

	if (timediff >= attack)		//发射子弹后固定时间后,再次发射子弹 攻击速度
	{
		pushlaunch();
		timediff = 0;
		now_1 = clock();
	}
}

int Plane_enemy::gethealth()
{
	return health;
}

int Plane_enemy::getenemy_prop()
{
	return planeprop;
}

int& Plane_enemy::setgetp_x()		
{
	return p_x;
}

int& Plane_enemy::setgetp_y()
{
	return p_y;
}

vector<bulxy>& Plane_enemy::getenemy_bullvec()
{
	return bullvec;
}

Plane_enemy::Plane_enemy(int prop)
{
	//初始化
	enemy_img_1 = newimage();		//敌人小兵
	bulletimg = newimage();		//子弹图片对象
	planeprop = 0;					//飞机属性
	speed_x = 0, speed_y = 0;		//子弹速度每帧x轴和y轴移动单位数
	attack = 0;

	this->planeprop = prop;		//将传进来的参数赋给类变量

	
	switch (prop)//根据属性获取不同的子弹图片素材,设置飞机宽高
	{
	case 1:
	case 2:		//大小兵
		getimage(bulletimg, "F:\\visual studio projects\\飞机大战\\图片素材\\敌人子弹1.png");
		setimage(18, 18, bulletimg);
		width = 120, height = 90;
		break;
	case 3:		//精英飞机
		getimage(bulletimg, "F:\\visual studio projects\\飞机大战\\图片素材\\敌人子弹2.png");
		setimage(18, 18, bulletimg);
		width = 240, height = 180;
		break;
	case 4:		//最终BOSS
		getimage(bulletimg, "F:\\visual studio projects\\飞机大战\\图片素材\\敌人导弹.png");
		setimage(40, 81, bulletimg);//子弹图片大小
		width = 480, height = 360;
	}

	p_x = rand() % 380, p_y = -(rand() % 101 + 200);			//随机横纵坐标


	switch (prop)//设定血量
	{
	case 1:
		getimage(enemy_img_1, "F:\\visual studio projects\\飞机大战\\图片素材\\敌人飞机大兵.png");
		health = 150;					//血量
		break;
	case 2:
		getimage(enemy_img_1, "F:\\visual studio projects\\飞机大战\\图片素材\\敌人飞机精英怪.png");
		health = 250;
		break;
	case 3:
		getimage(enemy_img_1, "F:\\visual studio projects\\飞机大战\\图片素材\\敌人飞机BOSS2.png");
		health = 440;
		break;
	case 4:
		getimage(enemy_img_1, "F:\\visual studio projects\\飞机大战\\图片素材\\敌人飞机BOSS1.png");
		health = 20000;			//血量
		p_x = 10, p_y = -360;	//BOSS从固定位置出发
	}
	setimage(width, height, enemy_img_1);			//设置图片宽高
}

inline void Plane_enemy::pushlaunch()					//向数组插入\新建子弹
{
	//根据属性确定子弹发射的位置和方式
	switch (planeprop)
	{
	case 1:		//小兵
	case 2:		//大兵子弹
		temp.b_x = p_x + 51, temp.b_y = p_y + 60;	//确定新子弹的位置
		temp.prop = 2;						//子弹属性向左
		bullvec.push_back(temp);			//将子弹插入进数组中
		temp.prop = 3;						//子弹属性向右
		bullvec.push_back(temp);
		break;
	case 3:		//小BOSS子弹
		temp.b_x = p_x + 110, temp.b_y = p_y + 180;	//确定新子弹的位置
		temp.prop = 2;						//子弹属性向左
		bullvec.push_back(temp);
		temp.prop = 3;						//子弹属性向右
		bullvec.push_back(temp);
		temp.prop = 1;						//子弹属性向下
		bullvec.push_back(temp);
		break;
	case 4:		//最终BOSS子弹
		//所有子弹位于y轴位于p_y + 160,子弹属性为1
		temp.b_y = p_y + 160, temp.prop = 1;
		//分别设置每发子弹的x轴,然后将这枚子弹插入进子弹数组中
		temp.b_x = p_x - 20;
		bullvec.push_back(temp);
		temp.b_x = p_x + 76;
		bullvec.push_back(temp);
		temp.b_x = p_x + 172;
		bullvec.push_back(temp);
		temp.b_x = p_x + 268;
		bullvec.push_back(temp);
		temp.b_x = p_x + 364;
		bullvec.push_back(temp);
		temp.b_x = p_x + 460;
		bullvec.push_back(temp);
	}
}

inline void Plane_enemy::laumoveunit()
{
	//根据飞机属性,确定飞机子弹的xy轴每帧移动单位
	switch (planeprop)
	{
	case 1:
	case 2:		//小大兵
		speed_x = 4, speed_y = 4; break;
	case 3:		//精英兵
		speed_x = 6, speed_y = 18; break;
	case 4:		//最终BOSS
		speed_x = 0, speed_y = 8;
	}
}

inline void Plane_enemy::laudire()
{
	//所有子弹移动
	//根据子弹的属性,确定不同子弹的运动方向
	//通过对子弹的坐标进行+= 或 -=实现
	int bullsizetemp = bullvec.size();
	for (int i = 0; i < bullsizetemp; i++)
		switch (bullvec[i].prop)		//判断每一个子弹的属性,根据属性决定子弹移动方向
		{
		case 1:		//子弹1运动垂直向下
			bullvec[i].b_y += speed_y;	//垂直向下子弹仅移动y轴
			break;
		case 2:		//子弹2运动向左下
			bullvec[i].b_y += speed_y, bullvec[i].b_x -= speed_x;	//左下子弹y轴逐渐增加,x轴减小
			break;
		case 3:		//右下
			bullvec[i].b_y += speed_y, bullvec[i].b_x += speed_x;	//右下子弹y轴逐渐增加,x轴增大
			break;
		}
}

inline void Plane_enemy::laushow()
{
	//遍历子弹数组,显示所有子弹
	//这里使用自动数据类型变量遍历结构xy属性
	for (auto bullvectempi : bullvec)
		putimage_withalpha(NULL, bulletimg, bullvectempi.b_x, bullvectempi.b_y);
}

inline void Plane_enemy::laudelete()
{
	//删除敌人越界的子弹
	for (vector<bulxy>::const_iterator it = bullvec.begin(); it != bullvec.end(); it++)
		if (it->b_y >= 800 || it->b_x + 18 <= 0 || it->b_x >= 500)
		{
			bullvec.erase(it);
			break;
		}
}

void Plane_enemy::planlaunch()
{
	attackspeed();			//子弹射速函数

	laumoveunit();			//子弹速度函数

	laudire();				//子弹方向函数

	laushow();				//显示子弹函数

	laudelete();			//删除越界子弹函数
}

void Plane_my::alterbullplan()
{
	getimage(findplaneimg, "F:\\visual studio projects\\飞机大战\\图片素材\\己方红色飞机.png");
	setimage(80, 86, findplaneimg);
	getimage(bulletimg, "F:\\visual studio projects\\飞机大战\\图片素材\\我方导弹.png");
	setimage(17, 37, bulletimg);
	upgrade = true;		//是否已经升级
}

void Plane_my::pushlaunch()
{
	if (upgrade) {		//如果已经升级
		temp.b_x = p_x - 10, temp.b_y = p_y + 40;
		bullvec.push_back(temp);
		temp.b_x = p_x + 31, temp.b_y = p_y + 40;
		bullvec.push_back(temp);
		temp.b_x = p_x + 73, temp.b_y = p_y + 40;
		bullvec.push_back(temp);
		return;
	}
	//没有升级
	temp.b_x = p_x + 24, temp.b_y = p_y - 20;	//确定新子弹的位置
	bullvec.push_back(temp);			//在子弹数组中插入新的子弹
}

inline void Plane_my::launmove()
{
	//所有子弹移动
	if (upgrade)								//如果已经升级飞机则提升弹道速度
		for (int i = 0; i < bullvec.size(); i++)
			bullvec[i].b_y -= 24;				//升级后的速度
	else
		for (int i = 0; i < bullvec.size(); i++)
			bullvec[i].b_y -= 16;				//一般速度

	//输出所有子弹
	for (int i = 0; i < bullvec.size(); i++)
		putimage_withalpha(NULL, bulletimg, bullvec[i].b_x, bullvec[i].b_y);
}

void Plane_my::launch()
{
	now_2 = clock();			//精确到毫秒获取时间

	timediff = now_2 - now_1;	//计算子弹发射时间差

	int attack = 0;				//时间间隔

	if (upgrade)				//如果已经升级飞机则提升攻速
		attack = 180;			//升级后的攻速
	else
		attack = 320;			//一般攻速

	if (timediff >= attack) {		//发射子弹后时间大于一定数值(毫秒)则再次发射子弹
		pushlaunch();			//新建子弹
		timediff = 0;			//累计时间重置
		now_1 = clock();		//重新获取子弹发射时时间
	}

	launmove();					//子弹移动

	//删除我方越界的子弹
	for (vector<bulxy>::const_iterator it = bullvec.begin(); it != bullvec.end(); it++)
		if (it->b_y <= -80) {
			bullvec.erase(it);
			break;
		}
}

void Plane_my::beattack(vector<Plane_enemy>& enemy_planevec, bool& explsign)
{
	if (!unskillsign)			//在没有释放必杀技时不停发射子弹
		launch();				//发射子弹

	int enemy_sizex, enemy_sizey;	//敌人飞机宽高变量
	for (vector<Plane_enemy>::iterator enemy_it = enemy_planevec.begin(); enemy_it != enemy_planevec.end(); enemy_it++)
	{
		for (vector<bulxy>::const_iterator it = bullvec.begin(); it != bullvec.end(); it++)
		{
			enemy_sizex = enemy_it->getwidth(), enemy_sizey = enemy_it->getheight();	//敌人飞机的宽高

			//如果有一发子弹的坐标与敌人重合,则敌人掉血
			if (it->b_x + 17 >= enemy_it->setgetp_x() && it->b_x + 17 <= enemy_it->setgetp_x() + enemy_sizex &&
				it->b_y >= enemy_it->setgetp_y() && it->b_y <= enemy_it->setgetp_y() + enemy_sizey)
			{
				enemy_it->health -= 50;					//敌人的飞机血量减少

				btarg_x = it->b_x, btarg_y = it->b_y;	//记录爆炸效果坐标
				sign = true;							//控制爆炸效果

				if (enemy_it->health <= 0)				//如果本次击中的敌人的血量<=0
				{
					switch (enemy_it->getenemy_prop())		//根据消灭的敌人,增加不同得分
					{
					case 1:
						score++;
						break;
					case 2:
						score += 2;
						break;
					case 3:
						score += 4;
						break;
					case 4:
						score += 21;
					}

					enemy_planevec.erase(enemy_it);			//删除与我方子弹重合且血量为空的飞机

					//产生一个新的敌军飞机
					Plane_enemy enemy_plane(rand() % 3 + 1);//敌人

					enemy_planevec.push_back(enemy_plane);	//插入进敌人飞机数组

					goto L1;							//跳出双重循环
				}
				bullvec.erase(it);		//删除这个击中敌人的子弹
				break;
			}
		}
	}

L1:


	//击中敌人时子弹处爆炸效果
	if (sign) {
		if (music.GetPlayStatus() == MUSIC_MODE_STOP) {
			music.Play(100, 400);
		}	//播放击中音效,必须在该音效播放完毕后播放
		putimage_withalpha(NULL, explimgarr[atemp], btarg_x - 17, btarg_y);
		atemp++;			//根据爆炸图片数组来显示爆炸效果
		if (atemp > 2)		//播放完毕停止
			sign = false, atemp = 0;	//关闭信号,重置数组下标
	}

	//被敌人击中时自己的爆炸效果,显示在飞机之上
	if (explsign) {
		if (music.GetPlayStatus() == MUSIC_MODE_STOP) {
			music.Play(80, 450);
		}//播放击中音效,必须在该音效播放完毕后播放
		putimage_withalpha(NULL, explimgarr[btemp], p_x + 20, p_y + 20);
		btemp++;			//根据爆炸图片数组来显示爆炸效果
		if (btemp > 2) {
			explsign = false, btemp = 0;//播放完毕停止
		}
	}
}

void Plane_my::twoskill(vector<Plane_enemy>& enemy_planevec)
{
	unskilltime_2 = clock();		//必杀开启之后的时间
	int temptime_1 = unskilltime_2 - unskilltime_1;	//相减
	if (unskillsign)				//如果必杀开启
	{
		//同时使用一次护盾,不消耗次数
		shieldsign = true;		//护盾开启标记
		shiledtime_1 = clock();	//护盾开启时的时间
		putimage_withalpha(NULL, unskillimg, p_x - 32, p_y - 690);	//显示护盾图片
		health = 400;			//血量恢复且护盾时效内不会掉血

		if (temptime_1 >= 6000) {
			unskillsign = false;//必杀有效时间
		}

		//必杀技攻击敌人的判定,这里只判断x轴
		for (vector<Plane_enemy>::iterator enemy_it = enemy_planevec.begin(); enemy_it != enemy_planevec.end(); enemy_it++)
		{
			int enemy_sizex = 0;	//敌人飞机的大小xy
			switch (enemy_it->getenemy_prop())
			{
			case 1:
			case 2:
				enemy_sizex = 120;
				break;
			case 3:
				enemy_sizex = 240;
				break;
			case 4:
				enemy_sizex = 480;
			}

			//根据敌机的大小判断位置,这里只判断x轴
			if ((p_x - 16 < enemy_it->setgetp_x()) || (p_x - 16 > enemy_it->setgetp_x() + enemy_sizex)) {
				continue;
			}
			enemy_it->health -= 50;			//敌人的飞机血量减少
			btarg_x = p_x + 30, btarg_y = enemy_it->setgetp_y() + 50; //记录爆炸效果坐标,根据敌机坐标确认
			if (enemy_it->getenemy_prop() == 4) {
				btarg_y += 160;
			}							//如果击中的敌人是最终BOSS则单独确定爆炸位置
			sign = true;					//控制爆炸效果
			if (enemy_it->health > 0) {
				continue;
			}		//如果本次击中的敌人的血量减少后>0 结束本次循环

			switch (enemy_it->getenemy_prop())	//根据消灭的敌人,增加得分
			{
			case 1:
				score++;
				break;
			case 2:
				score += 2;
				break;
			case 3:
				score += 4;
				break;
			case 4:
				score += 21;
			}
			enemy_planevec.erase(enemy_it);	//删除与我方子弹重合且血量为空的飞机

			//产生一个新的敌军飞机
			Plane_enemy enemy_plane(rand() % 3 + 1);//敌人
			enemy_planevec.push_back(enemy_plane);	//插入进敌人飞机数组
			break;
		}
	}

	shiledtime_2 = clock();		//护盾开启之后的时间

	int temptime_2 = shiledtime_2 - shiledtime_1;	//相减

	if (shieldsign)				//如果护盾开启
	{
		putimage_withalpha(NULL, shieldimg, p_x - 22, p_y - 10);

		health = 400;			//血量恢复且护盾时效内不会掉血

		if (temptime_2 >= 5000) shieldsign = false;		//护盾有效时间
	}
}

void Plane_my::controlmove()
{
	//移动
	//键盘按下
	if (kbhit())
	{
		//接收一个键值
		key = getch();

		switch (key)
		{
		case 'w':				//w飞机向上飞,并且确定一个向上滑行距离
			p_y -= 6;			//移动距离
			inerdis = p_y - 18;	//惯性距离
			break;
		case 'a':
			p_x -= 6;
			inerdis = p_x - 18;
			break;
		case 's':
			p_y += 6;
			inerdis = p_y + 18;
			break;
		case 'd':
			p_x += 6;
			inerdis = p_x + 18;
			break;
		case 'e':			
			if (shieldnum <= 0)		
				break;
			shieldsign = true;	
			shiledtime_1 = clock();	
			shieldnum--;
			break;
		case 'q':
			if (unskillnum <= 0)
				break;
			unskillsign = true;	
			unskilltime_1 = clock();
			unskillnum--;	
			break;
		case ' '://空格键暂停
			putimage_withalpha(NULL, findplaneimg, p_x, p_y);
			getch();
		}
	}

	//确定飞机滑行时的速度和限制飞机移动范围
	switch (key)
	{
	case 'w':
		if (p_y >= inerdis) p_y -= 2;	//飞机结束移动后向特定位置滑行一段距离
		if (p_y <= 0) p_y = 0;			//飞机坐标越界则重置坐标
		break;
	case 'a':
		if (p_x >= inerdis) p_x -= 2;
		if (p_x <= 0) p_x = 0;
		break;
	case 's':
		if (p_y <= inerdis) p_y += 2;
		if (p_y >= 674) p_y = 674;
		break;
	case 'd':
		if (p_x <= inerdis) p_x += 2;
		if (p_x >= 420) p_x = 420;
	}
}

void Plane_my::putInterface()
{
	setfont(30, NULL, "黑体");
	xyprintf(0, 0, "得分:%d", score);
	setfont(24, NULL, "黑体");
	xyprintf(0, 50, "生命值:%d", health);
	xyprintf(0, 90, "生命:%d", lifenum);

	//图标
	setfont(20, NULL, "楷体");
	outtextxy(6, 380, "护盾E");
	putimage_withalpha(NULL, shieldicon, 10, 410);	//护盾图标
	xyprintf(24, 460, "%d", shieldnum);				//护盾剩余使用次数

	outtextxy(1, 510, "必杀技Q");
	putimage_withalpha(NULL, unskillicon, 12, 540);	//必杀图标	++
	xyprintf(26, 590, "%d", unskillnum);			//必杀剩余使用次数
}

Plane_my::Plane_my() :findplaneimg(newimage()), bulletimg(newimage()), shieldimg(newimage()),
shieldicon(newimage()), unskillicon(newimage()), unskillimg(newimage())
{
	key = 0;
	inerdis = 0;		
	sign = false;
	atemp = 0;						
	btarg_x = 0;
	btarg_y = 0;		
	btemp = 0;					
	score = 0;						
	shieldsign = false;				
	shiledtime_1 = 0;			
	shiledtime_2 = 0;
	shieldnum = 3;						
	unskillsign = false;				
	unskilltime_1 = 0;			
	unskilltime_2 = 0;
	unskillnum = 2;					
	upgrade = false;				
	lifenum = 3;						
	i = 0;
	width = 80;
	height = 86;	//飞机宽高

	//获取并修改图片素材
	getimage(findplaneimg, "F:\\visual studio projects\\飞机大战\\图片素材\\己方蓝色飞机.png");
	setimage(width, height, findplaneimg);
	getimage(bulletimg, "F:\\visual studio projects\\飞机大战\\图片素材\\己方普通子弹.png");
	setimage(34, 74, bulletimg);

	getimage(shieldimg, "F:\\visual studio projects\\飞机大战\\图片素材\\护盾.png");
	setimage(120, 120, shieldimg);
	getimage(shieldicon, "F:\\visual studio projects\\飞机大战\\图片素材\\护盾.png");
	setimage(40, 40, shieldicon);

	getimage(unskillimg, "F:\\visual studio projects\\飞机大战\\图片素材\\激光.png");
	setimage(160, 700, unskillimg);
	getimage(unskillicon, "F:\\visual studio projects\\飞机大战\\图片素材\\激光.png");
	setimage(40, 40, unskillicon);

	for (i = 0; i < 3; i++) explimgarr[i] = newimage();
	//数组中总共1张图片,每张图片有两张重复帧
	for (i = 0; i < 3; i++) getimage(explimgarr[i], "F:\\visual studio projects\\飞机大战\\图片素材\\爆炸.png");

	p_x = 220, p_y = 660;		//飞机初始坐标
	health = 400;				//血量

	music.OpenFile("F:\\visual studio projects\\飞机大战\\音乐\\击中音效.wav");//打开音乐文件函数
}

Plane_my::~Plane_my()
{
	delimage(findplaneimg);
	delimage(bulletimg);
	delimage(shieldimg);
	delimage(shieldicon);
	delimage(unskillicon);
	delimage(unskillimg);
	for (int i = 0; i < 3; i++) delimage(explimgarr[i]);	//释放爆炸效果数组
}

vector<bulxy> Plane_my::getlaunxy()		//获取我方飞机子弹的坐标数组
{
	return bullvec;
}

int& Plane_my::setgetplane_x()		//获取或设置坐标
{
	return p_x;
}

int& Plane_my::setgetplane_y()
{
	return p_y;
}

int& Plane_my::setgetscore()			//获取或设置得分
{
	return score;
}

char& Plane_my::setgetkey()			//获取或设置键值
{
	return key;
}

int& Plane_my::setgetshieldnum()			//获取或设置护盾使用次数
{
	return shieldnum;
}

int& Plane_my::setgetunskillnum()		//获取或设置必杀使用次数
{
	return unskillnum;
}

int& Plane_my::setgetlifenum()			//获取或设置我方飞机生命数
{
	return lifenum;
}

bool Plane_my::move(vector<Plane_enemy>& enemy_planevec, bool& explsign)
{
	if (score >= 40)	alterbullplan();//得分大于40则升级
	putInterface();						//输出界面信息
	twoskill(enemy_planevec);				//两个技能相关

	if (!lifenum)	return true;
	controlmove();						//接收键值移动飞机

	putimage_withalpha(NULL, findplaneimg, p_x, p_y);//在飞机坐标位置显示飞机
	beattack(enemy_planevec, explsign);	//攻击敌人与被敌人攻击
	return false;
}

VS2019编写,四个文件:飞机大战.cpp,  Plane.h,  runtime.h,  runtime.cpp,  Plane.cpp

需要音频文件和图片资源,用背景透明的png图片

需要ege图形库

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值