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

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

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

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++图形化编程】飞机大战2——运动与碰撞检测

上一篇中,简单实现了飞机大战的基本框架,这篇文章继续完善,使其可以进行游戏。#include <graphics.h> #include <conio.h>...

C++小游戏——flappy bird简单实现

C++小游戏——flappy bird简单实现

上一篇小游戏中,我们简单实现了打砖块小游戏。这一篇中,我们根据前面的框架,简单实现flappy bird小游戏。1.游戏框架   2.实现下落的小鸟#include &l...

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

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

C++小游戏制作基础—键盘事件

0.前言我们制作小游戏的时候,需要用到键盘,一般是控制上下左右,这个时候就需要用到键盘事件了。1.键盘事件需要用到<conio.h>头文件,和_kbhit()函数程序参考:#include...

C++小游戏—弹跳小球

C++小游戏—弹跳小球

首先,要注意屏幕直角坐标系的问题,不然的话,后面移动过程中一定会出错。然后,利用printf函数在屏幕坐标(x,y)处显示一个静止的小球字符‘O’,注意屏幕坐标系的原点在左上方,参考代码#includ...

C++实现走迷宫小游戏

1.简单版本简单版本是利用字符数组实现的,利用字符数组设定入口和出口,用户每次按键就刷新一下当前字符数组。参考代码:#include<stdio.h>#include<stdlib....