飞机大战的部分思路框架
文章目录
实现的功能需求:
- 背景图片的打开,使用了#include<easyx.h> 的图形处理解决(各种图片的打开绘制),这里因为素材的原因没有实现(实体透明),没有找到相关的黑底白面,白底彩面的图片素材,显示效果不佳,再次基础上通过两张一样的图片对图片显示位置的改变,实现图片的滚动效果;在通过 BeginBatchDraw():开始批量绘制,将各种图片绘制在缓存中,以及 EndBatchDraw () :结束绘图,将一张完整的一帧绘制子在窗口中,实现帧数的刷新,防止闪屏;因为是一直在绘制图片的所以要 使用循环条件
- 背景音乐,使用一个阻塞的按键控制开关,再通过显示一张小图片的显示表示音乐的开关状态;
- 飞机的出现,与背景图片的显示一样操作;飞机的移动使用,使用一个非阻塞按键GetAsyncKeyState() 对飞机的细腻操作,同样通过改变飞机图片的出现的位置的改变达到对飞机的移动效果;
- 子弹的显示,同样与背景图片的显示一样操作;子弹的通过一个标记达到对子弹的有限的重复的利用,嫌少栈帧,;对子弹的出现的配合(联系)飞机坐标的变化,合理设计子弹的出现位置;再通过改变子弹坐标出现的位置的改变实现,子弹的飞行;
这次项目的实现,让我明白了项目架构的重要性,写项目的时候
-
仔细分析项目功能的需求
-
设计合理清晰的架构,不然几百行代码下来自己都不知道自己在写什么
- 头文件的定义(不要放变量,防止重定义),结构体,枚举,数据(数值)的信息化(#define),不要写死了,影响需求的改变维护,可变;
- 各种功能函数使用文件(见闻知意),分开来定义,实现功能函数;如 ** 文件(使用来实现初始化数据的), ** 文件(用来实现数据可视化,显示图片效果)
-
数据的初始化
-
数据的可视化(图片效果的显示)
-
数据的更新(一些操作上实现的改变),以及一些消失的条件的更新判断
-
退出的设定
目前在这个项目领悟的就这些了:
为了方便大家查看先给个大概图示: 说明一个我用的是 C语言编写的 这里用c++是因为 Easyx 不支持 c语言的,支持c++ 但是 c++兼容 C语言 所以影响不大,如果要运行下面代码的朋友,需要安装 Easyx 图形处理工具的,免费的,百度即可,具体安装详细: [Easyx的详细安装教程]((57条消息) (EasyX入门与实战)第一章 下载并安装easyX库_代码骑士的博客-CSDN博客)
代码:
头文件 代码: GameHead.h
#pragma once // 注意不要删除了,为了避免头文件的重复引入,影响效率
#include<stdio.h> // 标准输入输出
#include<windows.h> // 操作系统 注意要在 头文件mmsystem.h的前面,不然会报错的,因为音乐是要通过操作系统打开的
#include<mmsystem.h> // 多媒体
#include<conio.h> // 输入按键的头文件
#include<easyx.h> // 图形处理
#pragma comment (lib, "winmm.lib") // 预处理
// 定义窗口的大小
#define WIDTH 365 // 窗口的宽度
#define HEIGHT 650 // 窗口的高度
#define PLANEWIDTH 38 // 飞机的宽度
#define PLANEHEIGHT 73 // 飞机的高度
#define BULLEtWIDTH 31 // 子弹的宽度
#define BuLLEHEIGHT 124 // 子弹的高度
// 定义一个飞机的结构体
typedef struct My_plane
{
IMAGE myPlanephoto; // 存放自己飞机的图片
int plang_x = 0; // 自己飞机的X轴的位置
int plang_y = 0; // 自己飞机的Y轴的位置
int myPlaneblood; // 定义自己飞机的血量
}My_plane;
typedef struct Bullet
{
IMAGE myBulletPhoto; // 存放自己的子弹的图片
int bullet_x = 0; // 自己子弹的X轴的位置
int bullet_y = 0; // 自己子弹的Y轴的位置
bool Isexit; // 自己子弹是否存在的
}Bullet;
// 游戏场景
void GameInit(IMAGE* background_image, My_plane* myPlane,Bullet* bullet);
// 绘制界面(数据可视化)
void GameDraw(IMAGE* background_image, int* background_image_y1, int *background_image_y2);
// 数据更新
void GameUpdate(int* Background_image_y1, int* Background_image_y2, Bullet* bullet, My_plane* myPlane);
// 实现图片的上下滚动
void PhotosRoll(int* Background_image_y1, int* Background_image_y2);
// 显示音乐的状态
void MusicState();
// 实现开关音乐的控制
void ControlMusic(Bullet* bullet, My_plane* myplane);
//实现绘制(显示)自己的飞机
void ShowMyplane(My_plane* myPlane);
// 实现自己飞机的移动效果
void PlanexMoving(My_plane* myPlane);
// 绘制(显示)自己的子弹
void ShowMybullet(Bullet* bullet);
// 实现移动子弹
void MoveBullet(Bullet* bullet);
main 代码文件(Game.cpp):
#define _CRT_SECURE_NO_WARNINGS 1
#include"GameHead.h" // 自行定义的头文件使用 双引号 “ ” ;
// 查找路径的不同,“” 双引号可以查找自己本身所在的路径
// 定义背景图片的位置
int Background_image_y1 = 0; // 最开头
int Background_image_y2 = -HEIGHT; // 最末尾
IMAGE Background_image = 0; // 定义一个变量存放背景图片
IMAGE* background_image = &Background_image; // 定义一个IMAGE 的指针类型
extern bool musicState ; // 定义一个bool 类型用于表示音乐的播放关闭的状态;
My_plane myPlane = { 0 }; // 定义一个自己的飞机
Bullet bullet[10] = { 0 }; // 定义自己的子弹 10 发
int main()
{
// 创建窗口
initgraph(WIDTH, HEIGHT); // x,y
cleardevice(); // 刷新窗口
// 游戏场景
GameInit(background_image,&myPlane,bullet);
while (1)
{
// 绘制界面 (数据可视化)
GameDraw(background_image, &Background_image_y1, &Background_image_y2);
//实现绘制(显示)自己的飞机
ShowMyplane(&myPlane);
// 绘制(显示)自己的子弹
ShowMybullet(bullet);
// 实现移动子弹
MoveBullet(bullet);
// 实现自己飞机的移动效果
PlanexMoving(&myPlane);
// 数据的更新
GameUpdate(&Background_image_y1, &Background_image_y2,bullet,&myPlane);
Sleep(10); // 图片减缓速度
}
system("pause"); // 防止闪退
return 0;
}
代码文件初始化数据(GameInit.cpp):
#define _CRT_SECURE_NO_WARNINGS 1
#include"GameHead.h" // 自行定义的头文件使用 双引号 “ ” ;
// 查找路径的不同,“” 双引号可以查找自己本身所在的路径
// 初始化背景图片
void GameInit(IMAGE* background_image,My_plane*myPlane,Bullet*bullet)
{
// 存放背景的图
loadimage(background_image, "setting2.png"); // 把图片存放到使用IMAGE定义的变量(Background_image)
// 初始化音乐
mciSendString("open 封茗囧菌-东京不太热.mp3", 0, 0, 0); // open 打开音乐文件
mciSendString("play 封茗囧菌-东京不太热.mp3", 0, 0, 0); // play 播放音乐
/* 注意 音乐的名称不要有空格因为该函数mciSendString() 是通过空格来分割字符串的*/
//初始化自己的飞机
// 1.存放自己飞机的图片,
loadimage( &myPlane->myPlanephoto, "plane.png");
// 2.飞机的初始位置
myPlane->plang_x = (WIDTH - PLANEWIDTH) / 2; // 自己飞机的x轴,WIDTH 窗口的宽度
myPlane->plang_y = HEIGHT - PLANEHEIGHT; // 自己飞机的Y轴 HEIGHT 窗口的高度
myPlane->myPlaneblood = 100; // 自己飞机的血量 100
// 初始化自己的子弹
loadimage(&(bullet->myBulletPhoto), "bullet.png");
// 将十颗子弹初始化为 空 状态;
for (int i = 0; i < 10; i++)
{
bullet[i].Isexit = false;
}
}
代码文件数据的可视化(GameDraw.cpp)
#define _CRT_SECURE_NO_WARNINGS 1
#include"GameHead.h" // 自行定义的头文件使用 双引号 “ ” ;
// 查找路径的不同,“” 双引号可以查找自己本身所在的路径
extern bool musicState = true; // 定义一个bool 类型用于表示音乐的播放关闭的状态;
// 绘制界面(数据可视化)
void GameDraw(IMAGE* background_image,int* Background_image_y1,int* Background_image_y2)
{
BeginBatchDraw(); // 开始批量绘制,将各种图片绘制在缓存中,
putimage(0, 0, background_image);
putimage(0, *Background_image_y1, background_image);
putimage(0, *Background_image_y2, background_image);
MusicState(); // 显示音乐的状态
EndBatchDraw(); // 结束批量绘制,将完整的一帧绘制在窗口中
}
// 显示音乐的状态
void MusicState()
{
IMAGE VoicePhoto[2]; // 定义一个IMAGE类型的数组存放声音状态的图片
loadimage(&VoicePhoto[0], "playvoice.png"); // 把声音播放图片存放到数组下标[0]的位置地址
loadimage(&VoicePhoto[1], "pausvoice.png"); // 把声音关闭图片存放到数组下标[1]的位置地址
if (musicState)
{
//outtextxy(10, 10, "playing");
putimage(0, 0, &VoicePhoto[0]); // 把存放在数组下标[0]的图片显示在窗口 0,-10的位置
}
else
{
//outtextxy(10, 10, "pausing");
putimage(0, -20, &VoicePhoto[1]); // 把存放在数组下标[1]的图片显示在窗口 0,-10的位置
}
}
//实现绘制(显示)自己的飞机
void ShowMyplane(My_plane* myPlane)
{
BeginBatchDraw(); // 开始批量绘制,将各种图片绘制在缓存中,
if (myPlane->myPlaneblood > 0)
{
putimage(myPlane->plang_x, myPlane->plang_y, &myPlane->myPlanephoto);
}
EndBatchDraw(); // 结束批量绘制,将完整的一帧绘制在窗口中
}
// 绘制(显示)自己的子弹
void ShowMybullet(Bullet*bullet)
{
BeginBatchDraw(); // 开始批量绘制,将各种图片绘制在缓存中,
for (int i = 0; i < 10; i++)
{
if (bullet[i].Isexit)
{
putimage(bullet[i].bullet_x, bullet[i].bullet_y, &(bullet->myBulletPhoto));
}
}
EndBatchDraw(); // 结束批量绘制,将完整的一帧绘制在窗口中
}
代码文件数据的更新(GameUpdate.cpp)
#define _CRT_SECURE_NO_WARNINGS 1
#include"GameHead.h" // 自行定义的头文件使用 双引号 “ ” ;
// 查找路径的不同,“” 双引号可以查找自己本身所在的路径
extern bool musicState ; // 定义一个bool 类型用于表示音乐的播放关闭的状态;
// 数据更新
void GameUpdate(int* Background_image_y1, int* Background_image_y2, Bullet* bullet, My_plane* myPlane)
{
// 实现图片的上下滚动
PhotosRoll(Background_image_y1, Background_image_y2);
// 实现开关音乐的控制
ControlMusic(bullet, myPlane);
}
// 实现图片的上下滚动
void PhotosRoll(int* Background_image_y1, int* Background_image_y2)
{
(*Background_image_y1)++;
if ((*Background_image_y1) > HEIGHT) // HEIGT 窗口的高度
{
(*Background_image_y1) = -HEIGHT;
}
(*Background_image_y2)++;
if ((*Background_image_y2) > HEIGHT)
{
(*Background_image_y2) = -HEIGHT;
}
}
// 实现开关音乐的控制
void ControlMusic(Bullet* bullet, My_plane* myPlane)
{
if (_kbhit())
{
char key = _getch(); // 接受按键的信息
if (key == '1')
{
if (musicState)
{
mciSendString("pause 封茗囧菌-东京不太热.mp3", 0, 0, 0); //暂听音乐
musicState = !musicState; // 修改音乐的状态
}
else
{
mciSendString("play 封茗囧菌-东京不太热.mp3", 0, 0, 0); // 播放音乐
musicState = !musicState; // 修改音乐的状态
}
}
else if (key == ' ')
{
for (int i = 0; i < 10; i++)
{
if (!bullet[i].Isexit) // 将false 变成 true
{
bullet[i].Isexit = true;
bullet[i].bullet_x = myPlane->plang_x;
bullet[i].bullet_y = myPlane->plang_y - BuLLEHEIGHT;
break;
}
}
}
}
}
// 实现自己飞机的移动效果
void PlanexMoving(My_plane* myPlane)
{
// 飞机向下移动
// `这里运行了一个非阻塞按键的使用
if (GetAsyncKeyState(VK_UP))
{
if (myPlane->plang_y >= HEIGHT)
{
myPlane->plang_y = HEIGHT - PLANEHEIGHT;
}
if (myPlane->plang_y <= -3)
{
myPlane->plang_y = PLANEHEIGHT;
}
myPlane->plang_y -= 3;
}
// 飞机向上移动
if (GetAsyncKeyState(VK_DOWN))
{
if (myPlane->plang_y >= HEIGHT)
{
myPlane->plang_y = HEIGHT - PLANEHEIGHT;
}
if (myPlane->plang_y <= -3)
{
myPlane->plang_y = PLANEHEIGHT;
}
myPlane->plang_y += 3;
}
// 飞机向左移动
if (GetAsyncKeyState(VK_LEFT))
{
if (myPlane->plang_x >= WIDTH)
{
myPlane->plang_x = WIDTH - PLANEWIDTH;
}
if (myPlane->plang_x <= -3)
{
myPlane->plang_x = PLANEWIDTH;
}
myPlane->plang_x -= 3;
}
// 飞机向右移动
if (GetAsyncKeyState(VK_RIGHT))
{
if (myPlane->plang_x >= WIDTH)
{
myPlane->plang_x = WIDTH - PLANEWIDTH;
}
if (myPlane->plang_x <= -3)
{
myPlane->plang_x = PLANEWIDTH;
}
myPlane->plang_x += 3;
}
}
// 实现移动子弹
void MoveBullet(Bullet* bullet)
{
for (int i = 0; i < 10; i++)
{
if (bullet[i].Isexit)
{
bullet[i].bullet_y -= 7;
if (bullet[i].bullet_y < -BuLLEHEIGHT)
{
bullet[i].Isexit = false;
}
}
}
}
代码效果:
当然其中有一些图片的素材,音乐素材,你们可以复制粘贴 自行替换,而我这里的素材以为CSDN 的一些原因无法上传,真需要的朋友,可以评论留言:向我所要的: 还有可以查看我的主页,其中有一些我在写该项目的一些问题的出现,以及解决方案:
最后:
限于自己的水平的原因:其中的错误,不足,希望大家多多给予指教:韩信点兵——多多益善,谢谢大家!