1 实验内容

本实验主要是实现简单的飞机大战游戏,包含游戏声音、碰撞后爆炸效果,有大小敌机等。所用到的知识点如下:

1.贴图技术

2.飞机类、子弹类实现

3.位图移动

4.碰撞判断,实现爆炸效果

5.插入声音

此实验的大概设计:游戏画面保持有一架大敌机,五架小敌机,一架战机,30颗子弹。如果子弹击落了敌机,那么敌机对象不会被delete,而仅仅是改变它的位置,让它重新从上面飞下,姑且可以叫做“假摧毁”吧。同理,子弹飞出界面或打到敌机,该子弹对象也不会被delete,而是从底部重新上升。击落敌机时会有爆炸效果;战机被敌机摧毁会有更大的爆炸效果,且游戏会停1秒再继续。

2 实验环境

win10+vs2015

3 实验步骤

3.1 添加游戏资源

从网上下载自己喜欢的飞机和子弹图片(.png文件),下载游戏背景音乐(.wav文件),把上述资源导入本工程的res文件,复制res文件到Debug文件中,这样便可以直接打开zsr_简单飞机大战.exe

打开res文件,可以看到下图(当然啦,飞机、子弹和游戏声音选你喜欢的就行啦,不用跟我的一样):

上图中倒数第二个黑色的飞机就是我的程序图标。

3.2 修改程序图标

点击[这里]了解一下。

3.3 设置类

右键‘项目’,点击‘添加类’,就可以添加类啦。本实验设置4个类:大敌机(DADIJI),小敌机(XIAODIJI),战机(ZHANJI),子弹(ZIDAN)。并且在类中实现贴图。

3.3.1 大敌机类(DADIJI)

添加大敌机类,类名为'DADIJI'。并在类中添加数据成员和成员函数,修改构造函数。具体如下:

//在类中加入:
CImage m_hero;//图片类对象
int diji_x;//图片横坐标
int diji_y;//图片轴坐标
void JIDRAW(CDC *cDC) { //设定大敌机的大小
m_hero.Draw(*cDC, diji_x, diji_y, 100, 50);//图片的宽为100,高50
} //修改构造函数
DADIJI::DADIJI()
{
//加载图片
CString imgPath = _T("res\\LXPlane.png");
m_hero.Load(imgPath);
//初始化大敌机的位置
diji_x = 300;
diji_y = 0;
}

3.3.2 小敌机类(XIAODIJI)

添加内容和大敌机类似,如下:

//类中加入:
CImage m_hero;
int diji_x;
int diji_y;
//设定小敌机的大小
void JIDRAW(CDC *cDC) {
m_hero.Draw(*cDC, diji_x, diji_y, 50,50); //小敌机宽50,高50
}
//修改构造函数:
XIAODIJI::XIAODIJI()
{
//加载图片
CString imgPath = _T("res\\BluePlane.png");
m_hero.Load(imgPath);
//设定小敌机的初始位置
diji_x = 30;
diji_y = 0;
}

3.3.3 战机类(ZHANJI)

修改内容和大敌机差不多。这里说明一下,我的战机位置也用了diji_x和diji_y来表示,其实为了代码的可读性,这里用zhanji_x和zhanji_y比较好。(但我比较懒,这里就不修改了。)具体改动的代码如下:

//在类中加入:
CImage m_hero;
int diji_x;
int diji_y;
CImage m_hero1;
//设定战机的大小
void JIDRAW(CDC *cDC) {
m_hero.Draw(*cDC, diji_x, diji_y, 80, 80);
}
//加入爆炸效果函数
void JIDRAW1(CDC *cDC, int x, int y) {
m_hero1.Draw(*cDC, x, y, 100, 100);//战机被敌机碰撞将变成爆炸状
}
//修改构造函数:
ZHANJI::ZHANJI()
{
//加载战机图片
CString imgPath = _T("res\\XPlane.png");
m_hero.Load(imgPath);
//加载爆炸图片
CString imgPath1 = _T("res\\ZHANJIBAOZHA.png");
m_hero1.Load(imgPath1);
//设定战机的初始位置
diji_x = 330;
diji_y = 500;
}

3.3.4 子弹类(ZIDAN)

这里的解释,和战机类的解释一样。具体代码如下:

//在类中加入:
CImage m_hero;
CImage m_hero1;
int diji_x;
int diji_y
//设置子弹的大小;
void JIDRAW(CDC *cDC) {
m_hero.Draw(*cDC, diji_x, diji_y, 20, 20);
}
//设置爆炸效果
void JIDRAW1(CDC *cDC,int x,int y) {
m_hero1.Draw(*cDC, x, y, 50, 50);//子弹碰到敌机,将会变成爆炸状
}
修改构造函数:
ZIDAN::ZIDAN()
{
//加载子弹图片
CString imgPath = _T("res\\zidan.png");
m_hero.Load(imgPath);
//加载爆炸图片
CString imgPath1 = _T("res\\baozha.png");
m_hero1.Load(imgPath1);
设定子弹初始位置
diji_x = 320;
diji_y = 600;
}

