做视频的素材网站,wordpress模板地址,品牌建设有哪些方面,企业做网站认证有哪些好处[导读]本系列博文内容链接如下#xff1a; 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C】做一个飞… [导读]本系列博文内容链接如下 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C】做一个飞机空战小游戏(四)——给游戏添加背景音乐(多线程技巧应用) 【C】做一个飞机空战小游戏(五)——getch()控制两个飞机图标移动(控制光标位置) 【C】做一个飞机空战小游戏(六)——给两架飞机设置不同颜色(cout输出彩色字符、结构体使用技巧) 【C】做一个飞机空战小游戏(七)——两组按键同时检测平滑移动(GetAsyncKeyState()函数应用) 【C】做一个飞机空战小游戏(八)——生成敌方炮弹(rand()函数应用) 【C】做一个飞机空战小游戏(九)——发射子弹的编程技巧 【C】做一个飞机空战小游戏(十)——子弹击落炮弹、炮弹与飞机相撞 今天这节介绍实现子弹击落炮弹、炮弹与飞机相撞的效果增加了飞机的血量属性炮弹撞击一次掉血三分之一三次撞击则飞机被炮弹击落。还增加了飞机命数属性飞机设置了3条命飞机命数大于0的时候可以按复活键进行复活如果命为0时飞机不可复活。还增加了游戏暂停功能按空格键游戏暂停再按一次即可恢复游戏。
目录
一、炮弹与子弹或飞机相撞
一子弹击落炮弹
1、子弹、炮弹初始血量和伤害值
2、子弹与炮弹相撞后血量
3、击落函数
4、击落后血量变化代码
二炮弹与飞机相撞
1、飞机结构体
2、飞机初始化函数
1单个飞机初始化
2所有飞机初始化
3、飞机初始血量
4、飞机与炮弹相撞后血量
1炮弹血量
2飞机血量
5、飞机命数
6、相撞函数
7、相撞后血量命数变化代码
8、飞机复活
二、游戏暂停功能
一game中增加pause属性
二游戏暂停按键
三游戏暂停代码
三、完整代码
一主函数
二头文件control_plane.h
三库函数control_plane.cpp
四、运行效果
一子弹与炮弹相撞
二炮弹与飞机相撞、飞机复活 一、炮弹与子弹或飞机相撞
一子弹击落炮弹
1、子弹、炮弹初始血量和伤害值
子弹炮弹相撞前
子弹、炮弹血量hp1
子弹、炮弹伤害值dam1
2、子弹与炮弹相撞后血量
子弹炮弹相撞后
相撞后子弹血量相撞前子弹血量-炮弹伤害值
相撞后炮弹血量相撞前炮弹血量-子弹伤害值
因此子弹炮弹相撞后两者血量都为0alive值都为false会同归于尽炮弹被击落。
3、击落函数 bool shoot(Bullet bullet,Bomb bomb)
{bool sbb,sx0,sx1,sy0,sy1;sx0(bomb.location.xbullet.location.x-1);sx1(bomb.location.xbullet.location.x1); sy0(bomb.location.ybullet.location.y);sy1(bomb.location.ybullet.location.y1); sbbsx0 sx1sy0sy1;return sbb;
}
4、击落后血量变化代码
这部分代码在子弹位置更新线程中具体如下
for(int k0;kgame.bombs_round;k)//判断子弹是否击中炮弹
{ if(shoot(bullet[i][j],bomb[k])){bomb[k].hp-bullet[i][j].dam;bullet[i][j].hp-bomb[k].dam;}
}
二炮弹与飞机相撞
1、飞机结构体
//定义飞机结构体
typedef struct{Location location; //飞机坐标 int color; //飞机颜色 int icon; //飞机图标编号 direction_cmd keycmd; //飞机移动方向命令 bool fire; //飞机是否开火 int cnt_bullets; //按一次开火键加1然后初始化bullet[cnt_bullets],子弹死亡一个减1int hp; //飞机血量 bool alive; //飞机存活标志 int No; //飞机序号 int life; //飞机命数
}Plane;
2、飞机初始化函数
1单个飞机初始化
//单个飞机初始化函数
Plane init_plane(Plane plane)
{plane.alivetrue; plane.hp3; plane.keycmdnone_cmd;plane.locationplocation[plane.No];plane.colorplane.No1;plane.iconplane.No1; return plane;
}
初始化函数用在游戏开始和飞机复活时函数中没有设置No和life两项因为No值不同而life值每次死亡时减1复活后不能再恢复为原值。
2所有飞机初始化
//所有飞机初始化函数
void init_planes(void)
{for(int i0;igame.num_plane;i)//刷新飞机图标{ plane[i]init_plane(plane[i]);}
}
3、飞机初始血量
飞机初始血量hp3飞机没有设置伤害值默认其伤害值为无穷大。
4、飞机与炮弹相撞后血量
1炮弹血量
炮弹与飞机相撞后炮弹血量直接降为0alive值为false。
2飞机血量
飞机与炮弹相撞后相撞后飞机血量值相撞前血量值-炮弹伤害值。飞机血量值小于等于0时飞机死亡alive值为false。
5、飞机命数
飞机命数life初始值为3。如果飞机死亡其命数life值减1。
6、相撞函数 bool collide(Plane plane,Bomb bomb)
{bool cpb,cx0,cx1,cy0,cy1;cx0bomb.location.xplane.location.x-1;cx1bomb.location.xplane.location.xplane_width;cy0bomb.location.yplane.location.y;cy1bomb.location.yplane.location.yplane_height; cpbcx0 cx1 cy0 cy1;return cpb;
}
7、相撞后血量命数变化代码
飞机血量、命数的变化代码放置在炮弹位置更新线程中具体内容如下
for(int j0;jgame.num_plane;j)
{if(plane[j].alive){if(collide(plane[j],bomb[i])) {bomb[i].hp0;plane[j].hp-bomb[i].dam; }if(plane[j].hp0){plane[j].alivefalse;plane[j].lifeplane[j].life-1;plane[j].keycmdnone_cmd;plane[j].location.x0;plane[j].location.yb_b8; } }}
8、飞机复活
按复活键可复活当命数小于1时不能再复活永久死亡。plane[0]的复活代码如下
if(plane[0].life0)
{if (GetAsyncKeyState(O) 0x8000) //飞机复活指令{plane[0]init_plane(plane[0]);show_plane(plane[0]);}
}
二、游戏暂停功能
一game中增加pause属性
//定义游戏结构体
typedef struct{int stage; //游戏当前关 int bombs_round; //敌方每轮发射炮弹数量 int bombs_stage; //每关总计出现炮弹数量 bool clear; //游戏过关 bool complete; //游戏通关 bool gameover; //游戏结束int num_plane; //飞机数量 int cur_num_bomb; //当前已发射炮弹数量 int bomb_interval; //位置更新间隔 bool bomb_move; //炮弹是否移动bool bullet_move; //子弹是否移动bool pause; //游戏是否暂停
}Game;
二游戏暂停按键
游戏暂停键为空格键游戏进行时按下空格键game.pausetrue游戏暂停再按一次game.pausefalse游戏恢复代码在key()函数中内容如下
if (GetAsyncKeyState(VK_SPACE) 0x8000)
{Sleep(50);game.pause!game.pause;
}
代码中Sleep(50)为按键去抖动作用防止按了一次被识别为多次。
三游戏暂停代码
游戏暂停时主函数中除背景音乐之外所有的线程都暂停。在需要暂停的线程中加入如下代码
while(game.pause)
{;
}
三、完整代码
一主函数
#include control_plane.h
#include quenue.h
using namespace std; Plane plane[eq_plane];
Game game;
Bomb bomb[eq_bombs_round];
Bullet bullet[eq_plane][eq_bullets_round];
Location plocation[]{{2*r_b/3,b_b},{r_b/3,b_b}};int main(int argc, char** argv) { init(); //初始化 bgmusic();//播放背景音乐getkey();bomb_location_update(); bullet_location_update(); while(1) //循环等待键盘指令 {while(game.pause){;}if(plane[0].keycmd!none_cmd ||plane[1].keycmd!none_cmd ||game.bomb_move ||game.bullet_move){game.bomb_movefalse;game.bullet_movefalse;system(cls);for(int i0;igame.num_plane;i){if(plane[i].alive){show_plane(plane[i]);//刷新飞机图标}}for(int i0;igame.bombs_round;i){if(bomb[i].alive){show_bomb(bomb[i]);}}for(int i0;ieq_plane;i){for(int j0;jeq_bullets_round;j){ if(bullet[i][j].alive){show_bullet(bullet[i][j]);}} } } }return 0;
}
二头文件control_plane.h
#ifndef CONTROL_PLANE_H
#define CONTROL_PLANE
#include iostream
#include ctime
#include string
#includestdlib.h
#includewindows.h
#include pthread.h//导入线程头文件库
#include mmsystem.h //导入声音头文件库
#pragma comment(lib,winmm.lib)//导入声音的链接库
#define _CRT_SECURE_NO_WARNINGS
using namespace std;#define t_b 0 //图形显示区域上侧边界
#define l_b 0 //图形显示区域左侧边界
#define r_b 100 //图形显示区域右侧边界
#define b_b 20 //图形显示区域下侧边界
#define plane_width 9
#define plane_height 6#define eq_plane 2 //飞机架数
#define eq_bombs_round 23 //eqend quantity最终炮弹数量
#define eq_rt 10 //复活最大时间
#define eq_bullets_round 20 //eqend quantity飞机一次发射最多子弹数量 //定义飞机造型
const string icon_plane1[]{ ■,■ ■ ■,■■■■■,■ ■ ■, ■, ■■■};
const string icon_plane2[]{ ■,■ ■ ■,■■■■■, ■, ■■■,■■■■■};//定义炮弹造型
const string icon_bomb■;//定义子弹造型
const string icon_bullet■;//定义坐标结构体
typedef struct{int x;int y;
} Location;//定义移动方向命令枚举类型
typedef enum {none_cmd,up_cmd,down_cmd,left_cmd,right_cmd} direction_cmd;//定义游戏结构体
typedef struct{int stage; //游戏当前关 int bombs_round; //敌方每轮发射炮弹数量 int bombs_stage; //每关总计出现炮弹数量 bool clear; //游戏过关 bool complete; //游戏通关 bool gameover; //游戏结束int num_plane; //飞机数量 int cur_num_bomb; //当前已发射炮弹数量 int bomb_interval; //位置更新间隔 bool bomb_move; //炮弹是否移动bool bullet_move; //子弹是否移动bool pause; //游戏是否暂停
}Game;//定义飞机结构体
typedef struct{Location location; //飞机坐标 int color; //飞机颜色 int icon; //飞机图标编号 direction_cmd keycmd; //飞机移动方向命令 bool fire; //飞机是否开火 int cnt_bullets; //按一次开火键加1然后初始化bullet[cnt_bullets],子弹死亡一个减1int hp; //飞机血量 bool alive; //飞机存活标志 int No; //飞机序号 int life; //飞机命数
}Plane;//定义敌方炮弹结构体
typedef struct{Location location; //炮弹位置 bool alive; //炮弹是否存活 int color; //炮弹颜色string icon; //炮弹图标int rt; //rtrespawn time复活时间 int hp; //hphit point 生命值此值0时敌方炮弹死亡敌方炮弹被飞机子弹击中hp会减少坠地或与飞机相撞hp直接降为0 int dam; //damdamage 伤害值int type; //炮弹类型
}Bomb;//定义子弹结构体
typedef struct{Location location; //子弹位置 bool alive; //子弹是否存活 int color; //子弹颜色string icon; //子弹图标 int hp; //hphit point 生命值子弹击中炮弹或冲出屏幕上方hp直接降为0子弹死亡 int dam; //damdamage 伤害值int type; //子弹类型
}Bullet;extern Plane plane[eq_plane];
extern Game game;
extern Bomb bomb[eq_bombs_round];
extern Bullet bullet[eq_plane][eq_bullets_round];extern Location plocation[];
//extern Location plocation1{r_b/3,b_b};//声明刷新飞机位置函数
void show_plane(Plane plane);//获取键盘指令
void key(void);//更新所有飞机坐标
void plane_location_update(void);//初始化函数
void init(void);//播放背景音乐线程
void* thread_bgmusic(void* arg);
void play_bgmusic();
void bgmusic();//获取按键指令线程
void* thread_key(void* arg);
void getkey();//输出彩色字符函数
templatetypename T //T表示任何可以被cout输出的类型
void ColorCout(T t, const int ForeColor 7, const int BackColor 0);void init_bombs(void);
Bomb init_(Bomb bomb);
void* thread_bomb(void* arg);
void bomb_location_update();
void show_bomb(Bomb bomb);void bullet_location_update(); //子弹位置更新
void* thread_bullet(void* arg); //子弹线程函数
Bullet init_bullet(Bullet bullet); //单个子弹初始化
void init_bullets(void); //所有子弹初始化
Bullet fire(Plane plane,Bullet bullet); //飞机开火函数确定子弹出现的起始位置
void show_bullet(Bullet bullet); //显示子弹图标 bool collide(Plane plane,Bomb bomb);
bool shoot(Bullet bullet,Bomb bomb);Plane init_plane(Plane plane);
void init_planes(void);#endif
三库函数control_plane.cpp
#include iostream
#include conio.h
#include string
#include control_plane.h
#includewindows.h
using namespace std;//彩色输出函数
templatetypename T //T表示任何可以被cout输出的类型
void ColorCout(T t, const int ForeColor 7, const int BackColor 0)
{// 0 黑色 1 蓝色 2 绿色 3 浅绿色 4 红色 5 紫色 6 黄色 7 白色// 8 灰色 9 淡蓝色 10 淡绿色 11 淡浅绿色 12 淡红色 13 淡紫色 14 淡黄色 15 亮白色SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), ForeColor BackColor * 0x10);cout t;SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}//隐藏光标函数
HANDLE han GetStdHandle(-11);
void hide(){CONSOLE_CURSOR_INFO cursor;cursor.bVisible 0;cursor.dwSize 1;SetConsoleCursorInfo(han,cursor);
}//初始化函数
void init(void)
{plane[0].No0;plane[1].No1;plane[0].life3; plane[1].life3;srand(time(NULL));game.num_plane2;game.bombs_round3;game.bomb_movefalse;game.bullet_movefalse;game.bomb_interval1000;game.stage1;game.bombs_stage100;game.pausefalse; init_bombs();init_bullets();init_planes();system(cls);for(int i0;igame.num_plane;i)//刷新飞机图标{ show_plane(plane[i]);}game.bombs_round3;hide();//隐藏光标
}//********************************************************************************//以下三个函数为获得按键指令线程函数
//********************************************************************************void* thread_key(void* arg)
{while(1){Sleep(60); //获取指令延时一定时间起滤波作用延缓获取指令的响应速度 key(); //获取按键指令plane_location_update() ;//获取完指令马上更新飞机坐标 }
}
void getkey()
{pthread_t tid; pthread_create(tid, NULL, thread_key, NULL);
}//获取键盘指令函数
void key(void)
{if (GetAsyncKeyState(VK_SPACE) 0x8000){Sleep(50);game.pause!game.pause; }if(!game.pause){if(plane[0].alive){direction_cmd cnone_cmd;if (GetAsyncKeyState(VK_UP) 0x8000) c up_cmd;if (GetAsyncKeyState(VK_DOWN) 0x8000) c down_cmd;if (GetAsyncKeyState(VK_LEFT) 0x8000) c left_cmd;if (GetAsyncKeyState(VK_RIGHT) 0x8000) c right_cmd;plane[0].keycmdc; //刷新飞机方向指令 if (GetAsyncKeyState(P) 0x8000) plane[0].fire true; //飞机开火指令}else{if(plane[0].life0){if (GetAsyncKeyState(O) 0x8000) //飞机复活指令{plane[0]init_plane(plane[0]);show_plane(plane[0]);}}}if(plane[1].alive){direction_cmd dnone_cmd;if (GetAsyncKeyState(W) 0x8000) d up_cmd;if (GetAsyncKeyState(S) 0x8000) d down_cmd;if (GetAsyncKeyState(A) 0x8000) d left_cmd;if (GetAsyncKeyState(D) 0x8000) d right_cmd;plane[1].keycmdd;//刷新飞机图标if (GetAsyncKeyState(F) 0x8000) plane[1].fire true;}else{if(plane[1].life0){if (GetAsyncKeyState(Q) 0x8000){plane[1]init_plane(plane[1]);show_plane(plane[1]);}} } }
}void gotoxy(int x, int y) {COORD pos { x,y };HANDLE hOut GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出设备句柄SetConsoleCursorPosition(hOut, pos);//两个参数分别指定哪个窗口具体位置
}//飞机图标刷新函数
void show_plane(Plane plane) //预先定义字符定位显示函数x是列坐标y是行坐标原点(x0,y0)位于屏幕左上角
{int x,y;int i,j;int rows;xplane.location.x;yplane.location.y;switch(plane.icon){case 1://第一种造型 rowssizeof(icon_plane1)/sizeof(icon_plane1[0]);for(i0;irows;i) {gotoxy(x,yi); ColorCout(icon_plane1[i],plane.color);}break;case 2://第二种造型 rowssizeof(icon_plane2)/sizeof(icon_plane2[0]);for(i0;irows;i) {gotoxy(x,yi); ColorCout(icon_plane2[i],plane.color);}break; }
}//更新两个飞机的坐标
void plane_location_update(void)
{ for(int i0;i2;i){if(plane[i].keycmd!none_cmd) {int x,y;xplane[i].location.x;yplane[i].location.y;switch(plane[i].keycmd){case up_cmd:y--; //字符上移一行行值y减1if(yt_b) //限定y值最小值为0{yt_b;}break;case down_cmd:y; //字符下移一行行值y加1if(yb_b) //限定y高度 {yb_b;}break;case left_cmd:x--; //字符左移一列列值x减1if(xl_b){xl_b; //限定x最小值为0; }break;case right_cmd:x; //字符右移一列列值x加1if(xr_b){xr_b; //限定x宽度}break;}plane[i].location.xx;plane[i].location.yy;plane[i].keycmdnone_cmd; }}
}//单个炮弹初始化函数
Bomb init_bomb(Bomb bomb)
{bomb.location.xrand()%r_b; bomb.location.yb_b6;bomb.iconicon_bomb;bomb.color6;bomb.dam1;bomb.hp1;bomb.alivefalse;bomb.rtrand()%(eq_rt1)1; return bomb;
}//所有炮弹初始化函数
void init_bombs(void)
{game.bomb_movefalse;for(int i0;igame.bombs_round;i){bomb[i]init_bomb(bomb[i]); }
}//炮弹位置更新 线程
void* thread_bomb(void* arg)
{while(1){while(game.pause){;}Sleep(game.bomb_interval);game.bomb_movetrue;for(int i0;igame.bombs_round;i){ if(bomb[i].alive){bomb[i].location.y;if(bomb[i].location.yb_b5){bomb[i].hp0; }for(int j0;jgame.num_plane;j){if(plane[j].alive){if(collide(plane[j],bomb[i])) {bomb[i].hp0;plane[j].hp-bomb[i].dam; }if(plane[j].hp0){plane[j].alivefalse;plane[j].lifeplane[j].life-1;plane[j].keycmdnone_cmd;plane[j].location.x0;plane[j].location.yb_b8; } }} if(bomb[i].hp0){bomb[i]init_bomb(bomb[i]); } }else{bomb[i].rt--;if(bomb[i].rt0){bomb[i].alivetrue;bomb[i].location.y0;} }} }
}
//炮弹位置更新
void bomb_location_update()
{pthread_t tid; pthread_create(tid, NULL, thread_bomb, NULL);
}炮弹图标刷新函数
void show_bomb(Bomb bomb) //预先定义字符定位显示函数x是列坐标y是行坐标原点(x0,y0)位于屏幕左上角
{int x,y; xbomb.location.x;ybomb.location.y;hide();//隐藏光标gotoxy(x,y);ColorCout(bomb.icon,bomb.color);} //发射子弹
Bullet fire(Plane plane,Bullet bullet)
{game.bullet_movetrue;bullet.location.xplane.location.xplane_width/2; bullet.location.yplane.location.y-1;bullet.alivetrue; return bullet;
}//单个子弹初始化函数
Bullet init_bullet(Bullet bullet)
{bullet.iconicon_bullet;bullet.location.x0;bullet.location.yb_b7;bullet.alivefalse;bullet.color4;bullet.dam1;bullet.hp1; return bullet;
}//所有子弹初始化函数
void init_bullets(void)
{game.bullet_movefalse; for(int i0;ieq_plane;i){for(int j0;jeq_bullets_round;j){bullet[i][j]init_bullet(bullet[i][j]); } }
}//单个飞机初始化函数
Plane init_plane(Plane plane)
{plane.alivetrue; plane.hp3; plane.keycmdnone_cmd;plane.locationplocation[plane.No];plane.colorplane.No1;plane.iconplane.No1; return plane;
}//所有飞机初始化函数
void init_planes(void)
{for(int i0;igame.num_plane;i)//刷新飞机图标{ plane[i]init_plane(plane[i]);}
}//子弹位置更新 线程
void* thread_bullet(void* arg)
{while(1){while(game.pause){;}Sleep(game.bomb_interval);for(int i0;ieq_plane;i){if(plane[i].fire) //如果飞机开火要搜寻一个子弹处于死亡状态的位置激活子弹 { game.bullet_movetrue; for(int j0;jeq_bullets_round;j){if(!bullet[i][j].alive){bullet[i][j]fire(plane[i],bullet[i][j]);break;} }}plane[i].firefalse; }for(int i0;ieq_plane;i){for(int j0;jeq_bullets_round;j){ if(bullet[i][j].alive){bullet[i][j].location.y--;if(bullet[i][j].location.y0){bullet[i][j].hp0; }for(int k0;kgame.bombs_round;k)//判断子弹是否击中炮弹 { if(shoot(bullet[i][j],bomb[k])){bomb[k].hp-bullet[i][j].dam;bullet[i][j].hp-bomb[k].dam;}}if(bullet[i][j].hp0){//bullet[i][j].alivefalse;bullet[i][j]init_bullet(bullet[i][j]); } }} } }
}
//子弹位置更新
void bullet_location_update()
{pthread_t tid; pthread_create(tid, NULL, thread_bullet, NULL);
}子弹图标刷新函数
void show_bullet(Bullet bullet) //预先定义字符定位显示函数x是列坐标y是行坐标原点(x0,y0)位于屏幕左上角
{int x,y; xbullet.location.x;ybullet.location.y;hide();//隐藏光标gotoxy(x,y);ColorCout(bullet.icon,bullet.color);
} //********************************************************************************//以下函数为子弹被击落或撞落功能
//********************************************************************************bool collide(Plane plane,Bomb bomb)
{bool cpb,cx0,cx1,cy0,cy1;cx0bomb.location.xplane.location.x-1;cx1bomb.location.xplane.location.xplane_width;cy0bomb.location.yplane.location.y;cy1bomb.location.yplane.location.yplane_height; cpbcx0 cx1 cy0 cy1;return cpb;
}bool shoot(Bullet bullet,Bomb bomb)
{bool sbb,sx0,sx1,sy0,sy1;sx0(bomb.location.xbullet.location.x-1);sx1(bomb.location.xbullet.location.x1); sy0(bomb.location.ybullet.location.y);sy1(bomb.location.ybullet.location.y1); sbbsx0 sx1sy0sy1;return sbb;
}//********************************************************************************//以下三个函数为播放背景音乐功能
//********************************************************************************//播放一遍背景音乐 void play_bgmusic() { mciSendString(TEXT(open hero.mp3 alias s1),NULL,0,NULL);mciSendString(TEXT(play s1),NULL,0,NULL);Sleep(153*1000);//153*1000意思是153秒,是整首音乐的时长 mciSendString(TEXT(close S1),NULL,0,NULL); }//循环播放音乐线程函数
void* thread_bgmusic(void* arg) //
{ while(1){ play_bgmusic();}
} //创建音乐播放线程,开始循环播放音乐
void bgmusic()
{pthread_t tid; pthread_create(tid, NULL, thread_bgmusic, NULL);
}
四、运行效果
一子弹与炮弹相撞 二炮弹与飞机相撞、飞机复活 未完待续