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

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

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

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

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

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

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

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

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

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

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

飞机空战游戏,一般都是两个飞机,今天介绍一下如何用getch()通过不同的方向键组控制两个飞机移动。

一、控制光标的位置

(二)为什么要控制光标位置

1、避免控制多个图标移动相互影响

本例中本节之前的代码对飞机位置的控制是通过cout函数输出空格和换行来确定飞机图标x和y坐标,这种方式对于游戏中只有一个被控制图标是可行的,但是要控制多个图标移动就行不通了,因为输出换行和空格时会对另外的图标产生影响。

2、消除光标的闪烁现象

输出换行和空格时,光标会不断移动,所以在移动飞机图标时会有光标闪烁的情况,游戏的体验感不好。

而通过控制光标把光标直接移动到要显示飞机图标的位置,就避免了频繁输出换行和空格的操作,不会对屏幕上其他的图标产生影响,也消除了光标闪烁的情况。

(二)如何控制光标的输出位置

对光标位置的控制,本文参考了以下博文

C++移动输出端的光标代码实现_c++光标_我行我素,向往自由的博客-CSDN博客

代码如下所示,需要引入头文件windows.h,并自定义一个gotoxy(x,y)函数,x,y就是光标输出的位置。

#include<windows.h>
void gotoxy(int x, int y) {
	COORD pos = { x,y };
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出设备句柄
	SetConsoleCursorPosition(hOut, pos);//两个参数分别指定哪个窗口,具体位置
}

二、控制两个飞机图标移动程序

要想实现对两架飞机的控制,需要对代码进行部分更新,更新内容包括以下几方面。

(一)头文件control_plane.h

1、更新键盘指令枚举内容

增加一组控制飞机移动的指令,更新后的内容如下:

//定义移动方向命令枚举类型 
typedef  enum {up_cmd,down_cmd,left_cmd,right_cmd,up_cmd2,down_cmd2,left_cmd2,right_cmd2} direction_cmd;

"up_cmd2,down_cmd2,left_cmd2,right_cmd2"四项为新增加的内容。

2、增加一个飞机的结构体类型坐标

extern location plocation,plocation2;			//声明第二架飞机坐标 

3、更新飞机坐标计算函数声明

因为有两架飞机,需要计算两组坐标,所以在函数声明中增加了标识飞机序号的参量int n,具体代码如下:

//计算出接收指令后的飞机坐标 
location plane_locate(int n,location plct,direction_cmd dircmd);

(二)控制函数库control_plane.cpp

1、增加光标控制函数

void gotoxy(int x, int y) {
	COORD pos = { x,y };
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出设备句柄
	SetConsoleCursorPosition(hOut, pos);//两个参数分别指定哪个窗口,具体位置
}

2、更新显示飞机图标函数

有了控制光标函数之后,就可以把显示飞机图标的函数进行调整了,具体代码如下所示。

//飞机图标刷新函数 
void show_plane(location plct)		//预先定义字符定位显示函数,x是列坐标,y是行坐标,原点(x=0,y=0)位于屏幕左上角 
{
	int x,y;
	int i,j;	
	int rows=sizeof(icon_plane)/sizeof(icon_plane[0]);
	x=plct.x;
	y=plct.y;
	
	for(i=0;i<rows;i++)				//图标每行前输出x个空格 
	{
	    gotoxy(x,y+i);              //将光标移动到(x,y+i)位置
		cout<<icon_plane[i]<<endl;  //按行输出飞机图标
	}
}

3、初始化函数

初始化函数中增加另外一架飞机的初始位置,具体代码如下所示。

//初始化函数 
void init(void)
{
	plocation.x=2*r_b/3;				//初始化飞机1图标的x坐标为屏幕横轴最大值的2/3 
	plocation.y=b_b;					//初始化飞机1图标的y坐标为屏幕纵轴最大值
	plocation2.x=r_b/3;					//初始化飞机2图标的x坐标为屏幕横轴最大值的1/3 
	plocation2.y=b_b;					//初始化飞机2图标的y坐标为屏幕纵轴最大值
}

4、更新获取键盘指令函数

因为两架飞机,需要有两组控制飞机移动方向的控制键组合,第一组为双码按键“↑、↓、←、→”四个键,第二组为单码键'w'、's'、'a'、'd'四个键。所以函数中增加了第二组键的返回值。

//获取键盘指令函数 
direction_cmd key(void)
{
	int key_value1,key_value2;			//声明两个变量,存放键值 
	key_value1=getch();					//先获取第一个码值	
	if(key_value1==224)					//如果第一个码值为224,则进行第二个码值的判断 
		{
			key_value2=getch();			//先获取第二个码值
			
			switch(key_value2)
			{
				case 72:				//向上方向键 
					return up_cmd;
				case 80:				//向下方向键
					return down_cmd;
				case 75:				//向左方向键
					return left_cmd;
				case 77:				//向右方向键
					return right_cmd;
			}
			
		}
		else
		{
			switch(key_value1)
			{
				case 119:				//向上方向键 
					return up_cmd2;
				case 115:				//向下方向键
					return down_cmd2;
				case 97:				//向左方向键
					return left_cmd2;
				case 100:				//向右方向键
					return right_cmd2;
			}
		}		
}

