目录
家人们火速玩起来,录屏情况下得分破百私信我必给你超级大惊喜!
由于上一个弹球没有游戏体验,接下来做一个可以正常游玩的游戏《狂野打飞机》!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;
}