【C语言】 《狂野打飞机》初步构想以及进阶 以及防止闪屏

目录

一、初设想

首先

 但是!

 二、做优化

1)准备

2)具体步骤

a)代码重构

b)新式子弹

c)添加敌机

三、消除屏闪,最终完善

完全体《狂野打飞机》如下:

        家人们火速玩起来,录屏情况下得分破百私信我必给你超级大惊喜!


由于上一个弹球没有游戏体验,接下来做一个可以正常游玩的游戏《狂野打飞机》!doge

一、初设想

首先

        根据上一个游戏思维,我们首先要做的就是在屏幕上呈现出飞机,然后飞机可以移动,这个移动呢必须得是我们主动控制它来移动,不能是像小球一样自己移动。所以我们第一时间想到是通过scanf输入指令,然后做出判断并运行,每次移动后都进行清屏然后重新输出

        但是呢我们如果用的是scanf的话,每次输入都得按一下回车来执行,这十分影响我们的游戏体验,不可取!所以我们要用getch()来控制飞机的飞行。

        要用getch()的话我们首先要加一个库函数#include<conio.h>用kbhit()来判断是否输入规定值。

        正所谓打飞机,肯定得有靶子,并且飞机得能发射。 所以程序如下:d

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main()
{
	int i, j;
	int x = 10;
	int y = 5;
	char input;
	int isFire = 0;

	int nx = 5;
	int isKilled = 0;
	while (1)
	{
		system("cls");
		if (!isKilled)
		{
			for (j = 0; j < nx; j++)
				printf(" ");
			printf(" + \n");
		}
		if (isFire == 0)
		{
			for (i = 0; i < y; i++)
				printf("\n");
		}
		else
		{
			for (i = 0; i < y; i++)
			{
				for (j = 0; j < x; j++)
					printf(" ");
				printf("  |\n");
			}
			if (x + 2 == nx)
				isKilled = 1;
			isFire = 0;
		}
		for (i = 0; i < y; i++)
			printf("\n");
		for (j = 0; j < x; j++)
			printf(" ");
		printf("  *\n");
		for (j = 0; j < x; j++)
			printf(" ");
		printf("****** \n");
		for (j = 0; j < x; j++)
			printf(" ");
		printf(" *  * \n");

		if (_kbhit()) 
		{
			input = _getch();
			if (input == 'a')
				x--;
			if (input == 'd')
				x++;
			if (input == 'w')
				y--;
			if (input == 's')
				y++;
			if (input == ' ')
				isFire = 1;
		}
	}
	return 0;
}

 但是!

这个游戏玩起来十分卡顿,并且有闪屏游戏体验依旧很差,就此,我们对它进行进一步的更新。


 二、做优化

1)准备

        对游戏的优化我们主要做的是添加几个函数,将会用到startup()、show()、updateWithoutInput()、updateWithInput()几个函数中实现,主函数与之前大体无差。

2)具体步骤

a)代码重构

        我们首先要做的就是把前面所说的函数加入到之前程序中去,并做出一定的修改。

        主要是通过startup()函数来进行数据的初始化,用show()函数来显示画面,用updateWithoutInput()和updateWithInput()函数来进行与用户输入无关和有关的更新。修改后代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

//全局变量
int pos_x, pos_y;
int high, width;
//初始化数据
void startup()
{
	high = 20;
	width = 30;
	pos_x = width / 2;
	pos_y = high / 2;
}
//显示画面
void show()
{
	system("cls");
	int i, j;
	for (i = 0; i < high; i++)
	{
		for (j = 0; j < width; j++)
		{
			if ((i == pos_y) && (j == pos_x))
				printf("@");
			else
				printf(" ");
		}
		printf("\n");
	}

}
//与用户输入无关的更新
void updateWithoutInput()
{

}
//与用户输入有关的更新
void updateWithInput()
{
	char input;
	if (_kbhit())
	{
		input = _getch();
		if (input == 'a')
			pos_x--;
		if (input == 'd')
			pos_x++;
		if (input == 'w')
			pos_y--;
		if (input == 's')
			pos_y++;
	}
}