5、更新了飞机获取指令后位置计算函数的定义

参量n代表飞机的序号,不同的飞机响应不同的指令dircmd,然后再根据不同的指令分别计算两架飞机位置。

//计算获得移动指令后飞机的坐标 
location plane_locate(int n,location plct,direction_cmd dircmd)
{
 	int x,y;
 	x=plct.x;
 	y=plct.y;
 	
 	if(n==1)
 	{
		switch(dircmd)
		{
			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;
				
			}
	}
	else if(n==2)
	{
		switch(dircmd)
		{
			case up_cmd2:
				y--;				//字符上移一行,行值y减1
				if(y<t_b)			//限定y值最小值为0
				{
					y=t_b;
				}
				break;
			case down_cmd2:
				y++;				//字符下移一行,行值y加1
				if(y>b_b)			//限定y高度 
				{
					y=b_b;
				}
				break;
			case left_cmd2:
				x--;				//字符左移一列,列值x减1
				if(x<l_b)
				{
					x=l_b;			//限定x最小值为0; 
				}
				break;
			case right_cmd2:
				x++;				//字符右移一列,列值x加1
				if(x>r_b)
				{
					x=r_b;			//限定x宽度
				}
				break;
				
		}
	}
		plct.x=x;
		plct.y=y;
		return plct;
 }

(二)最终程序

1、主函数

#include "control_plane.h"
using namespace std;

location plocation;
location plocation2;

int main(int argc, char** argv) {	
	init();	//初始化					 

	bgmusic();//播放背景音乐
	
	while(1)					//循环等待键盘指令 
	{
		system("cls");			//清屏
		show_plane(plocation);	//刷新飞机1图标
		show_plane(plocation2);	//刷新飞机2图标 		
		dir_cmd=key();			//获取按键指令 
		
		//计算收到键盘指令后的两架飞机坐标 
		plocation=plane_locate(1,plocation,dir_cmd);
		plocation2=plane_locate(2,plocation2,dir_cmd);	
	}
	return 0; 	
}

2、头文件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	//图形显示区域下侧边界


//定义飞机造型 
const string icon_plane[]={"    ■   ","■  ■  ■","■■■■■","■  ■  ■","    ■   ","  ■■■ "};

//定义图标坐标结构体 
typedef struct{
	int x;
	int y;
} location;

//定义移动方向命令枚举类型 
typedef  enum {up_cmd,down_cmd,left_cmd,right_cmd,up_cmd2,down_cmd2,left_cmd2,right_cmd2} direction_cmd;


extern location plocation,plocation2;			//声明飞机坐标 
static direction_cmd dir_cmd; 		//声明存放按键码值的两个变量

//声明刷新飞机位置函数 
void show_plane(location plct);

//获取键盘指令 
direction_cmd key(void);

//计算出接收指令后的飞机坐标 
location plane_locate(int n,location plct,direction_cmd dircmd);

//计算出接收指令后的飞机坐标 
location plane_locate2(location plct,direction_cmd dircmd);

void init(void);
 
void* thread_bgmusic(void* arg);
void play_bgmusic();
void bgmusic();
 
#endif

3、库函数control_plane.cpp

#include <iostream>
#include "conio.h"
#include <string>
#include "control_plane.h"
#include<windows.h>
using namespace std;

//初始化函数 
void init(void)
{
	plocation.x=2*r_b/3;				//初始化飞机图标的x坐标为屏幕横轴最大值的一半 
	plocation.y=b_b;					//初始化飞机图标的y坐标为屏幕纵轴最大值
	plocation2.x=r_b/3;					//初始化飞机图标的x坐标为屏幕横轴最大值的一半 
	plocation2.y=b_b;					//初始化飞机图标的y坐标为屏幕纵轴最大值
}

//********************************************************************************
 //以下三个函数为播放背景音乐功能 
//********************************************************************************
 
 //播放一遍背景音乐 
 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(location plct)		//预先定义字符定位显示函数,x是列坐标,y是行坐标,原点(x=0,y=0)位于屏幕左上角 
{
	int x,y;
	int i,j;	
	int rows=sizeof(icon_plane)/sizeof(icon_plane[0]);
	x=plct.x;
	y=plct.y;
	
	for(i=0;i<rows;i++)				//图标每行前输出x个空格 
	{
		gotoxy(x,y+i);
		cout<<icon_plane[i]<<endl;
	}
}


