【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、子弹、炮弹初始血量和伤害值

子弹炮弹相撞前:

子弹、炮弹血量hp=1;

子弹、炮弹伤害值dam=1;

2、子弹与炮弹相撞后血量

子弹炮弹相撞后:

相撞后子弹血量=相撞前子弹血量-炮弹伤害值;

相撞后炮弹血量=相撞前炮弹血量-子弹伤害值;

因此,子弹炮弹相撞后,两者血量都为0,alive值都为false,会同归于尽,炮弹被击落。

3、击落函数

 bool shoot(Bullet bullet,Bomb bomb)
{bool sbb,sx0,sx1,sy0,sy1;sx0=(bomb.location.x>=bullet.location.x-1);sx1=(bomb.location.x<=bullet.location.x+1);	sy0=(bomb.location.y>=bullet.location.y);sy1=(bomb.location.y<=bullet.location.y+1);	sbb=sx0 &&sx1&&sy0&&sy1;return sbb;
}

4、击落后血量变化代码

这部分代码在子弹位置更新线程中,具体如下:

for(int k=0;k<game.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.alive=true;	plane.hp=3;	plane.keycmd=none_cmd;plane.location=plocation[plane.No];plane.color=plane.No+1;plane.icon=plane.No+1;		return plane;
}

初始化函数用在游戏开始和飞机复活时,函数中没有设置No和life两项,因为No值不同,而life值每次死亡时减1,复活后不能再恢复为原值。

(2)所有飞机初始化

//所有飞机初始化函数 
void init_planes(void)
{for(int i=0;i<game.num_plane;i++)//刷新飞机图标{			plane[i]=init_plane(plane[i]);}
}

3、飞机初始血量

飞机初始血量hp=3,飞机没有设置伤害值,默认其伤害值为无穷大。

4、飞机与炮弹相撞后血量

(1)炮弹血量

炮弹与飞机相撞后,炮弹血量直接降为0,alive值为false。

(2)飞机血量

飞机与炮弹相撞后,相撞后飞机血量值=相撞前血量值-炮弹伤害值。飞机血量值小于等于0时,飞机死亡,alive值为false。

5、飞机命数

飞机命数life初始值为3。如果飞机死亡,其命数life值减1。

6、相撞函数

 bool collide(Plane plane,Bomb bomb)
{bool cpb,cx0,cx1,cy0,cy1;cx0=bomb.location.x>=plane.location.x-1;cx1=bomb.location.x<=plane.location.x+plane_width;cy0=bomb.location.y>=plane.location.y;cy1=bomb.location.y<=plane.location.y+plane_height; cpb=cx0 && cx1 && cy0 && cy1;return cpb;
}

7、相撞后血量命数变化代码

飞机血量、命数的变化代码放置在炮弹位置更新线程中,具体内容如下:

for(int j=0;j<game.num_plane;j++)
{if(plane[j].alive){if(collide(plane[j],bomb[i])) {bomb[i].hp=0;plane[j].hp-=bomb[i].dam;	}if(plane[j].hp<=0){plane[j].alive=false;plane[j].life=plane[j].life-1;plane[j].keycmd=none_cmd;plane[j].location.x=0;plane[j].location.y=b_b+8;									}					}}

8、飞机复活

按复活键可复活,当命数小于1时,不能再复活,永久死亡。plane[0]的复活代码如下:

if(plane[0].life>0)
{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.pause=true,游戏暂停,再按一次game.pause=false,游戏恢复,代码在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_move=false;game.bullet_move=false;system("cls");for(int i=0;i<game.num_plane;i++){if(plane[i].alive){show_plane(plane[i]);//刷新飞机图标}}for(int i=0;i<game.bombs_round;i++){if(bomb[i].alive){show_bomb(bomb[i]);}}for(int i=0;i<eq_plane;i++){for(int j=0;j<eq_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>
#include<stdlib.h>
#include<windows.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	//eq=end quantity最终炮弹数量 
#define eq_rt 10	//复活最大时间
#define eq_bullets_round 20	//eq=end 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;				//rt=respawn time复活时间 int hp;				//hp=hit point 生命值,此值<=0时,敌方炮弹死亡,敌方炮弹被飞机子弹击中hp会减少,坠地或与飞机相撞hp直接降为0 int dam;			//dam=damage 伤害值int type;			//炮弹类型 
}Bomb;//定义子弹结构体 
typedef struct{Location location;	//子弹位置 bool alive;			//子弹是否存活 int color;			//子弹颜色string icon;		//子弹图标	int hp;				//hp=hit point 生命值,子弹击中炮弹或冲出屏幕上方hp直接降为0,子弹死亡 int dam;			//dam=damage 伤害值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();//输出彩色字符函数
template<typename 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"
#include<windows.h>
using namespace std;//彩色输出函数
template<typename 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].No=0;plane[1].No=1;plane[0].life=3;		plane[1].life=3;srand(time(NULL));game.num_plane=2;game.bombs_round=3;game.bomb_move=false;game.bullet_move=false;game.bomb_interval=1000;game.stage=1;game.bombs_stage=100;game.pause=false;	init_bombs();init_bullets();init_planes();system("cls");for(int i=0;i<game.num_plane;i++)//刷新飞机图标{			show_plane(plane[i]);}game.bombs_round=3;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 c=none_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].keycmd=c;												//刷新飞机方向指令											 if (GetAsyncKeyState('P') & 0x8000)		plane[0].fire = true;	//飞机开火指令}else{if(plane[0].life>0){if (GetAsyncKeyState('O') & 0x8000)							//飞机复活指令{plane[0]=init_plane(plane[0]);show_plane(plane[0]);}}}if(plane[1].alive){direction_cmd d=none_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].keycmd=d;//刷新飞机图标if (GetAsyncKeyState('F') & 0x8000)			plane[1].fire = true;}else{if(plane[1].life>0){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是行坐标,原点(x=0,y=0)位于屏幕左上角 
{int x,y;int i,j;int rows;x=plane.location.x;y=plane.location.y;switch(plane.icon){case 1://第一种造型 rows=sizeof(icon_plane1)/sizeof(icon_plane1[0]);for(i=0;i<rows;i++)				 {gotoxy(x,y+i);				ColorCout(icon_plane1[i],plane.color);}break;case 2://第二种造型 rows=sizeof(icon_plane2)/sizeof(icon_plane2[0]);for(i=0;i<rows;i++)				{gotoxy(x,y+i);				ColorCout(icon_plane2[i],plane.color);}break;				}
}//更新两个飞机的坐标 
void plane_location_update(void)
{ 	for(int i=0;i<2;i++){if(plane[i].keycmd!=none_cmd) {int x,y;x=plane[i].location.x;y=plane[i].location.y;switch(plane[i].keycmd){case up_cmd:y--;				//字符上移一行,行值y减1if(y<t_b)			//限定y值最小值为0{y=t_b;}break;case down_cmd:y++;				//字符下移一行,行值y加1if(y>b_b)			//限定y高度 {y=b_b;}break;case left_cmd:x--;				//字符左移一列,列值x减1if(x<l_b){x=l_b;			//限定x最小值为0; }break;case right_cmd:x++;				//字符右移一列,列值x加1if(x>r_b){x=r_b;			//限定x宽度}break;}plane[i].location.x=x;plane[i].location.y=y;plane[i].keycmd=none_cmd;	}} 		
}//单个炮弹初始化函数 
Bomb init_bomb(Bomb bomb)
{bomb.location.x=rand()%r_b;	bomb.location.y=b_b+6;bomb.icon=icon_bomb;bomb.color=6;bomb.dam=1;bomb.hp=1;bomb.alive=false;bomb.rt=rand()%(eq_rt+1)+1;	return bomb;			
}//所有炮弹初始化函数 
void init_bombs(void)
{game.bomb_move=false;for(int i=0;i<game.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_move=true;for(int i=0;i<game.bombs_round;i++){			if(bomb[i].alive){bomb[i].location.y++;if(bomb[i].location.y>b_b+5){bomb[i].hp=0;									}for(int j=0;j<game.num_plane;j++){if(plane[j].alive){if(collide(plane[j],bomb[i])) {bomb[i].hp=0;plane[j].hp-=bomb[i].dam;	}if(plane[j].hp<=0){plane[j].alive=false;plane[j].life=plane[j].life-1;plane[j].keycmd=none_cmd;plane[j].location.x=0;plane[j].location.y=b_b+8;									}					}}				if(bomb[i].hp<=0){bomb[i]=init_bomb(bomb[i]);				}			}else{bomb[i].rt--;if(bomb[i].rt<=0){bomb[i].alive=true;bomb[i].location.y=0;}			}}		}
}
//炮弹位置更新 
void bomb_location_update()
{pthread_t tid; pthread_create(&tid, NULL, thread_bomb, NULL);
}炮弹图标刷新函数
void show_bomb(Bomb bomb)		//预先定义字符定位显示函数,x是列坐标,y是行坐标,原点(x=0,y=0)位于屏幕左上角 
{int x,y;	x=bomb.location.x;y=bomb.location.y;hide();//隐藏光标gotoxy(x,y);ColorCout(bomb.icon,bomb.color);} //发射子弹 
Bullet fire(Plane plane,Bullet bullet)
{game.bullet_move=true;bullet.location.x=plane.location.x+plane_width/2;	bullet.location.y=plane.location.y-1;bullet.alive=true;		return bullet;			
}//单个子弹初始化函数
Bullet init_bullet(Bullet bullet)
{bullet.icon=icon_bullet;bullet.location.x=0;bullet.location.y=b_b+7;bullet.alive=false;bullet.color=4;bullet.dam=1;bullet.hp=1;	return bullet;			
}//所有子弹初始化函数 
void init_bullets(void)
{game.bullet_move=false;	for(int i=0;i<eq_plane;i++){for(int j=0;j<eq_bullets_round;j++){bullet[i][j]=init_bullet(bullet[i][j]);	}	}
}//单个飞机初始化函数
Plane init_plane(Plane plane)
{plane.alive=true;	plane.hp=3;	plane.keycmd=none_cmd;plane.location=plocation[plane.No];plane.color=plane.No+1;plane.icon=plane.No+1;		return plane;
}//所有飞机初始化函数 
void init_planes(void)
{for(int i=0;i<game.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 i=0;i<eq_plane;i++){if(plane[i].fire)			//如果飞机开火,要搜寻一个子弹处于死亡状态的位置激活子弹 {					game.bullet_move=true;	for(int j=0;j<eq_bullets_round;j++){if(!bullet[i][j].alive){bullet[i][j]=fire(plane[i],bullet[i][j]);break;}	}}plane[i].fire=false;				}for(int i=0;i<eq_plane;i++){for(int j=0;j<eq_bullets_round;j++){				if(bullet[i][j].alive){bullet[i][j].location.y--;if(bullet[i][j].location.y<0){bullet[i][j].hp=0;									}for(int k=0;k<game.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].hp<=0){//bullet[i][j].alive=false;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是行坐标,原点(x=0,y=0)位于屏幕左上角 
{int x,y;	x=bullet.location.x;y=bullet.location.y;hide();//隐藏光标gotoxy(x,y);ColorCout(bullet.icon,bullet.color);		
} //********************************************************************************//以下函数为子弹被击落或撞落功能 
//********************************************************************************bool collide(Plane plane,Bomb bomb)
{bool cpb,cx0,cx1,cy0,cy1;cx0=bomb.location.x>=plane.location.x-1;cx1=bomb.location.x<=plane.location.x+plane_width;cy0=bomb.location.y>=plane.location.y;cy1=bomb.location.y<=plane.location.y+plane_height; cpb=cx0 && cx1 && cy0 && cy1;return cpb;
}bool shoot(Bullet bullet,Bomb bomb)
{bool sbb,sx0,sx1,sy0,sy1;sx0=(bomb.location.x>=bullet.location.x-1);sx1=(bomb.location.x<=bullet.location.x+1);	sy0=(bomb.location.y>=bullet.location.y);sy1=(bomb.location.y<=bullet.location.y+1);	sbb=sx0 &&sx1&&sy0&&sy1;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);
}

四、运行效果

(一)子弹与炮弹相撞

(二)炮弹与飞机相撞、飞机复活

 (未完待续)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/97796.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unsafe upfileupload

文章目录 client checkMIME Typegetimagesize 文件上传功能在web应用系统很常见&#xff0c;比如很多网站注册的时候需要上传头像、上传附件等等。当用户点击上传按钮后&#xff0c;后台会对上传的文件进行判断 比如是否是指定的类型、后缀名、大小等等&#xff0c;然后将其按…

HTML中的字符串转义

为什么要转义&#xff1f; 转义可以防止 xss 攻击。接下来&#xff0c;我们来看一下如何转义。 HTML Sanitizer API Sanitizer 是浏览器自带的转义方法&#xff0c;在2021年初被提出&#xff0c;兼容性问题很大。 列举几个常用的 API&#xff1a; const $div document.qu…

【广州华锐视点】VR线上教学资源平台提供定制化虚拟现实学习内容

虚拟现实&#xff08;VR&#xff09;技术的出现为我们提供了一种全新的在线教学方式。由广州华锐视点开发的VR线上教学资源平台&#xff0c;作为一个综合性的学习工具&#xff0c;正在教育领域迅速发展&#xff0c;并被越来越多的教育机构和学生所接受。那么&#xff0c;VR线上…

redis实战-缓存数据解决缓存与数据库数据一致性

缓存的定义 缓存(Cache),就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于本地代码。防止过高的数据访问猛冲系统,导致其操作线程无法及时处理信息而瘫痪&#xff0c;这在实际开发中对企业讲,对产品口碑,用户评价都是致命的;所以企业非常重视缓存…

ReactNative进阶(三十四):ipa Archive 阶段报错error: Multiple commands produce问题修复及思考

文章目录 一、前言二、问题描述三、问题解决四、拓展阅读五、拓展阅读 一、前言 在应用RN开发跨平台APP阶段&#xff0c;从git中拉取项目&#xff0c;应用Jenkins进行组包时&#xff0c;发现最终生成的ipa安装包版本号始终与项目中设置的版本号不一致。 二、问题描述 经过仔…

图数据库_Neo4j和SpringBoot整合使用_实战创建明星关系图谱---Neo4j图数据库工作笔记0010

然后我们再来看一下这个明星关系图谱 可以看到这里 这个是原来的startRelation 我们可以写CQL去查询对应的关系 可以看到,首先查询出来以后,然后就可以去创建 我们可以把写的创建明星关系的CQL,拿到 springboot中去执行 可以看到,这里我们先写一个StarRelationRepository,然…

【100天精通python】Day42:python网络爬虫开发_HTTP请求库requests 常用语法与实战

目录 1 HTTP协议 2 HTTP与HTTPS 3 HTTP请求过程 3.1 HTTP请求过程 3.2 GET请求与POST请求 3.3 常用请求报头 3.4 HTTP响应 4 HTTP请求库requests 常用语法 4.1 发送GET请求 4.2 发送POST请求 4.3 请求参数和头部 4.4 编码格式 4.5 requests高级操作-文件上传 4.6 …

机器学习之数据集

目录 1、简介 2、可用数据集 3、scikit-learn数据集API 3.1、小数据集 3.2、大数据集 4、数据集使用 ⭐所属专栏&#xff1a;人工智能 文中提到的代码如有需要可以私信我发给你&#x1f60a; 1、简介 当谈论数据集时&#xff0c;通常是指在机器学习和数据分析中使用的一组…

代码pytorch-adda-master跑通记录

前言 最近在学习迁移学习&#xff0c;ADDA算法&#xff0c;由于嫌自己写麻烦&#xff0c;准备先跑通别人的代码。 代码名称&#xff1a;pytorch-adda-master 博客&#xff1a;https://www.cnblogs.com/BlairGrowing/p/17020378.html github地址&#xff1a;https://github.com…

【C语言练习】数组OJ题

目录 一.消失的数字思路1&#xff1a;思路2&#xff1a; 二.移除元素三.轮转数组四.删除有序数组中的重复项五.合并两个有序数组 一.消失的数字 题目&#xff1a; 思路1&#xff1a; 数组是从0加到N&#xff0c;所以把0到N的数加起来减去数组中的值&#xff0c;结果就是消失…

HLK-LD105/2410B/2420模块测试

HLK105/2410B/2420模块测试 &#x1f4cc;模块资料地址&#xff1a;https://h.hlktech.com/Mobile/download &#x1f33f;HLK-LD105模块&#xff1a; 10G微波雷达 &#x1f33f;HLK-LD2420-24G&#xff1a;24G毫米波雷达 &#x1f33f;HLK-LD2410B-24G&#xff1a;24…

AVL树的讲解

算法拾遗三十八AVL树 AVL树AVL树平衡性AVL树加入节点AVL删除节点AVL树代码 AVL树 AVL树具有最严苛的平衡性&#xff0c;&#xff08;增、删、改、查&#xff09;时间复杂度为O&#xff08;logN&#xff09;&#xff0c;AVL树任何一个节点&#xff0c;左树的高度和右树的高度差…

Java之线程的状态

文章目录 一、线程状态二、代码演示1. Threadstate 类2. SleepUtils 类3. 运行示例 三、参考资料 一、线程状态 Java线程在运行的生命周期中可能处于下图所示的6种不同的状态,在给定的一个时刻线程只能处于其中的一个状态。 Java线程的状态 状态名称说明NEW初始状态&#xff0…

C++继承

一、继承的定义 class Person { public:void Print(){cout << "name:" << _name << endl;cout << "age:" << _age << endl;} protected:string _name "peter"; // 姓名int _age 18; // 年龄 };class Stu…

Java-抽象类和接口(下)

接口使用实例 给对象数组排序 两个学生对象的大小关系怎么确定? 需要我们额外指定. 这里需要用到Comparable 接口 在Comparable 接口内部有一个compareTo 的方法&#xff0c;我们需要实现它 在下图中&#xff0c;我们需要将o强制转换为Student 之后调用Arrays.sort(array)即…

恢复NuGet包_解决:System.BadImageFormatException:无法加载文件或程序集

C#工程 主要是开发了一个 web api接口&#xff0c;这个工程源码去年还可以的&#xff0c;今年换了一个电脑打开工程就报错。 错误提示如下&#xff1a; 在 Microsoft.CodeAnalysis.CSharp.CommandLine.Program.Main(String[] args) Test1 System.BadImageFormatEx…

Vue 项目搭建

环境配置 1. 安装node.js 官网&#xff1a;nodejs&#xff08;推荐 v10 以上&#xff09; 官网&#xff1a;npm 是什么&#xff1f; 由于vue的安装与创建依赖node.js&#xff08;JavaScript的运行环境&#xff09;里的npm&#xff08;包管理和分发工具&#xff09;&#xff…

线上售楼vr全景看房成为企业数字化营销工具

在房地产业中&#xff0c;VR全景拍摄为买家提供了虚拟看房的全新体验。买家可以通过相关设备&#xff0c;远程参观各个楼盘的样板间和实景&#xff0c;感受房屋的空间布局和环境氛围&#xff0c;极大地提高了购房决策的准确性。对于房地产开发商和中介机构来说&#xff0c;VR全…

docker的安装与基础使用

一.docker简介 1&#xff09;什么是docker Docker是一种用于构建、打包和运行应用程序的开源平台。它基于操作系统级虚拟化技术&#xff0c;可以将应用程序和其依赖的库、环境等资源打包到一个可移植的容器中&#xff0c;形成一个轻量级、独立的可执行单元。 开发者在本地编…

Rabbitmq的应用场景

Rabbitmq的应用场景 一、异步处理 场景说明&#xff1a;用户注册后&#xff0c;需要发注册邮件和注册短信,传统的做法有两种 1.串行的方式 2.并行的方式 ​​串行方式​​: 将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务全部完成后才返回给客户端。 这有…