3.4 游戏重要变量

//在view类中加入下面变量:
DADIJI DA1;//大敌机1台
XIAODIJI XIAO1[5];//保持游戏界面有小敌机5台
ZIDAN ZI[30];//保持游戏界面有子弹30颗
ZHANJI ZHAN;//战机一台

3.5 设计游戏开始界面

//修改view中的Oncreat()函数,如下:
int Czsr_简单飞机大战View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1; // TODO: 在此添加您专用的创建代码
PlaySound(_T("res\\youxi.wav"), NULL, SND_FILENAME | SND_ASYNC|SND_LOOP);//循环播放背景音乐
this->SetTimer(1, 100, NULL);//设置一个定时器
int x_num = 30;
for (int j3 = 0;j3 < 5;j3++)
{
XIAO1[j3].diji_x += x_num;//开始时,小飞机的横坐标相隔30
x_num += 30;
XIAO1[j3].diji_y -= x_num;//开始时,小飞机的纵坐标相隔30,起到延迟出现的效果
} int num = 0;
for (int j2 = 0;j2 < 30;j2++)
{
ZI[j2].diji_y-= num;//开始时,子弹的纵坐标相隔25,起到延迟出现的效果
ZI[j2].diji_x = ZHAN.diji_x+30;//子弹的横坐标在战机的正中间
num += 25;
;
} return 0;
}

3.6 位图移动和碰撞

看到3.5的修改中已经设置了一个计时器,这里响应Ontimer()函数,如下:

//设计ontimer()函数(如下):
void Czsr_简单飞机大战View::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值 CDC *cDC = this->GetDC(); //获得当前窗口的DC
GetClientRect(&m_client); //获得窗口的尺寸
CRect rect;
GetClientRect(rect);
cDC->FillSolidRect(rect, RGB(255, 255, 255)); ZHAN.JIDRAW(cDC);//画战机 //子弹
for (int j1 = 0;j1 < 30;j1++)
{
if (ZI[j1].diji_x < DA1.diji_x+100&& ZI[j1].diji_x >DA1.diji_x - 100&&ZI[j1].diji_y < DA1.diji_y+50&& ZI[j1].diji_y >DA1.diji_y - 50)//判断子弹是否和大战机碰撞
{
int xx = DA1.diji_x;
int yy = DA1.diji_y;
ZI[j1].JIDRAW1(cDC,xx,yy );//若两者产生碰撞,则出现爆炸效果
ZI[j1].diji_y = ZHAN.diji_y;
ZI[j1].diji_x = ZHAN.diji_x + 30;//发生爆炸的子弹,重新回到战机的子弹口
DA1.diji_x = rand() % 400; //大敌机从上面的随机位置重新出现
while (DA1.diji_x<20)
DA1.diji_x = rand() % 400;
DA1.diji_y = 0;
}
else if (ZI[j1].diji_y < 0)//如果子弹飞到最高处,重回战机子弹口
{
ZI[j1].diji_y = ZHAN.diji_y;
ZI[j1].diji_x = ZHAN.diji_x + 30;
}
else
ZI[j1].diji_y = ZI[j1].diji_y-10;//否则,继续上升
for (int i1 = 0;i1 < 5;i1++)
{
if (ZI[j1].diji_x < XIAO1[i1].diji_x + 50 && ZI[j1].diji_x >XIAO1[i1].diji_x - 50 && ZI[j1].diji_y <XIAO1[i1].diji_y + 50 && ZI[j1].diji_y >XIAO1[i1].diji_y - 50)//判断每台小敌机是否和子弹碰撞
{
int xx1 = XIAO1[i1].diji_x;
int yy1 = XIAO1[i1].diji_y;
XIAO1[i1].diji_x = rand() % 400;//若碰撞,小敌机重新从上面的随机位置降落
while (XIAO1[i1].diji_x<20)
XIAO1[i1].diji_x = rand() % 400;
XIAO1[i1].diji_y = -30; ZI[j1].JIDRAW1(cDC, xx1, yy1);//爆炸状态
ZI[j1].diji_y = ZHAN.diji_y;
ZI[j1].diji_x = ZHAN.diji_x + 30;//子弹重新回到战机子弹口
}
}
ZI[j1].JIDRAW(cDC);//画子弹
} //小敌机
for (int j = 0;j < 5;j++)
{
if (ZHAN.diji_x < XIAO1[j].diji_x + 50 && ZHAN.diji_x >XIAO1[j].diji_x -50 && ZHAN.diji_y < XIAO1[j].diji_y + 50 && ZHAN.diji_y >XIAO1[j].diji_y - 50)//判断战机是否和小战机碰撞
{
int xxx = ZHAN.diji_x;
int yyy = ZHAN.diji_y;
ZHAN.JIDRAW1(cDC, xxx, yyy);//若碰撞,发生战机爆炸
Sleep(500);//停止500ms
XIAO1[j].diji_x = rand() % 400;
while (DA1.diji_x<20)
XIAO1[j].diji_x = rand() % 400;//小敌机重新随机降落
DA1.diji_y = 0;
ZHAN.diji_x = 300;
ZHAN.diji_y = 500;//战机回到初始位置
}
else if (XIAO1[j].diji_y > 690)//若小敌机走出游戏界面,则重新随机降落
{
XIAO1[j].diji_x = rand() % 400;
while(XIAO1[j].diji_x<20)
XIAO1[j].diji_x = rand() % 400;
XIAO1[j].diji_y = 0;
}
XIAO1[j].diji_y += 10;//小战机下降
XIAO1[j].JIDRAW(cDC);
} //大敌机
if (ZHAN.diji_x < DA1.diji_x + 100 && ZHAN.diji_x >DA1.diji_x - 100 && ZHAN.diji_y < DA1.diji_y + 80 && ZHAN.diji_y >DA1.diji_y - 80)//判断战机是否和大敌机发生碰撞
{
int xxx = ZHAN.diji_x;
int yyy = ZHAN.diji_y;
ZHAN.JIDRAW1(cDC, xxx, yyy);//若碰撞,战机爆炸,大敌机重新随机降落
Sleep(500);//停止500ms
DA1.diji_x = rand() % 400;
while (DA1.diji_x<20)
DA1.diji_x = rand() % 400;
DA1.diji_y = 0;
ZHAN.diji_x = 300;//战机回到初始位置
ZHAN.diji_y = 500;
}
if (DA1.diji_y < 650)//大敌机下降
DA1.diji_y = DA1.diji_y + 10;
else
DA1.diji_y = 0;//若大飞机飞出游戏界面 ,重新随机降落
DA1.JIDRAW(cDC); //画大敌机
ReleaseDC(cDC); CView::OnTimer(nIDEvent);
}

