本节将利用函数封装重构飞机游戏,并实现新式子弹、敌机移动和更好的清屏功能。
2.1.1 代码重构
没有函数,我们所有的代码都要写在主函数中,这样看着杂乱也不利于更行和添加功能。
我们将给出一个模板
int main() {
startup();//初始化
while (true) {//游戏循环开始
show();//显示画面
updateWithoutInput();//与用户输入无关的更新
updateWithInput();//与用户输入有关的更新
}
return 0;
}
这样的模板并不详尽,只有一些基础必备的东西,我们可以按照这种方法自行添加想要实现的新的功能。
接下来我们把之前的代码按照上面的结构进行划分。(删减了一些功能,之后会升级补上)
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#pragma warning(disable:4996)
int position_x, position_y;//飞机位置
int high, width;//游戏画面尺寸
//数据初始化
void startup() {
high = 20;
width = 30;
position_x = high / 2;
position_y = width / 2;
}
//显示画面
void show() {
system("cls");
int i, j;
for (i = 0; i < high; i++) {
for (j = 0; j < width; j++) {
if ((i == position_x) && (j == position_y))
printf("*");
else
printf(" ");
}
printf("\n");
}
Sleep(100);
}
//与用户输入无关的输入
void updateWithoutInput() {
}
//与用户输入有关的更新
void updateWithInput() {
char input;
if (kbhit()) {
input = getch();
switch (input) {
case 'a':position_y--; break;
case 'd':position_y++; break;
case 'w':position_x--; break;
case 's':position_x++; break;
default:;
}
}
}
//主函数
int main() {
startup();
while (true) {
show();
updateWithoutInput();
updateWithInput();
}
return 0;
}
2.1.2 新式子弹
上一节我们实现了这个激光武器,这一节我们将实现一个能发射常规子弹的武器。初始化子弹为飞机的正上方(
b
u
l
l
e
t
_
x
=
p
o
s
i
t
i
o
n
_
x
−
1
;
b
u
l
l
e
t
_
y
=
p
o
s
i
t
i
o
n
_
y
bullet\_x=position\_x-1;bullet\_y=position\_y
bullet_x=position_x−1;bullet_y=position_y),子弹发射后自动向上移动
这种写法只能同时存在一发子弹。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#pragma warning(disable:4996)
int position_x, position_y;
int bullet_x, bullet_y;//子弹位置
int high, width;
//数据初始化
void startup() {
high = 20;
width = 30;
position_x = high / 2;
position_y = width / 2;
bullet_x = 0;
bullet_y = position_y;
}
//显示画面
void show() {
system("cls");
int i, j;
for (i = 0; i < high; i++) {
for (j = 0; j < width; j++) {
if ((i == position_x) && (j == position_y))
printf("*");
else if ((i == bullet_x) && (j == bullet_y))
printf("|");
else
printf(" ");
}
printf("\n");
}
Sleep(100);
}
//与用户输入无关的输入
void updateWithoutInput() {
if (bullet_x > -1)
bullet_x--;
}
//与用户输入有关的更新
void updateWithInput() {
char input;
if (kbhit()) {
input = getch();
switch (input) {
case 'a':position_y--; break;
case 'd':position_y++; break;
case 'w':position_x--; break;
case 's':position_x++; break;
case ' ':
bullet_x = position_x - 1;
bullet_y = position_y; break;
default:;
}
}
}
//主函数
int main() {
startup();
while (true) {
show();
updateWithoutInput();
updateWithInput();
}
return 0;
}
2.1.3 静止的敌机
在上一节我们实现了一个静止的靶子,这次我们将实现一个真正的敌人(虽然不会移动也不会攻击),用符号@代表,其坐标为 ( e n e m y _ x , e n e m y _ y ) (enemy\_x,enemy\_y) (enemy_x,enemy_y)。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#pragma warning(disable:4996)
int position_x, position_y;//飞机位置
int bullet_x, bullet_y;//子弹位置
int enemy_x, enemy_y;//敌机位置
int high, width;//游戏画面尺寸
//数据初始化
void startup() {
high = 20;
width = 30;
position_x = high / 2;
position_y = width / 2;
bullet_x = -1;
bullet_y = position_y;
enemy_x = 0;
enemy_y = position_y;
}
//显示画面
void show() {
system("cls");
int i, j;
for (i = 0; i < high; i++) {
for (j = 0; j < width; j++) {
if ((i == position_x) && (j == position_y))
printf("*");//输出飞机
else if ((i == enemy_x) && (j == enemy_y))
printf("@");//输出敌机
else if ((i == bullet_x) && (j == bullet_y))
printf("|");//输出子弹
else
printf(" ");//输出空格
}
printf("\n");
}
Sleep(100);
}
//与用户输入无关的输入
void updateWithoutInput() {
if (bullet_x > -1)
bullet_x--;
}
//与用户输入有关的更新
void updateWithInput() {
char input;
if (kbhit()) {//判断是否有东西输入
input = getch();
switch (input) {
case 'a':position_y--; break;//左移
case 'd':position_y++; break;//右移
case 'w':position_x--; break;//上移
case 's':position_x++; break;//下移
case ' ':
bullet_x = position_x - 1;//发射子弹的初始位置在飞机的正上方
bullet_y = position_y; break;
default:;
}
}
}
//主函数
int main() {
startup();//数据初始化
while (true) {//游戏循环执行
show();//显示画面
updateWithoutInput();//与用户输入无关的更新
updateWithInput();//与用户输入有关的更新
}
return 0;
}
2.1.4 敌机移动
我们有了一个敌人,然而好像和靶子没有区别,这次我们将实现敌人会向我们移动
(
e
n
e
m
y
_
x
+
+
)
(enemy\_x++)
(enemy_x++)。
为了降低敌机移动速度的同时影响用户输入相应的频率,要使用一个小技巧,即在 updateWithoutInput() 函数中利用静态变量 speed,每执行 10 次 updateWithoutInput 函数敌机才移动一次。
void updateWithoutInput() {//与用户输入无关的更新
if (bullet_x > -1)
bullet_x--;
//用来控制敌机向下移动的速度,每隔几次循环才移动一次敌机
//用来修改,虽然用户按键的交互速度还是很快,但NPC的移动显示可以降速
static int speed = 0;
if (speed < 10)
speed++;
if (speed == 10) {
enemy_x++;
speed = 0;
}
}
2.1.5 击中敌机