【C++】做一个飞机空战小游戏(七)——两组按键同时检测平滑移动(GetAsyncKeyState()函数应用)

这篇具有很好参考价值的文章主要介绍了【C++】做一个飞机空战小游戏(七)——两组按键同时检测平滑移动(GetAsyncKeyState()函数应用)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 [导读]本系列博文内容链接如下:

【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值

【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动
【C++】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动

【C++】做一个飞机空战小游戏(四)——给游戏添加背景音乐(多线程技巧应用)

【C++】做一个飞机空战小游戏(五)——getch()控制两个飞机图标移动(控制光标位置)

【C++】做一个飞机空战小游戏(六)——给两架飞机设置不同颜色(cout输出彩色字符、结构体使用技巧)

【C++】做一个飞机空战小游戏(七)——两组按键同时检测平滑移动(GetAsyncKeyState()函数应用)

【C++】做一个飞机空战小游戏(八)——生成敌方炮弹(rand()函数应用)

【C++】做一个飞机空战小游戏(九)——发射子弹的编程技巧

【C++】做一个飞机空战小游戏(十)——子弹击落炮弹、炮弹与飞机相撞 

一、GetAsyncKeyState()函数

在上一节

【C++】做一个飞机空战小游戏(六)——给两架飞机设置不同颜色(cout输出彩色字符、结构体使用技巧)

中实现了利用键盘控制两组方向键控制两个不同颜色、造型的飞机移动,但是实际测试过程中发现,两组方向键盘会相互影响,不能实现两组方向键长按指令,而且移动有卡顿,不平滑。经过查询资料,发现可以利用windows自带的GetAsyncKeyState()函数实现可以同时检测两组按键,并且移动比较平滑。

参考博文:20191223同时检测多个按键和按键平滑处理_c++检测用户同时按下多个按键_lee李家军的博客-CSDN博客

二、代码优化

(一)key()函数

//获取键盘指令函数
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;
}

(二)主函数

把位置更新的函数,从主线程中移动到按键检测线程中。

(三)thread_key()

检测按键线程内加入飞机位置更新函数。注意,线程中要加一个延时函数,延时的时间要进行测试,以长按时能显示出每次移动一个位置,而且移动比较平滑为准。

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<num_plane;i++)
			{
				show_plane(plane[i]);	//刷新飞机图标
			}
		}		
	}
	return 0; 	
}

(二)头文件control_plane.h

#ifndef CONTROL_PLANE_H
#define CONTROL_PLANE
#include <iostream>
#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 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<typename T>	//T表示任何可以被cout输出的类型 
void ColorCout(T t, const int ForeColor = 7, const int BackColor = 0);

#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].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;i<num_plane;i++)//刷新飞机图标
		{		
			show_plane(plane[i]);	
			plane[i].keycmd=none_cmd;		
		}
	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 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 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);
}
 
 
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减1
					if(y<t_b)			//限定y值最小值为0
					{
						y=t_b;
					}
					break;
				case down_cmd:
					y++;				//字符下移一行,行值y加1
					if(y>b_b)			//限定y高度 
					{
						y=b_b;
					}
					break;
				case left_cmd:
					x--;				//字符左移一列,列值x减1
					if(x<l_b)
					{
						x=l_b;			//限定x最小值为0; 
					}
					break;
				case right_cmd:
					x++;				//字符右移一列,列值x加1
					if(x>r_b)
					{
						x=r_b;			//限定x宽度
					}
					break;
				
			}
			plane[i].location.x=x;
 			plane[i].location.y=y;
 			plane[i].keycmd=none_cmd;	
		}
					
	} 		
} 

(未完待续)文章来源地址https://www.toymoban.com/news/detail-647838.html

到了这里,关于【C++】做一个飞机空战小游戏(七)——两组按键同时检测平滑移动(GetAsyncKeyState()函数应用)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值

     [导读]本系列博文内容链接如下: 【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 【C++】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C++】做一个飞

    2024年02月15日
    浏览(28)
  • 【C++】做一个飞机空战小游戏(八)——生成敌方炮弹(rand()和srand()函数应用)

     [导读]本系列博文内容链接如下: 【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 【C++】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C++】做一个飞

    2024年02月12日
    浏览(55)
  • 【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动

     [导读]本系列博文内容链接如下: 【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 【C++】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C++】做一个飞

    2024年02月15日
    浏览(29)
  • 【C++】做一个飞机空战小游戏(六)——给两架飞机设置不同颜色(cout输出彩色字符、结构体使用技巧)

      [导读]本系列博文内容链接如下: 【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 【C++】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C++】做一个飞

    2024年02月14日
    浏览(34)
  • C++控制台打飞机小游戏

    我终于决定还是把这个放出来。 视频在这:https://v.youku.com/v_show/id_XNDQxMTQwNDA3Mg==.html 具体信息主界面上都有写。 按空格暂停,建议暂停后再升级属性。 记录最高分的文件进行了加密。 有boss(上面视频2分47秒)。 挺好玩的。 可能有bug,不想改了,整体体验不错就行了。 更多

    2024年02月05日
    浏览(37)
  • Python开发小游戏:写一个飞机大战只需要500行代码!

    ‘’’ :param background_image_path: 背景图片的路径地址 :param size: 游戏窗口的大小 :param title: 游戏窗口的标题 :param font_name: 指定字体 :param font_size: 指定字体大小 :param speed: 背景图滚动整个窗口一次所用时间,单位为ms ‘’’ self.size = size self.screen = pygame.display.set_mode(size) self.tit

    2024年04月11日
    浏览(38)
  • 超好玩C++控制台打飞机小游戏,附源码

    我终于决定还是把这个放出来。 视频在这:https://v.youku.com/v_show/id_XNDQxMTQwNDA3Mg==.html 具体信息主界面上都有写。 按空格暂停,建议暂停后再升级属性。 记录最高分的文件进行了加密。 有boss(上面视频2分47秒)。 挺好玩的。 可能有bug,不想改了,整体体验不错就行了。 更多

    2024年02月05日
    浏览(34)
  • Python飞机大战小游戏

    游戏规则:键盘上下左右键控制飞机移动 游戏展示图片: 源码: 第一个py命名为:plane_main.py 第二py命名为:plane_sprites.py 素材图片image关注私信我获取!!!

    2024年02月10日
    浏览(37)
  • python——飞机大战小游戏

    目录 1、导入模块 2、窗口操作 3、事件操作 4、长按事件 5、添加游戏背景 6、添加英雄飞机 7、获取飞机的图片矩形 8、基本游戏窗口 9、添加游戏窗口图片 10、英雄飞机登场 11、英雄飞机装备子弹并发射 1、enemy_plane 2、game_main 3、game_map 4、game_score 5、hero_plane 6、plane_bullet 先安

    2024年02月03日
    浏览(53)
  • python小游戏开发(飞机大战)

    目录 一:背景       1. pygame 模块初识 二.项目设计内容 开发一款飞机大战游戏,要求: (1)实现飞机的移动、子弹发射,对本次游戏有一个初步的编写及认识。 (2)飞机的持续按键移动和飞机自爆优化。 (3)进行基类的抽取,使代码更具有层次性和简化重复代码。 (

    2024年02月16日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包