3.7 战机移动

为方便,这里的战机只能左右移动。下面响应一个键盘左右键的函数:

void Czsr_简单飞机大战View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (nChar == 37)//向左移
{
if (ZHAN.diji_x > 0)
ZHAN.diji_x -= 10;
} else
{
if (nChar == 39)//向右移
if (ZHAN.diji_x <450)
ZHAN.diji_x += 10;
} CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

3.8 删除状态栏

在框架类的OnCreate()函数中删除响应代码即可。

3.9  删除菜单栏,固定窗口大小

修改框架类的PreCreateWindow()函数:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式 //zsr,删除菜单项
cs.hMenu = NULL;
//禁止改变窗口大小
cs.dwExStyle &= ~WS_EX_CLIENTEDGE; cs.style &= ~WS_MAXIMIZEBOX; //禁止窗口最大化 cs.style &= ~WS_MINIMIZEBOX; //禁止窗口最小化 cs.style &= ~WS_THICKFRAME;//使窗口不能用鼠标改变大小 return TRUE;
}

4 游戏展示

初始样式                                                                    游戏中

小敌机爆炸                                                                 大敌机、战机爆炸

5 总结

这个实验太过简单,飞机数量已经固定且没有计分功能。

MFC实现简单飞机大战(含游戏声音)的更多相关文章

  1. canvas绘制“飞机大战”小游戏,真香!

    canvas是ArkUI开发框架里的画布组件,常用于自定义绘制图形.因为其轻量.灵活.高效等优点,被广泛应用于UI界面开发中. 本期,我们将为大家介绍canvas组件的使用. 一.canvas介绍 1 ...

  2. android:怎样用一天时间,写出“飞机大战”这种游戏!(无框架-SurfaceView绘制)

    序言作为一个android开发人员,时常想开发一个小游戏娱乐一下大家,今天就说说,我是怎么样一天写出一个简单的"飞机大战"的. 体验地址:http://www.wandoujia. ...

  3. [知了堂学习笔记]_纯JS制作《飞机大战》游戏_第1讲(实现思路与游戏界面的实现)

    整体效果展示: 一.实现思路 如图,这是我完成该项目的一个逻辑图,也是一个功能模块完成的顺序图. 游戏界面的完成 英雄飞机对象实现,在实现发射子弹方法过程中,又引出了子弹对象并实现.在此时,英雄飞机能 ...

  4. 用面向对象的编程方式实现飞机大战小游戏,java版

    概述 本文将使用java语言以面向对象的编程方式一步一步实现飞机大战这个小游戏 本篇文章仅供参考,如有写的不好的地方或者各位读者哪里没看懂可以在评论区给我留言 或者邮件8274551712@qq.co ...

  5. IOS学习之路五(SpriteKit 开发飞机大战小游戏一)

    参考SpriteKit 创建游戏的教程今天自己动手做了一下,现在记录一下自己怎么做的,今天之做了第一步,一共有三个部分. 第一步,项目搭建. 项目所用图片资源:点击打开链接 1.在Xcode打开之后, ...

  6. [知了堂学习笔记]_纯JS制作《飞机大战》游戏_第2讲(对象的实现及全局变量的定义)

    整体展示: 一.全局变量 /*===================玩家参数==========================*/ var myPlane; //英雄对象 var leftbtn = ...

  7. docker项目——搭建飞机大战小游戏

    项目2:搭建打飞机小游戏,验证数据持久化(最底下有链接) 第一步:拉取镜像 [root@localhost docker-image]# docker load < httpd_img.tar. ...

  8. [知了堂学习笔记]_纯JS制作《飞机大战》游戏_第3讲(逻辑方法的实现)

    整体展示: 上一讲实现了诸多对象,这次我们就需要实现许多逻辑方法,如控制飞机移动,判断子弹击中敌机,敌机与英雄飞机相撞等等.并且我们在实现这些功能的时候需要计时器去调用这些方法.setInterval ...

  9. javascript飞机大战-----009游戏结束

    /* 游戏引擎 */ var Engine = { //刚开始的游戏状态 gameStatus:false, //所以敌机 enemy:{}, //子弹 bullet:{}, //得分 scroe:0 ...

随机推荐

  1. Ubuntu下修改tomcat6默认的8080端口

    $ sudo vi /etc/tomcat6/server.xml   将 <Connector port="8080" protocol="HTTP/1.1&qu ...

  2. 推广Facebook技巧

    1.创建有吸引力的内容发布多样化的内容,包括图片,状态更新,视频,投票等.可以问你的粉丝一些问题让他们提供答案.这些内容不仅你的粉丝可以看到,它们还将会出现在你粉丝的个人动态栏,所以他们的朋友也是可以 ...

  3. 在Linux系统上查看Apache服务器的错误日志

    错误日志和访问日志文件为系统管理员提供了有用的信息,比如,为 Web 服务器排障,保护系统不受各种各样的恶意活动侵犯,或者只是进行各种各样的分析以监控 HTTP 服务器.根据你 Web 服务器配置的不 ...

  4. ORACLE完整安装过程

    安装 oracle, 主要是, 先确认系统资源, 再安装 oracle 软件, 最后按照 oracle 数据库 如果是使用 dbca 来安装数据库, 那么不需要自己创建文件夹.( 用来安装oracle ...

  5. freemarker 超出字符用省略号表示

    <#if x.content?length lt 200> ${x.content} <#else> ${x.content[0..201]}... </#if>

  6. 用dnSpy破解某旅游系统5.2版。

    某系统是网上最常见也是目前最好用的旅游站系统之一,5.1版本之前采用的maxtocode加壳后可以用de4dot反混淆后破解.5.1版本以后用de4dot无法脱壳. 本文仅限学习和讨论,请勿做侵权使用 ...

  7. ABP中连接已有数据库执行Sql或存储过程

    一:在EntityFramework项目中创建类如:ZSWDbContext. public class ZSWDbContext : AbpDbContext { public ZSWDbConte ...

  8. 利用jsonrpc技术包装uiautomator

    昨天一天在网上搜索解决上一篇文章中的exception: monkeyrunner内置uiautomator出错的原因 尽管没找到解决办法.可是让我无意中发现了一个好工具,比sl4a更好用的工具.直接 ...

  9. iOS企业开发In House ipa发布流程

    这两天需要发布一个ipa放到网上供其他人安装,需要用到企业级开发者账号.在网上查了一下资料,感觉没有一个比较完善的流程,于是决定把整个流程写下来,供大家参考. 首先详细说明一下我们的目标,我们需要发布 ...

  10. Instagram发布动态自动裁剪照片说明

    发布Ins时,照片总是被截取一截,感觉很不爽...然后就仔细了解了Ins是如何限制图片大小的. 官方帮助说的很清楚,https://help.instagram.com/163182164042672 ...