基于EasyX的飞机大战游戏设计-----ZYS
一、问题描述
程序开始运行时,显示开始界面,分为开始游戏、退出游戏两个选项。点击开始游戏,游戏开始,可用键盘的左右移动键移动飞机并按空格发射子弹以便飞机击中障碍物。障碍物分大小两种,游戏进行时背景换为蓝色背景。游戏结束后,显示飞机击杀数量,与重新游戏和退出游戏两个选项。飞机大战游戏应符合以下条件:
(1)开始界面与结束界面清晰明了,结束界面显示击杀数量
(2)飞机由鼠标控制移动,可上下左右移动。移动范围应限制在游戏界面内。
(3)游戏以飞机触碰到障碍物为结束条件,一旦飞机触碰到障碍物,游戏立刻结束,结束后结算显示击杀数量
《飞机大战》是一款经典的射击游戏,玩家需要操控一架飞机,灭敌方飞机和障碍物,获得高分。本游戏设计基于 Easy X 图形库,使用 C++ 编程语言实现。游戏旨在提供紧张刺激的游戏体验,同时锻炼玩家的反应速度和策略思维。飞机大战游戏的规则通常简单明了,玩家只需控制飞机移动,躲避敌人和子弹,就可以进行游戏。这样的设计让新手玩家可以快速学会游戏操作。该游戏通常不需要太多的时间投入,玩家可以在碎片时间进行游戏,起到放松身心、缓解压力的作用。该游戏支持多种平台,如PC、手机、网页等,方便玩家随时随地游戏。通过本游戏设计,玩家可以在轻松愉快的氛围中体验到紧张刺激的游戏感受,同时锻炼自己的反应速度和策略思维。游戏设计充分考虑了玩家的需求和游戏的可玩性,力求打造一款令人难以忘怀的飞机大战游戏。
图1.1游戏的操作流程
二、系统设计
1.功能模块设计
(1)关闭功能,不支持修改窗口大小,因为插入的图片对应有坐标,随意改变窗口大小会增加坐标处理的复杂程度。
(2)键盘与鼠标连接控制模块:可以用鼠标与键盘来共同控制游戏的开始、结束与进行。
(3)速度控制模块:飞机的子弹发射速度可以通过改变相应的代码来改变。
(4)计数模块:定义一个无符号实数kill,通过hit函数来计算击杀数量。
(5)音乐模块:可通过改变对应代码来更改音乐。
(6)循环模块:重新定义了整型变量H,通过over函数,得到H的值,如果H等于1则重新开始,若H等于0则退出游戏,每次游戏结束都会重复
2.数据结构设计
A.全局结构体变量
(1)玩家结构体定义及其变量定义
图2.1玩家结构体定义
B.游戏主体结构函数
(1)主函数
图2.2游戏主函数
(2)游戏开始界面函数,包括音乐的播放与字体颜色。
图2.3游戏开始界面函数
(3)游戏结束界面函数,包括结束背景的修改,字体颜色,用户结束后的选择的判断。
(4)飞机参数的定义及飞机子弹的初始化
![]() |
图2.4结束模块函数
图2.5敌机和子弹的初始化
(5)图像加载函数及图像坐标设置
图2.6游戏画布处理函数
(6)子弹及飞机的速度控制
图2.7子弹及飞机的速度控制
图2.8玩家控制飞机速度
(7)飞机击杀数量计算
图2.9飞机击杀数量计算
3.函数功能描述
#include<coino.h>提供屏幕缓冲区函数,用于文本模式下的屏幕输出。
#include<stdlib.h>用于执行内存分配、程序控制、转换操作等任务。
#include<time.h>定义与时间相关的函数,以及与日期和时间相关的常量。
#include<graphics.h>用于进行图形编辑。
#include<vector>用于在源代码文件中包含标准模板库中的向量容器。
#include<windows.h>头文件提供了访问 Windows 操作系统核心功能的途径,包括图形、用户界面、消息处理、文件系统等。使用这个头文件,你可以创建窗口、处理输入事件、绘制图形、播放声音等。
#include <mmsystem.h> 一个预处理指令,用于在源代码文件中包含 Microsoft Multimedia API 的头文件。这个 API 提供了访问多媒体功能的方法,例如音频播放、视频播放、多媒体消息等。
#pragma comment(lib, "winmm.lib")是 Windows 多媒体 API(Multimedia API)的库文件,它包含了用于处理多媒体操作(如音频播放、录音和多媒体消息)的函数。
三、详细设计
本游戏利用Easyx图形处理库进行游戏的编写。对一些游戏细节的设计更加独特,比如飞机的形象设计、飞机移动动画等,运用了更多的人机交互,如鼠标控制游戏开始、结束,键盘控制飞机移动。此工程只有一个.cpp和多个.h文件组成,采用模块化编程,可移植性强。本游戏在传统飞机大战游戏上做了改进,游戏上手简单,游戏的可玩性增加。
1.游戏界面
本游戏游戏界面较简单,分为开始游戏界面、游戏进行界面、结束游戏界面,界面功能简单清晰。
A.按键功能
首先加载按键图片,设置一个函数来判断鼠标是否在按键区域内,如果不在案件区域内,点击后不做反应,仍保持在原界面;如果在按键区域内,点击后会跳转到相应界面。
图3.1开始界面函数
图3.2结束界面函数
图3.3游戏进入界面
2.游戏主体
A.敌机出现及飞机移动动画
进入游戏后,出现多个敌机,随着时间流失敌机开始往下移动;飞机刚开始位于屏幕的正下方,随着左右上下键的移动改变位置以发射子弹来击败敌机。
图3.4飞机的初始化
B.子弹发射动画
游戏开始后,玩家手动按住键盘空格,子弹开始发射,并且随着左右键控制飞机的移动,子弹的方向也随之移动,随后打到敌机上击败敌机。
图3.5子弹创建模块
图3.6游戏运行图
C.音乐播放函数
mciSendString("open ./images/222.mp3 alias music", NULL,NULL,NULL);
mciSendString("play music repeat", NULL, NULL, NULL);
D.开始界面与结束界面背景改变
loadimage(&bgain,_T("./images/bg3.png"));//修改开始背景
loadimage(&bg1, _T("./images/bg2.png")); //修改结束背景
E.飞机参数设置
设置了玩家飞机的坐标,飞机的大小,以及敌机的血量,判断敌机是否存活
图3.7飞机参数的定义
F.敌机的定义
定义了敌机的大小
图3.8飞机大小的定义
G.游戏数据的初始化
初始化飞机的起始位置与存活状态,开始时飞机位于正下方,处于满血状态。
void game_csh()
{
player.x = bgwidth / 2 - 50;
player.y = bgheight - 120;
player.live = true;
player.width = 114;
player.height = 85;
}
初始化子弹与敌机子弹由飞机发射,以数组的方式初始化,敌机同样以数组的方式初始化,开始出现时是满血状态。
for (int i = 0; i < bullet_num; i++)
{
bullet[i].x = 0;
bullet[i].y = 0;
bullet[i].live = false;
}
for (int i = 0; i < enemy_num; i++)
{
enemy[i].live = false;
enemyHP(i);
}
H.游戏图像的加载
设定一个图像指针变量loadimage,将图片的地址赋给指针,通过指针直接调用图片。
void loadIMAGE()
{
I.图像画布处理
先调用图像加载函数,再通过void gamedraw()改变图像坐标,改变图像位置。
void gamedraw()
{
loadIMAGE();
putimage(0, 0, &bg);
putimage(player.x, player.y, &t_player, SRCINVERT);
for (int i = 0; i < bullet_num; i++)
{
if (bullet[i].live)
{
putimage(bullet[i].x, bullet[i].y, &t_bullet, SRCINVERT);
}
{
if (enemy[i].type == BIG)
{
}
for (int i = 0; i < enemy_num; i++)
putimage(enemy[i].x, enemy[i].y, &t_enemy2, SRCINVERT);
}
else putimage(enemy[i].x, enemy[i].y, &t_enemy1, SRCINVERT);
}
J.子弹速度的控制
通过定义一个speed变量,设置子弹速度,改变对应变量即可改变子弹输出速度大小。
void move_b(int speed)
{
if (GetAsyncKeyState(VK_SPACE) && timer(300, 1))
{
bullet_creat();
}
for (int i = 0; i < bullet_num; i++)
{
if (bullet[i].live)
{
bullet[i].y -= speed;
if (bullet[i].y < 0)
{
bullet[i].live = false;
}
}
}
}
K.飞机与敌机的移动速度控制
敌机的速度由变量speed决定,飞机的速度由玩家通过鼠标控制。
void move_e(int speed)
{
for (int i = 0; i < enemy_num; i++)
{
if (enemy[i].live)
{
enemy[i].y += speed;
if (enemy[i].y > bgheight)
{
enemy[i].live = false;
}
}
}
}
//敌机速度
L.子弹是否击中飞机的判断
int hit(unsigned long long &kill)
{
int h;
for (int i = 0; i < enemy_num; i++)
{
if (!enemy[i].live)
continue;
for (int j = 0; j < bullet_num; j++)
{
if (!bullet[j].live)
continue;
if (bullet[j].x > enemy[i].x &&
bullet[j].x < enemy[i].x + enemy[i].width &&
bullet[j].y > enemy[i].y &&
bullet[j].y < enemy[i].y + enemy[i].height)
{
bullet[j].live = false;
enemy[i].hp--;
}
}
if (enemy[i].hp <= 0)
{
enemy[i].live = false;
kill++;//计算击杀数
}
}