//获取键盘指令函数 
direction_cmd key(void)
{
	int key_value1,key_value2;			//声明两个变量,存放键值 
	key_value1=getch();					//先获取第一个码值 
	
	
	if(key_value1==224)					//如果第一个码值为224,则进行第二个码值的判断 
		{
			key_value2=getch();			//先获取第二个码值
			
			switch(key_value2)
			{
				case 72:				//向上方向键 
					return up_cmd;
				case 80:				//向下方向键
					return down_cmd;
				case 75:				//向左方向键
					return left_cmd;
				case 77:				//向右方向键
					return right_cmd;
			}
			
		}
		else
		{
			switch(key_value1)
			{
				case 119:				//向上方向键 
					return up_cmd2;
				case 115:				//向下方向键
					return down_cmd2;
				case 97:				//向左方向键
					return left_cmd2;
				case 100:				//向右方向键
					return right_cmd2;
			}
		}		
}


//计算获得移动指令后飞机的坐标 
location plane_locate(int n,location plct,direction_cmd dircmd)
{
 	int x,y;
 	x=plct.x;
 	y=plct.y;
 	
 	if(n==1)
 	{
		switch(dircmd)
		{
			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;
				
			}
	}
	else if(n==2)
	{
		switch(dircmd)
		{
			case up_cmd2:
				y--;				//字符上移一行,行值y减1
				if(y<t_b)			//限定y值最小值为0
				{
					y=t_b;
				}
				break;
			case down_cmd2:
				y++;				//字符下移一行,行值y加1
				if(y>b_b)			//限定y高度 
				{
					y=b_b;
				}
				break;
			case left_cmd2:
				x--;				//字符左移一列,列值x减1
				if(x<l_b)
				{
					x=l_b;			//限定x最小值为0; 
				}
				break;
			case right_cmd2:
				x++;				//字符右移一列,列值x加1
				if(x>r_b)
				{
					x=r_b;			//限定x宽度
				}
				break;
				
		}
	}
		plct.x=x;
		plct.y=y;
		return plct;
 }
 
 //计算获得移动指令后飞机的坐标 
location plane_locate2(location plct,direction_cmd dircmd)
{
 	int x,y;
 	x=plct.x;
 	y=plct.y;
	 switch(dircmd)
		{
			case up_cmd2:
				y--;				//字符上移一行,行值y减1
				if(y<t_b)			//限定y值最小值为0
				{
					y=t_b;
				}
				break;
			case down_cmd2:
				y++;				//字符下移一行,行值y加1
				if(y>b_b)			//限定y高度 
				{
					y=b_b;
				}
				break;
			case left_cmd2:
				x--;				//字符左移一列,列值x减1
				if(x<l_b)
				{
					x=l_b;			//限定x最小值为0; 
				}
				break;
			case right_cmd2:
				x++;				//字符右移一列,列值x加1
				if(x>r_b)
				{
					x=r_b;			//限定x宽度
				}
				break;
				
		}
		plct.x=x;
		plct.y=y;
		return plct;
 }
 
 
 

三、运行效果

(未完待续) 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我们来看看如何用C++语言制作一个简单飞机游戏。以下是一个简单游戏框架: ```c++ #include <iostream> #include <conio.h> #include <windows.h> using namespace std; const int WIDTH = 80; const int HEIGHT = 25; int x, y; // 飞机的坐标 void gotoxy(int x, int y) { COORD pos = { x, y }; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos); } void draw_plane() { gotoxy(x, y); cout << " /\\"; gotoxy(x, y + 1); cout << " / \\"; gotoxy(x, y + 2); cout << "/____\\"; } void clear_plane() { gotoxy(x, y); cout << " "; gotoxy(x, y + 1); cout << " "; gotoxy(x, y + 2); cout << " "; } void move_plane(int dx, int dy) { clear_plane(); x += dx; y += dy; draw_plane(); } int main() { x = WIDTH / 2 - 1; y = HEIGHT - 3; draw_plane(); while (true) { if (_kbhit()) { char ch = _getch(); if (ch == 'a' && x > 1) { move_plane(-1, 0); } else if (ch == 'd' && x < WIDTH - 4) { move_plane(1, 0); } else if (ch == 'w' && y > 1) { move_plane(0, -1); } else if (ch == 's' && y < HEIGHT - 4) { move_plane(0, 1); } } } return 0; } ``` 这个程序使用了Windows API来控制控制台窗口的输出,所以只能在Windows系统上运行。程序中定义了飞机的坐标,然后使用`gotoxy()`函数控制台上输出ASCII字符来绘制飞机使用`_kbhit()`和`_getch()`函数来获取键盘输入,并且使用`move_plane()`函数移动飞机。 这只是一个简单的示例,你可以添加更多的功能和特效来增加游戏的乐趣。例如,你可以添加敌机和子弹,添加音乐和音效,或者设计关卡系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值