飞机大战.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图形库