摘要: 飞机大战是一款经典的游戏,最早应追溯到打击者1945(Strikers 1945),这是日本彩京公司于1995年发售的飞行射击游戏。本作是参照打击者1945基于visual C++写成的飞行射击类游戏。本作中实现了敌机的产生功能、子弹的发射功能、飞机中弹销毁和计算得分等功能,而且通过文件读写的相关操作完成了存档与读档的相关操作。本作通过便捷的操作方式,使玩家可以轻易地上手该游戏,在游戏中放松心情,释放压力,提高反应能力。游玩该游戏可以为玩家带来欢乐。
关键词: 可视化 飞机大战 游戏设计
引言 随着社会的不断发展,人们的生活方式也不断的在变化,人们的娱乐方式也越发的多种多样。人们对美好生活的向往,不单单局限于物质生活,人们的精神生活也在一天天的丰富。游戏是很多人精神生活中的一种重要组成部分。毫无疑问飞机大战是一款极其经典的游戏,玩家通过鼠标或键盘操作飞机攻击敌方飞机,躲避碰撞和敌方飞机攻击。极其简单的操作和轻松的上手,使得这一款游戏带给了无数人欢乐。
1 需求分析
在飞行射击类游戏中,玩家登陆游戏后可以通过鼠标或键盘操作飞机前进,躲避敌机攻击,并通过点击鼠标左键或空格键发射子弹击败敌机。
完成这个飞机大战游戏的设计,需要完成用户飞机的移动功能,敌机的产生功能、子弹的发射功能、飞机中弹销毁和计算得分等功能。在用户需要时可以暂停游戏,可以通过文件读写完成存档与读档。为丰富游戏的趣味性,相应增加了各种音效,并会根据用户的得分产生相应的敌机。
2 关键技术
2.1 C++面向对象的程序设计
C++起始于C语言。当C语言发展到巅峰时出现了增加关键词和类的C with class的C语言版本,而这是C语言的一大突破,开发者将这一种语言命名为C++。这便是C++最早的版本。
美国AT&T贝尔实验室的本贾尼·斯特劳斯特鲁普博士在20世纪80年代初期成功地实现了C++,即C with classes。当时C++是作为C语言的加强版本出现,从给C增加类开始,不断增加新的特征[1]。
然而就目前而言,C++可以认为它是一门独立的编程语言,它源于C语言但是它并不依赖于C语言。C++与C语言也是有本质差别:在于C++是面向对象的,而C语言是面向过程的。或者说C++是在C语言的基础上增加了面向对象程序设计的新内容,是对C语言的一次更重要的改革,使得C++成为软件开发的重要工具。
2.2 C++语言的优点
(1)在C语言的基础上进行扩充和完善,使C++兼容了C语言的面向过程特点,又成为了一种面向对象的程序设计语言; (2)可以使用抽象数据类型进行基于对象的编程; (3)可以使用多继承、多态进行面向对象的编程; (4)可以担负起以模版为特征的泛型化编程。 (5)C++实现了面向对象程序设计。在高级语言当中,处理运行速度是最快的,大部分的游戏软件,系统都是由C++来编写的。
(6)C++语言非常灵活,功能非常强大。如果说C语言的优点是指针,那么C++的优点就是性能和类层次结构的设计。
(7)C++非常严谨、精确和数理化,标准定义很细致。
(8)C++语言的语法思路层次分明、相呼应;语法结构是显式的、明确的。
2.3 Visual C++的优点
(1)与Windows紧密结合,MFC类库集成了大量已经预先定义好的类,用户可以根据编程的需要定义相应的类,或根据需要自己定义相应的类。因此Visual C++在使用API等方面和Windows联系的最为紧密[2]。
(2)强大的类库支持和类改造能力。代码重用是C++追求的目标,重用就是从已有的基类派生出新的C++类;MFC提供了大量的基类供程序员们根据不同的应用要求生成新的类以满足要求。VC++有了MFC,具有非常强大对类改造的能力。只要集成MFC类,稍加修改就可以得到符合要求的控件类或应用类。
(3)拥有高效的运行速度。高的运行速度取决于两点:1.软件本身编写的质量,2.编程工具的编译质量。因为VC++非常接近Windows底层,所以编译器所编译的质量相当高,从而保证了VC++编写出来的软件产品拥有高效的运行速度[3]。
2.4 C++的语言体系
(1)C子语言。C++是以C语言为基础,C++几乎支持C语言的全部功能。
(2)面向对象的C++。C++首先是一门面向对象的程序设计语言,并以此闻名。
(3)泛型编程语言。相比C语言,C++增加了模板,C++强大的模板功能使系统能够在编译期间就能完成许多工作,从而大大提高了运行效率[4]。
(4)STL。随着STL的不断发展,渐渐成为C++程序设计体系中不可或缺的一部分。其安全性与规范性的优秀使得它受到程序员的欢迎[1]。
3.游戏总体设计
游戏被分成两个部分,一部分是与用户输入有关的更新,包括根据鼠标位置或键盘按键进行飞机的移动和炮弹发射等等。另一部分是与用户输入无关的更新,包括子弹移动,敌机移动逻辑等判断。图1为飞机大战程序设计图。
[图片上传失败...(image-6b775-1626647574358)]
图1 飞机大战程序设计图
4 游戏功能实现
4.1 代码设计
4.1.1 头文件
(1) #include<iostream>头文件,包含头文件输入输出流,c++中没有c语言中输入输出语句(比如#include<stdio>),而是利用数据流来解决这个问题。要使用比如cout,cin语句输入输出函数。其中#include文件的目的是把多个编译单元公用的内容单独放在一个文件里减少整体代码尺寸,或者提供可跨工程使用的公共代码;
(2)#include<fstream>头文件#include 是C++的预编译语句,作用是包含对应的文件,在这里是包含C++的STL头文件fstream。在包含了这个文件后,就可以使用fstream中定义的类及各种成员函数了。fstream是C++ STL中对文件操作的合集,包含了常用的所有文件操作。在C++中,所有的文件操作,都是以流(stream)的方式进行的,fstream也就是文件流file stream[5]。
(3)#include<iomanip>头文件,这个头文件是声明一些 “流操作符”的,比较常用的setw(int);//设置显示宽度、left//right//设置左右对齐、setprecision(int);//设置浮点数的精确度。
(4)#include<fstream>包含读写文件头文件,实际上是一个输出流的类模板,含有ifstream和ofstream两个派生类。
(5)#include <math.h> 是包含math头文件的意思,math.h头文件中声明了常用的一些数学运算,比如乘方,开方运算等等。
(6)#include<graphics.h>头文件是C语言和visual studio的图形库文件,包含像素函数、线型函数、画线函数、相对画线函数等多种函数,可进行图形的快速编程。这也是实现可视化的最重要工具。使用easyx.exe,可以直接运行安装图形库到visual studio。然后直接使用。
(7)#include<windows.h>头文件是最重要的头文件之一,它包含了其他Windows头文件,这些头文件也包含了其他头文件,其中有用户界面函数<Winuser.h>、图形设备接口函数<Wingdi.h>[6]。
(8)#include<conio.h>是Console Input/Output(控制台输入输出)的简写,其中定义了通过控制台进行数据输入和数据输出的函数,主要是一些用户通过按键盘产生的对应操作,比如getch()函数等等[4]。
(9)#pragma comment(lib,"Winmm.lib")声明程序使用了winmm.lib库,这个库是是Windows多媒体相关应用程序接口,用于低档的音频和游戏手柄。可以用来实现音频的添加和利用。在该飞机大战程序中这个库中的内容实现了游戏运行时中的背景音乐的开始和结束放映等功能。
4.1.2使用函数
settextstyle() 设置文本型式函数,函数settextstyle() 设置图形文本当前字体、文本显示方向(水平显示或垂直显示)以及字符大小。在使用中用于显示得分和成绩。通常与Outtextxy配套使用。
Outtextxy()函数,这个函数用于在指定位置输出字符串。
loadimageLoadImage()函数,功能是装载图标,光标,或位图。在本程序中用于加载图片。
Initgraph()函数功能为初始化图形系统。pathtodriver表示存放图形驱动文件的路径。
SetTextColor(),Windows API 函数,设置指定DC中的文字颜色。
kbhit()是一个C和C++函数,用于非阻塞地响应键盘输入事件。其中文可译为“键盘敲击”(keyboard hit),注意这个函数在高版本VC下已被淘汰,应使用_kbhit()函数。
MouseHit()函数是实现鼠标操作最关键的函数,用于判断是否有鼠标信息。[5]使用MouseHit()函数效果与kbhit()函数效果类似,如果没有鼠标信息自动跳过。避免了因为没有鼠标信息导致程序无法运行的状况[7]。
getch()是编程中所用的函数,这个函数是一个不回显函数,当用户按下某个字符时,函数自动读取,无需按回车,有的C语言命令行程序会用到此函数做游戏,但是这个函数并非标准函数。在高版本VC或者VS中已经无法使用应该使用_getch()函数[8]。
SetBkMode()函数这就需要使用SetBkMode函数来设置DrawText函数的输出方式,显示设备共有两种输出方式:OPAQUE和TRANSPARENT。OPAQUE的方式是用当前背景的画刷的颜色输出显示文字的背景,而TRANSPARENT是使用透明的输出,也就是文字的背景是不改变的。
MCI(Media Control Interface,媒体控制接口)函数中,有些只适用于一种接口方式,有些则两种接口都可以用。mciSendString只适用于命令串接口方式(命令串中不区分大小写)以形如mciSendString("play movie",buf,sizeof(buf),NULL);的方式进行音频播放,以形如mciSendString("pause movie",buf,sizeof(buf),NULL);的方式暂停播放。以形如mciSendString("close movie",buf,sizeof(buf),NULL)的形式关闭播放。
4.2操作逻辑
本程序使用两种操作方式,依靠键盘按键操作和依靠鼠标位置进行操作。图2为飞机移动操作逻辑示意图。
[图片上传失败...(image-cdff38-1626647574358)]
图2 飞机移动操作逻辑示意图
使用鼠标操作代码如下:
if (isExpolde == 0)
{
MOUSEMSG m;
while (MouseHit())
{
m = GetMouseMsg();
if (m.uMsg == WM_MOUSEMOVE)
{
position_x = m.x;
position_y = m.y;
}
else if (m.uMsg == WM_LBUTTONDOWN)
{
bullet_x = position_x;
bullet_y = position_y - 85;
}}
}
对应的使用键盘操作代码为:
char input;
if (_kbhit()) // 判断是否有输入
{input = _getch(); // 根据用户的不同输入来移动,不必输入回车
if (input == 27) // ESC键的ACSII码为27
gameStatus = 3;
if (input == 'a')
position_x -= 10;
if (input == 'd')
position_x += 10;
if (input == 'w')
position_y += 10;
if (input == 's')
position_y -= 10;}
先定义MOUSEMSG的鼠标类型参数m;通过while (MouseHit()) 进行操作,既能保证能够使用鼠标进行操作也避免了,在没有鼠标操作时游戏的停止。
类似的有定义char 类型的的变量通过while(_kbhit())来进行是否有键盘信息的判断,用_getch()函数获取键盘的敲击值。
4.3 与用户输出无关的逻辑
4.3.1 敌机生成逻辑
使用rand()函数生成一个最大为32767的数,并通过%(Width-50)得到飞机的初始坐标,并同时将blood等参数复原。
4.3.2 敌机简单移动逻辑
代码如下:
if (enemy_y < High - 25)
{
if (enemy_x == 0)
flag = 0;
if (enemy_x == 500)
flag = 1;
enemy_y = enemy_y + 1;
if (flag == 1)
enemy_x = enemy_x--;
else enemy_x = enemy_x++;
}
通过定义全局变量static flag 进行操控飞机的飞行方向,同时在每个循环过程中使飞机能够实现摆动下降。
4.4暂停页面与存储逻辑
通过_getch()函数读取输入,如存在按键为Esc时,将gameStatus设置为3,出现暂停页面,图3为游戏暂停页面。
图3 游戏暂停页面
游戏数据储存逻辑
void read() {
ifstream file2;//输入指针
file2.open("../data.txt");
file2 >> position_x >> position_y >> bullet_x >> enemy_x >> enemy_y >> isExpolde >> score;
file2.close();};
void write() {
ofstream file1;
file1.open("./data.txt", std::ios::app);
if (!file1.is_open()) {
std::cout << "打开文件失败!!\n";
exit(0);
}
file1 << position_x << " " << position_y << " " << bullet_x << " " << enemy_x << " " << enemy_y <<" " << isExpolde <<" " << score << "\n";
file1.close();
};
通过ifstream和ofstream两个类进行操作,实现数据的存储于写入。也通过键盘操作识别Esc按钮实现暂停操作。
图4为飞机大战程序登录界面,图5为程序运行截图。
图4 程序登录界面
图5 程序运行截图
5.总结
基于C++的可视化飞机大战游戏是一个简单的可视化的小游戏,玩家能够通过鼠标或键盘进行操控飞机的移动和攻击,并且运用了文件操作技术,可以实现数据的永久性保存。基于C++的飞机大战游戏是采用C++语言及其easyX拓展模块开发完成的。本项目实现了游戏流程中的所有功能,界面布局更加人性化,并有着良好的可扩展性。但游戏依旧存在一些不足之处,比如说本游戏还没有实现对玩家操纵飞机进行血量的显示,敌方飞机尚无法发射子弹,对击中逻辑的判断还存在问题。
参考文献:
[1]黄宝贵等.C++面向对象程序设计[M] 北京:清华大学出版社,2019:2-3
[2]童晶编著.C语言程序设计与游戏开发实践教程[M] 北京:清华大学出版社 2017:16
[3]黄维通等.Visual C++面向对象与可视化程序设计[M](第三版)北京:清华大学出版社 2011:14
[4]郑莉等编著.C++程序设计语言(第三版)[M].北京:清华大学出版社,2005:134-139.
[5]刘振安等编著.C++程序设计课程设计[M] 北京:机械工业出版社,2004:23-31 [6]朱立华等编著.面向对象程设计及C++[M].北京:人民邮电出版社,2008:43 [7]郑莉,董渊.C++语言程序设计(第二版) [M].北京清华大学出版社,2002:23 [8]陈维兴,林小茶.C++面向对象程序设计教程(第2版)[M].北京清华大学出版社.2007:34