当前位置:首页 > 趣味小程序 > 正文内容

C++小游戏——简单飞机大战(2)——代码与显示优化

亿万年的星光4年前 (2021-03-27)趣味小程序2851

0.前言

在上一篇中,我们在C++控制台中简单实现了飞机大战了逻辑,但是代码比较长,显示也不是很好看,这篇文章中,我们对上一篇的代码进行优化下,把很多过程封装成函数形式。让程序看上去更加精简。

一个合理化的游戏框架

1.游戏框架

框架参考:

int main() {
	startup(); //数据初始化
	while(1){  //游戏循环执行 
		show();  //显示画面
		updateWithoutInput(); //与用户输入有关的更新
		updateWithInput(); //与用户输入有关的更新 
	} 
	return 0; 
}


与输入无关的,比如敌机往下落,发射出去的子弹都不需要用户控制了。

#include<cstdio>
#include<iostream>
#include<conio.h>
using namespace std;
//全局变量定义 


//数据初始化
void start(){

}
//显示画面
void show(){
	
} 
//输入无关
void noInput(){
	
} 

//输入有关 
void Input(){
	
}



//主函数 
int main(){
	
	return 0; 
}	

2.飞机移动


#include<cstdio>
#include<iostream>
#include<conio.h>
#include<windows.h>
#include<ctime> 
using namespace std;
//全局变量定义
int px,py;  //飞机的坐标
int high, width; //画面的尺寸