int main()
{
	startup();
	while (1)
	{
		show();
		updateWithoutInput();
		updateWithInput();
	}
	return 0;
}

        这样我们就完成了第一步的输出一个可以移动的飞机。 


b)新式子弹

        飞机必不可少的就是子弹,我们可以像之前那样定义子弹的位置,然后让输出后的子弹自己移动。代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

//全局变量
int pos_x, pos_y;
int high, width;
int bul_x, bul_y;
//初始化数据
void startup()
{
	high = 20;
	width = 30;
	pos_x = width / 2;
	pos_y = high / 2;
	bul_x = pos_x;
	bul_y = 0;
}
//显示画面
void show()
{
	system("cls");
	int i, j;
	for (i = 0; i < high; i++)
	{
		for (j = 0; j < width; j++)
		{
			if ((i == pos_y) && (j == pos_x))
				printf("@");
			else if ((i == bul_y) && (j == bul_x))
				printf("|");
			else
				printf(" ");
		}
		printf("\n");
	}

}
//与用户输入无关的更新
void updateWithoutInput()
{
	//子弹自行移动
	if (bul_y > -1)
		bul_y--;
}
//与用户输入有关的更新
void updateWithInput()
{
	char input;
	if (_kbhit())
	{
		input = _getch();
		if (input == 'a')
			pos_x--;
		if (input == 'd')
			pos_x++;
		if (input == 'w')
			pos_y--;
		if (input == 's')
			pos_y++;
		if (input == ' ')
		{
			bul_y = pos_y - 1;
			bul_x = pos_x;
		}
	}
}

int main()
{
	startup();
	while (1)
	{
		show();
		updateWithoutInput();
		updateWithInput();
	}
	return 0;
}

        这样我们的飞机就可以发射子弹了。


c)添加敌机

        作为打飞机游戏,没有敌机怎么打?所以我们现在的任务就是添加敌机,然后让敌机移动起来,并且在我们的子弹击中敌机后让敌机消失

        第一步还是定义敌机的位置,然后让敌机自主地向下移动,即在与用户输入无关的更新的函数updateWithoutInput()中利用静态变量speed静态变量不会被初始化,也不会被别的文件调用,再次调用仍是上次的值,每执行10次updateWithoutInput()函数,敌机移动一次(太快没法打

        然后就是在我们的子弹击中敌机后,敌机和子弹都会消失,然后重新随机生成敌机,并定义一个计分板来计数。其中rand()函数我们在程序中使用的rand()%width意思就是随机在1~width之间选取一个整数产生一个0~9的随机整数。

        程序如下:

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

//全局变量
int pos_x, pos_y;
int high, width;
int bul_x, bul_y;
int enm_x, enm_y;
int score;
//初始化数据
void startup()
{
	high = 20;
	width = 30;
	pos_x = width / 2;
	pos_y = high / 2;
	bul_x = pos_x;
	bul_y = 0;
	enm_y = 0;
	enm_x = pos_x;
	score = 0;
}
//显示画面
void show()
{
	system("cls");
	int i, j;
	for (i = 0; i < high; i++)
	{
		for (j = 0; j < width; j++)
		{
			if ((i == pos_y) && (j == pos_x))
				printf("@");
			else if ((i == enm_y) && (j == enm_x))
				printf("$");
			else if ((i == bul_y) && (j == bul_x))
				printf("|");
			else
				printf(" ");
		}
		printf("\n");
	}
	printf("得分:%d\n", score);
}
//与用户输入无关的更新
void updateWithoutInput()
{
	//子弹自行移动
	if (bul_y > -1)
		bul_y--;
	//击中
	if ((bul_x == enm_x) && (bul_y == enm_y))
	{
		score++;
		enm_y == 0;
		enm_x = rand() % width;
	}
	//敌机飞出地图
	if (enm_y > high)
	{
		enm_y = -1;
		enm_y = rand() % width;
	}
	static int speed = 0;
	if (speed < 10)
		speed++;
	if (speed == 10)
	{
		enm_y++;
		speed = 0;
	}
}
//与用户输入有关的更新
void updateWithInput()
{
	char input;
	if (_kbhit())
	{
		input = _getch();
		if (input == 'a')
			pos_x--;
		if (input == 'd')
			pos_x++;
		if (input == 'w')
			pos_y--;
		if (input == 's')
			pos_y++;
		if (input == ' ')
		{
			bul_y = pos_y - 1;
			bul_x = pos_x;
		}
	}
}

int main()
{
	startup();
	while (1)
	{
		show();
		updateWithoutInput();
		updateWithInput();
	}
	return 0;
}

        这就是经过以上完善的程序,它具有了可玩性,但是闪屏极为严重游戏体验依旧很差!接下来我们就要消除它的屏闪。


三、消除屏闪,最终完善

         我们消除屏闪首先要知道屏闪是由什么造成的,屏闪的原因就是每次运行到show()函数都进行一次清屏,并且光标不能回到原点,跟随输出到处跑。

        故而需要用到库函数#include<windows.h>中的void gotoxy(int x,int y)函数,在show()函数里首先调用gotoxy(0,0),光标移动到原点位置,在进行重画,这样就不会使光标到处跑造成屏闪。

         同时使用隐藏光标函数HideCursor()解决光标到处跑

完全体《狂野打飞机》如下:

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<Windows.h>

//消除屏闪
void gotoxy(int x, int y)
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos = { x,y };
	SetConsoleCursorPosition(handle, pos);
}

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

