离职删除做的网站,wordpress邮箱内容更改,工装哪家装修公司好,mysql做wp网站[导读]本系列博文内容链接如下#xff1a; 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C】做一个飞… [导读]本系列博文内容链接如下 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C】做一个飞机空战小游戏(四)——给游戏添加背景音乐(多线程技巧应用) 【C】做一个飞机空战小游戏(五)——getch()控制两个飞机图标移动(控制光标位置) 【C】做一个飞机空战小游戏(六)——给两架飞机设置不同颜色(cout输出彩色字符、结构体使用技巧) 【C】做一个飞机空战小游戏(七)——两组按键同时检测平滑移动(GetAsyncKeyState()函数应用) 【C】做一个飞机空战小游戏(八)——生成敌方炮弹(rand()函数应用) 前边7讲都是介绍飞机控制的方法从今天开始介绍敌方炮弹生成的方法。炮弹生成所用到的rand()函数详细介绍见【c】rand()随机函数的应用(一)——rand()函数详解和实例_一只爬爬虫的博客-CSDN博客
目录
一、生成敌方炮弹的几个关键问题
一炮弹的数量
1、每轮炮弹数量(bombs_round)
2、每关总炮弹数量(bombs_stage)
3、最大同屏炮弹数量(end_bombs_round)
二炮弹出现的时间(rt)
三炮弹的起始位置
1、y坐标
2、x坐标
四炮弹移动速度(bomb_interval)
五炮弹与飞机相撞或被飞机子弹击落
二、构造结构体
一游戏结构体Game
二炮弹结构体Bomb
三、新增与炮弹相关的函数
一单个炮弹初始化函数
二所有炮弹初始化
三炮弹位置更新线程函数
四炮弹位置更新线程启动函数
四、更新后的程序代码
一主函数
二头文件control_plane.h
三库函数control_plane.cpp 一、生成敌方炮弹的几个关键问题
一炮弹的数量
1、每轮炮弹数量(bombs_round)
每轮炮弹数量也就是屏幕当中出现的最多炮弹数量也就是敌方同一波发射的最多炮弹数量数量越多难度也越大这个数量可随关数的增加而增加。
2、每关总炮弹数量(bombs_stage)
每关发射的炮弹总数量不一样关数越高炮弹总数量也越多。
3、最大同屏炮弹数量(end_bombs_round)
最大单轮炮弹数量也就是最后一关敌方同一波发射炮弹数量。
二炮弹出现的时间(rt)
同一波炮弹出现的时间不能一样否则所有炮弹呈现一排游戏的体验感较差所以炮弹出现的时间也应该是随机的也就是炮弹的y值是随机的。如下图所示黄色方框为敌方炮弹。 为了实现这个效果炮弹设置了一个炮弹坠地(炮弹到达屏幕最下方)、被击落或者与飞机相撞后死亡复活时间(respawn time缩写为rt)在复活期间炮弹不出现在屏幕。这个复活时间是随机的这个时间会自减1当这个时间降为0的时候炮弹复活才从屏幕上方出现。
三炮弹的起始位置
1、y坐标
炮弹开始出现在屏幕的位置位于屏幕最上方也就是y0处但因为炮弹有复活时间炮弹的起始位置不能在y0处防止炮弹还未复活就被击落。所以炮弹的起始位置设置在屏幕最下侧再往下一行也就是b_b6b_b为飞机坐标的下边界6为飞机图标的高度。这样炮弹在复活期间就不会与飞机相撞也不会被飞机发射的子弹击中。
所以炮弹从死亡开始到复活前其位置为x坐标随机yb_b6而且在复活期间位置不发生移动。复活后x坐标不变y0然后y值自加1。
2、x坐标
x坐标在死亡后复活前和复活后都是随机生成的且坐标值一样。为了简化游戏难度炮弹出现在屏幕中后x坐标值不发生变化仅有y值再增加也就是炮弹是竖直下落的。
四炮弹移动速度(bomb_interval)
炮弹移动速度由炮弹位置更新线程函数内的Sleep函数的参数决定数值越大位置更新的间隔越大移动速度就越小反之就越快。
五炮弹与飞机相撞或被飞机子弹击落
本文今天暂时没考虑后边会实现这个功能。
二、构造结构体
一游戏结构体Game
//定义游戏结构体
typedef struct{int stage; //游戏当前关 int bombs_round; //敌方每轮发射炮弹数量 int bombs_stage; //每关总计出现炮弹数量 bool complete; //游戏通关 bool gameover; //游戏结束int num_plane; //飞机数量 int cur_num_bomb; //当前已发射炮弹数量 int bomb_interval; //位置更新间隔 bool bomb_move; //炮弹是否移动
}Game;
二炮弹结构体Bomb
//定义敌方炮弹结构体
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;
三、新增与炮弹相关的函数
一单个炮弹初始化函数
这个函数在单个炮弹死亡后调用。
//单个炮弹初始化函数
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; //eq_rt为复活最长时间return bomb;
}
此处init_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){Sleep(game.bomb_interval);game.bomb_movetrue;for(int i0;igame.bombs_round;i){ if(bomb[i].alive){bomb[i].location.y; }else{bomb[i].rt--;if(bomb[i].rt0){bomb[i].alivetrue;bomb[i].location.y0;} }if(bomb[i].location.yb_b5){bomb[i].hp0; }if(bomb[i].hp0){bomb[i]init_bomb(bomb[i]); }} }
}
四炮弹位置更新线程启动函数
这个函数在主函数中调用启动然后一直运行。
//炮弹位置更新线程启动函数
void bomb_location_update()
{pthread_t tid; pthread_create(tid, NULL, thread_bomb, NULL);
}四、更新后的程序代码
一主函数
#include control_plane.h
using namespace std; Plane plane[eq_plane];
Game game;
Bomb bomb[eq_bombs_round];int main(int argc, char** argv) { init(); //初始化 bgmusic();//播放背景音乐getkey();bomb_location_update(); while(1) //循环等待键盘指令 {if(plane[0].keycmd!none_cmd ||plane[1].keycmd!none_cmd ||game.bomb_move){game.bomb_movefalse;system(cls);for(int i0;igame.num_plane;i){show_plane(plane[i]); //刷新飞机图标}for(int i0;igame.bombs_round;i){if(bomb[i].alive){show_bomb(bomb[i]);}}}}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 eq_plane 2 //飞机架数
#define eq_bombs_round 23 //eqend quantity最终炮弹数量
#define eq_rt 10 //复活最大时间//定义飞机造型
const string icon_plane1[]{ ■,■ ■ ■,■■■■■,■ ■ ■, ■, ■■■};
const string icon_plane2[]{ ■,■ ■ ■,■■■■■, ■, ■■■,■■■■■};//定义炮弹造型
const string icon_bomb■;//定义坐标结构体
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; //炮弹是否移动
}Game;//定义飞机结构体
typedef struct{Location location;int color;int icon;direction_cmd keycmd;
}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;extern Plane plane[eq_plane];
extern Game game;
extern Bomb bomb[eq_bombs_round];//声明刷新飞机位置函数
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);#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].location{2*r_b/3,b_b};plane[1].location{r_b/3,b_b};plane[0].color1;plane[1].color2;plane[0].icon1;plane[1].icon2;srand(time(NULL));game.num_plane2;game.bombs_round3;game.bomb_movefalse;game.bomb_interval1000;init_bombs();system(cls);for(int i0;igame.num_plane;i)//刷新飞机图标{ show_plane(plane[i]); plane[i].keycmdnone_cmd; }
// game.num_plane2; 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)
{direction_cmd cnone_cmd;direction_cmd dnone_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;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[0].keycmdc;plane[1].keycmdd;
}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){Sleep(game.bomb_interval);game.bomb_movetrue;for(int i0;igame.bombs_round;i){ if(bomb[i].alive){bomb[i].location.y; }else{bomb[i].rt--;if(bomb[i].rt0){bomb[i].alivetrue;bomb[i].location.y0;} }if(bomb[i].location.yb_b5){bomb[i].hp0; }if(bomb[i].hp0){bomb[i]init_bomb(bomb[i]); }} }
}
//炮弹位置更新
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;gotoxy(x,y);ColorCout(bomb.icon,bomb.color);} //********************************************************************************//以下三个函数为播放背景音乐功能
//********************************************************************************//播放一遍背景音乐 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);
}
未完待续