//屏幕移动函数 
void gotoxy(int x, int y) {
    COORD pos = {x,y};
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
    SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
//数据初始化
void start() {
	high=64;
	width=32;
	px=high/3;
	py=width/2;

}
//显示画面
void show() {
	printf("★\n");	
	gotoxy(px+1,py+1);
	printf("★\n");	
	gotoxy(px-1,py+1);
	printf("★\n");	
}
// 移动到控制台x,y坐标


//输入无关
void noInput() {

}

//输入有关
void Keydown() {
	char input;
	if (_kbhit()) { //如果有按键按下,则_kbhit()函数返回真
		input = _getch();//使用_getch()函数获取按下的键值
		switch(input) {
			case 72: //上键
			case 'w':
			case 'W':
				//px--; //for模式 
				py--;  //gotoxy模式 
				break;
			case 80: // 下键
			case 's':
			case 'S':
				//px++;
				py++;
				break;
			case 75: //左键
			case 'a':
			case 'A':
				//py--;
				px--;
				break;
			case  77: //右键
			case  'd':
			case 'D':
				//py++;
				px++;
				break;
		}
	}
}



//主函数
int main() {
	start(); //数据初始化

	while(1){
		Keydown();
		system("cls");
		gotoxy(px,py);
		show(); 
	}
	


	return 0;
}


3.构造子弹与子弹移动


这个地方的主要思路是子弹的坐标取飞机的坐标。当按下空格键时,子弹就会从飞机头部坐标发射出去。

#include<cstdio>
#include<iostream>
#include<conio.h>
#include<windows.h>
#include<ctime> 
using namespace std;
//全局变量定义
int px,py;  //飞机的坐标
int high, width; //画面的尺寸
int bullet_x,bullet_y; //子弹的位置 

//屏幕移动函数 
void gotoxy(int x, int y) {
    COORD pos = {x,y};
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
    SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
//数据初始化
void start() {
	high=64;
	width=32;
	px=high/3;  //飞机位置初始化 
	py=width/2; // 飞机位置 

	bullet_x=px; //子弹位置 
	bullet_y=py; // 子弹位置 
}
//显示画面
void show() {
	/*描绘飞机*/ 
	printf("★\n");	
	gotoxy(px+1,py+1);
	printf("★\n");	
	gotoxy(px-1,py+1);
	printf("★\n");
	/*描绘子弹*/
	gotoxy(bullet_x,bullet_y-1);
	printf("|\n");	
}
// 移动到控制台x,y坐标


//输入无关
void noInput() {

}

//输入有关
void Keydown() {
	char input;
	if (_kbhit()) { //如果有按键按下,则_kbhit()函数返回真
		input = _getch();//使用_getch()函数获取按下的键值
		switch(input) {
			case 72: //上键
			case 'w':
			case 'W':
				//px--; //for模式 
				py--;  //gotoxy模式 
				break;
			case 80: // 下键
			case 's':
			case 'S':
				//px++;
				py++;
				break;
			case 75: //左键
			case 'a':
			case 'A':
				//py--;
				px--;
				break;
			case  77: //右键
			case  'd':
			case 'D':
				//py++;
				px++;
				break;
			case 32: //空格 
				bullet_y=py-1;  //gotoxy模式下坐标变化 
				bullet_x=px; 
				break; 
			
		}
	}
}


//主函数
int main() {
	start(); //数据初始化

	while(1){
		Keydown();
		system("cls");
		gotoxy(px,py);
		show(); 
	}
	


	return 0;
}


上面这样做还是有个问题,就是子弹一旦发射出去,那么就不会受到飞机的控制,开始自己按照轨迹飞,所以应该把子弹的移动放到输入无关的部分。

效果图:


这样基本实现了子弹和飞机脱离的情况,但是还有另外一个小BUG,就是游戏一开始子弹就自动发射了,我们可以让子弹的初始值为-1,这样就看不到了。

4.增加敌机

我们定义敌机的位置并初始化,同样的问题就是敌机的位置会往下落,那么敌机位置的变化也要放到输入无关的部分。

参考代码:

#include<cstdio>
#include<iostream>
#include<conio.h>
#include<windows.h>
#include<ctime> 
using namespace std;
//全局变量定义
int px,py;  //飞机的坐标
int high, width; //画面的尺寸
int bullet_x,bullet_y; //子弹的位置 
int enemy_x,enemy_y; //敌机位置 

//屏幕移动函数 
void gotoxy(int x, int y) {
    COORD pos = {x,y};
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
    SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
//数据初始化
void start() {
	high=20;
	width=30;
	px=high/3;  //飞机位置初始化 
	py=width/2; // 飞机位置 

	bullet_x=px; //子弹位置 
	//bullet_y=py; // 子弹位置 
	bullet_y=-1; // 子弹位置 
	
	enemy_x=px;  //敌机位置 
	enemy_y=0;  //敌机位置 
}
//显示画面
void show() {
	/*描绘飞机*/ 
	printf("★\n");	
	gotoxy(px+1,py+1);
	printf("★\n");	
	gotoxy(px-1,py+1);
	printf("★\n");
	/*描绘子弹*/
	gotoxy(bullet_x,bullet_y-1);
	printf("!\n");	
	
	/*描绘敌机*/
	gotoxy(enemy_x,enemy_y);
	printf("#\n"); 
}
// 移动到控制台x,y坐标


//输入无关
void noInput() {
	/*子弹往上移动*/
	if(bullet_y>-1)
		bullet_y--;// 子弹往上移动 
	
	/*飞机往下移动*/ 
	if(enemy_y<high) 
		enemy_y++;
	else	
		enemy_y=0; 
}

//输入有关
void Keydown() {
	char input;
	if (_kbhit()) { //如果有按键按下,则_kbhit()函数返回真
		input = _getch();//使用_getch()函数获取按下的键值
		switch(input) {
			case 72: //上键
			case 'w':
			case 'W':
				//px--; //for模式 
				py--;  //gotoxy模式 
				break;
			case 80: // 下键
			case 's':
			case 'S':
				//px++;
				py++;
				break;
			case 75: //左键
			case 'a':
			case 'A':
				//py--;
				px--;
				break;
			case  77: //右键
			case  'd':
			case 'D':
				//py++;
				px++;
				break;
			case 32: //空格 
				bullet_y=py-1;  //gotoxy模式下坐标变化 
				bullet_x=px; 
				break; 
			
		}
	}
}


//主函数
int main() {
	start(); //数据初始化

	while(1){
		Keydown();
		noInput(); 
		system("cls");
		gotoxy(px,py);
		show(); 
	}
	


	return 0;
}

问题又来了,敌机的位置总是固定的从一个位置下落,所以我们要加入随机数,让敌机在随机的位置生成,随机数一节参考“C++产生随机数”。

敌机如果飞行的太快,我们可以加上sleep函数。但是如果在主循环中加入sleep函数,会导致我们的飞机和敌人的飞机同时变慢(相当于没变)。那么我们有个思路是让敌机处于循环中,我们执行speed次,敌机才移动一次,这样就能达到我们移动速度不变,但是敌机移动变慢了的.

参考代码:

#include<cstdio>
#include<iostream>
#include<conio.h>
#include<windows.h>
#include<ctime>
using namespace std;
//全局变量定义
int px,py;  //飞机的坐标
int high, width; //画面的尺寸
int bullet_x,bullet_y; //子弹的位置
int enemy_x,enemy_y; //敌机位置
int speed; //延迟时间

//屏幕移动函数
void gotoxy(int x, int y) {
	COORD pos = {x,y};
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
	SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
//数据初始化
void start() {
	high=20;
	width=30;
	px=high/3;  //飞机位置初始化
	py=width/2; // 飞机位置

	bullet_x=px; //子弹位置
	//bullet_y=py; // 子弹位置
	bullet_y=-1; // 子弹位置

	enemy_x=px;  //敌机位置
	enemy_y=0;  //敌机位置

	speed=2;  //敌机移动速度 
}
//显示画面
void show() {
	/*描绘飞机*/
	printf("★\n");
	gotoxy(px+1,py+1);
	printf("★\n");
	gotoxy(px-1,py+1);
	printf("★\n");
	/*描绘子弹*/
	gotoxy(bullet_x,bullet_y-1);
	printf("!\n");

	/*描绘敌机*/
	gotoxy(enemy_x,enemy_y);
	printf("#\n");
}
// 移动到控制台x,y坐标


//输入无关
void noInput() {
	/*子弹往上移动*/
	if(bullet_y>-1)
		bullet_y--;


	/*飞机往下移动*/
	static int speed_tmp=0;
	if(speed_tmp<speed)
		speed_tmp++;
	if(speed_tmp==speed) {
		srand((int)time(NULL));
		if(enemy_y<high){
			enemy_y++;
			speed_tmp=0;  //速度重置 
		}
		else {
			enemy_y=0;
			enemy_x=rand()%width;
		}
	}




}

//输入有关
void Keydown() {
	char input;
	if (_kbhit()) { //如果有按键按下,则_kbhit()函数返回真
		input = _getch();//使用_getch()函数获取按下的键值
		switch(input) {
			case 72: //上键
			case 'w':
			case 'W':
				//px--; //for模式
				py--;  //gotoxy模式
				break;
			case 80: // 下键
			case 's':
			case 'S':
				//px++;
				py++;
				break;
			case 75: //左键
			case 'a':
			case 'A':
				//py--;
				px--;
				break;
			case  77: //右键
			case  'd':
			case 'D':
				//py++;
				px++;
				break;
			case 32: //空格
				bullet_y=py-1;  //gotoxy模式下坐标变化
				bullet_x=px;
				break;

		}
	}
}

//主函数
int main() {
	start(); //数据初始化
	while(1) {
		Keydown();
		noInput();
		system("cls");
		gotoxy(px,py);
		show();
	}
	return 0;
}

效果图

5.击中敌机


击中敌机的思路是子弹的坐标和飞机的坐标相等就是击中敌机了,但是击中之后要记得把子弹消失,然后敌机要继续随机生成。同时加上得分效果。



效果:


6.最终代码

#include<cstdio>
#include<iostream>
#include<conio.h>
#include<windows.h>
#include<ctime>
using namespace std;
//全局变量定义
int px,py;  //飞机的坐标
int high, width; //画面的尺寸
int bullet_x,bullet_y; //子弹的位置
int enemy_x,enemy_y; //敌机位置
int speed; //敌机速度
int score; //用户得分 


//屏幕移动函数
void gotoxy(int x, int y) {
	COORD pos = {x,y};
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
	SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
//数据初始化
void start() {
	high=20;
	width=30;
	px=high/3;  //飞机位置初始化
	py=width/2; // 飞机位置

	bullet_x=px; //子弹位置
	//bullet_y=py; // 子弹位置
	bullet_y=-1; // 子弹位置

	enemy_x=px;  //敌机位置
	enemy_y=0;  //敌机位置

	speed=4;  //敌机移动速度 
}
//显示画面
void show() {
	/*描绘飞机*/
	printf("★\n");
	gotoxy(px+1,py+1);
	printf("★\n");
	gotoxy(px-1,py+1);
	printf("★\n");
	/*描绘子弹*/
	gotoxy(bullet_x,bullet_y-1);
	printf("!\n");

	/*描绘敌机*/
	gotoxy(enemy_x,enemy_y);
	printf("#\n");
	
	/*展示得分*/
	gotoxy(high,width);
	printf("得分:%d",score); 
}
// 移动到控制台x,y坐标


//输入无关
void noInput() {
	/*子弹往上移动*/
	if(bullet_y>-1)
		bullet_y--;
	/*飞机往下移动*/
	static int speed_tmp=0;
	if(speed_tmp<speed)
		speed_tmp++;
	if(speed_tmp==speed) {
		srand((int)time(NULL));
		if(enemy_y<high){
			enemy_y++;
			speed_tmp=0;  //速度重置 
		}
		else {
			enemy_y=0;
			enemy_x=rand()%width;
		}
	}

	/*判断击中敌机*/
	if(enemy_x==bullet_x && enemy_y==bullet_y)
	{
		score++;
		bullet_y=bullet_x=-1; //子弹消失
		enemy_y=0;
		enemy_x=rand()%width; //敌机继续生成 
		 
	 } 
}

//输入有关
void Keydown() {
	char input;
	if (_kbhit()) { //如果有按键按下,则_kbhit()函数返回真
		input = _getch();//使用_getch()函数获取按下的键值
		switch(input) {
			case 72: //上键
			case 'w':
			case 'W':
				//px--; //for模式
				py--;  //gotoxy模式
				break;
			case 80: // 下键
			case 's':
			case 'S':
				//px++;
				py++;
				break;
			case 75: //左键
			case 'a':
			case 'A':
				//py--;
				px--;
				break;
			case  77: //右键
			case  'd':
			case 'D':
				//py++;
				px++;
				break;
			case 32: //空格
				bullet_y=py-1;  //gotoxy模式下坐标变化
				bullet_x=px;
				break;

		}
	}
}

void HideCursor(){
	CONSOLE_CURSOR_INFO cursor_info={1,0}; //第二个值表示隐藏光标 
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);	
}

//主函数
int main() {
	start(); //数据初始化
	HideCursor();  //隐藏光标
	while(1) {
		Keydown();
		noInput();
		system("cls");
		//gotoxy(0,0)
		gotoxy(px,py);
		show();
	}
	return 0;
}


7.不足之处

  • 显示BUG,左侧有个子弹

  • 敌机不能击中玩家

  • 显示频率过高

扫描二维码推送至手机访问。

版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

分享给朋友:

相关文章

C++小游戏—反弹球实现打砖块

C++小游戏—反弹球实现打砖块

0.前言在上一篇中,我们用C++代码实现了弹球小游戏,上一篇链接可以点击这里查看。这一篇中,我们继续优化代码,使用上一篇的弹球小游戏进行扩展,实现打砖块效果。1.思路底部挡板跟随键盘移动在顶部生成目标...

【C++图形化编程】C++图形库的引入

【C++图形化编程】C++图形库的引入

0.前言前面的文章用C++的控制台完成了小游戏,但是我们平常玩的游戏都是有图形化界面,我们从这篇文章开始就引入一个C++图形库—EasyX。C++的图形库有很多,EasyX是最适合上手的图形库。1.简...

【C++图形化编程】EasyX的基本概念

一、颜色        EasyX 使用 24bit 真彩色,不支持调色板模式。     ...

【C++图形化编程】flappy bird(3)—碰撞检测(大功告成)

0.前言    前面几篇文章中,我们简单介绍了基础框架和游戏逻辑,这一篇文章我们接着上一篇,继续完善游戏,主要是移动与碰撞逻辑的检测...

【二分与分治】中间值、边界值、循环条件、模块写法(2)

二分法的模板写法:(1)标准的二分查找(寻找的值正好等于x的任意位置)int search(int A[], int n, int targ...

【C++图形化编程】EasyX函数~图形绘制相关函数(1)

简介:EasyX有很多图形绘制函数,这篇文章简单介绍下:函数或函数类型说明arc画椭圆形circle画无填充的圆clearcircle清空圆形区域clearllipse清空椭圆形区域clearpie清...