[导读]本系列博文内容链接如下:
【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值
【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动
【C++】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动【C++】做一个飞机空战小游戏(四)——给游戏添加背景音乐(多线程技巧应用)
【C++】做一个飞机空战小游戏(五)——getch()控制两个飞机图标移动(控制光标位置)
【C++】做一个飞机空战小游戏(六)——给两架飞机设置不同颜色(cout输出彩色字符、结构体使用技巧)
【C++】做一个飞机空战小游戏(七)——两组按键同时检测平滑移动(GetAsyncKeyState()函数应用)
在上一节
【C++】做一个飞机空战小游戏(六)——给两架飞机设置不同颜色(cout输出彩色字符、结构体使用技巧)
中实现了利用键盘控制两组方向键控制两个不同颜色、造型的飞机移动,但是实际测试过程中发现,两组方向键盘会相互影响,不能实现两组方向键长按指令,而且移动有卡顿,不平滑。经过查询资料,发现可以利用windows自带的GetAsyncKeyState()函数实现可以同时检测两组按键,并且移动比较平滑。
参考博文:20191223同时检测多个按键和按键平滑处理_c++检测用户同时按下多个按键_lee李家军的博客-CSDN博客
//获取键盘指令函数
void key(void)
{
direction_cmd c=none_cmd;
direction_cmd d=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;
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].keycmd=c;
plane[1].keycmd=d;
}
把位置更新的函数,从主线程中移动到按键检测线程中。
检测按键线程内加入飞机位置更新函数。注意,线程中要加一个延时函数,延时的时间要进行测试,以长按时能显示出每次移动一个位置,而且移动比较平滑为准。
void* thread_key(void* arg)
{
while(1)
{
Sleep(60); //获取指令延时一定时间,起滤波作用,延缓获取指令的响应速度
key(); //获取按键指令
plane_location_update() ;//获取完指令马上更新飞机坐标
}
}
#include "control_plane.h"
using namespace std;
Plane plane[num_plane];
int main(int argc, char** argv) {
init(); //初始化
bgmusic();//播放背景音乐
getkey();
while(1) //循环等待键盘指令
{
if(plane[0].keycmd!=none_cmd ||plane[1].keycmd!=none_cmd)
{
system("cls");
for(int i=0;i
#ifndef CONTROL_PLANE_H
#define CONTROL_PLANE
#include
#include
#include
#include
#include //导入线程头文件库
#include //导入声音头文件库
#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 num_plane 2 //飞机架数
//定义飞机造型
const string icon_plane1[]={" ■","■ ■ ■","■■■■■","■ ■ ■"," ■"," ■■■"};
const string icon_plane2[]={" ■","■ ■ ■","■■■■■"," ■"," ■■■","■■■■■"};
//定义坐标结构体
typedef struct{
int x;
int y;
} Location;
//定义移动方向命令枚举类型
typedef enum {none_cmd,up_cmd,down_cmd,left_cmd,right_cmd} direction_cmd;
//定义飞机结构体
typedef struct{
Location location;
int color;
int icon;
direction_cmd keycmd;
}Plane;
extern Plane plane[num_plane];
//声明刷新飞机位置函数
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 //T表示任何可以被cout输出的类型
void ColorCout(T t, const int ForeColor = 7, const int BackColor = 0);
#endif
#include
#include "conio.h"
#include
#include "control_plane.h"
#include
using namespace std;
//彩色输出函数
template //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].color=1;
plane[1].color=2;
plane[0].icon=1;
plane[1].icon=2;
system("cls");
for(int i=0;ib_b) //限定y高度
{
y=b_b;
}
break;
case left_cmd:
x--; //字符左移一列,列值x减1
if(xr_b)
{
x=r_b; //限定x宽度
}
break;
}
plane[i].location.x=x;
plane[i].location.y=y;
plane[i].keycmd=none_cmd;
}
}
}
(未完待续)