//全局变量
int pos_x, pos_y;
int high, width;
int bul_x, bul_y;
int enm_x, enm_y;
int score;
//初始化数据
void startup()
{
	high = 20;
	width = 50;

	pos_x = width / 2;
	pos_y = high / 2;

	bul_x = pos_x;
	bul_y = 0;

	enm_y = 0;
	enm_x = pos_x;

	score = 0;
}
//显示画面
void show()
{
	gotoxy(0, 0);
	int i, j;
	for (i = 0; i < high; i++)
	{
		for (j = 0; j < width; j++)
		{
			if ((i == pos_y) && (j == pos_x))
				printf("@");

			else if ((i == enm_y) && (j == enm_x))
				printf("$");

			else if ((i == bul_y) && (j == bul_x))
				printf("|");

			else
				printf(" ");
		}
		printf("\n");
	}
	printf("《狂野打飞机》");
	printf("得分:%d\n", score);
}
//与用户输入无关的更新
void updateWithoutInput()
{
	//子弹自行移动
	if (bul_y > -1)
		bul_y--;
	//击中
	if ((bul_x == enm_x) && (bul_y == enm_y))
	{
		score++;
		enm_y = 0;
		enm_x = rand() % width;
	}
	//敌机飞出地图
	if (enm_y > high)
	{
		score--;
		enm_y = -1;
		enm_y = rand() % width;
	}
	static int speed = 0;
	if (speed < 50)
		speed++;
	if (speed == 50)
	{
		enm_y++;
		speed = 0;
	}
}
//与用户输入有关的更新
void updateWithInput()
{
	char input;
	if (_kbhit())
	{
		input = _getch();
		if (input == 'a')
			pos_x--;
		if (input == 'd')
			pos_x++;
		if (input == 'w')
			pos_y--;
		if (input == 's')
			pos_y++;

		if (input == ' ')
		{
			bul_y = pos_y - 1;
			bul_x = pos_x;
		}
	}
}

int main()
{
	startup();
	while (1)
	{
		show();
		updateWithoutInput();
		updateWithInput();
		HideCursor();
	}
	return 0;
}

 

 

        家人们火速玩起来,录屏情况下得分破百私信我必给你超级大惊喜!

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值