提示:该项目需要使用EasyX 图形库

文章目录

  • 前言
  • 〇、效果展示
  • 一、准备工作
  • 二、具体步骤
    • 1.包含头文件
    • 2.枚举变量
    • 3.飞机属性
  • 三、问题剖析
    • 问题1:战机怎么创建?战机怎么移动?
    • 问题2:战机如何发子弹,子弹的移动?
    • 问题3:敌机创建和移动?
    • 问题4:碰撞处理方式?
    • 问题5:整个游戏的逻辑是什么样的?
    • 问题6:什么是定时器?
  • 四、奉上源码
  • 五、拓展

前言

提示:本文主要作为自己之前学习C++的总结,顺便做一个游戏小项目,加深数组、循环、结构体的一些的理解


〇、效果展示

一、准备工作

  1. 下载 Easyx ,这个比较简单,直接跳过
  2. 准备素材资源,飞机,敌机,子弹,背景

二、具体步骤

1.包含头文件

2.枚举变量

提示:这个步骤也可以使用宏替换

3.飞机属性

三、问题剖析

问题1:战机怎么创建?战机怎么移动?

Easyx 有 loadimage 加载图片,注意这只是把图片加载到内存中,还没并没有画出来


至于移动的处理,可以采用事件监听

问题2:战机如何发子弹,子弹的移动?

战机的子弹,首先绘制子弹和战机一样,发送子弹可以监听空格键


提示:子弹我用一个数组保存起来,这个数组大小N,N的意思就是在屏幕中最多能出现N个子弹,因为我们绘制子弹的时候,首先去判断子弹是否存在,如果只用一个变量保存,那么屏幕中永远只有一颗子弹,这不符合常理

子弹这个逻辑比较难,如果不懂,可以看看下面的图

我们再来看看这个图,就应该明白了

这样子弹就被节能的利用起来了,而不是一直向内存索要资源去创建

子弹的移动就很简单了,先去判断它是否存在,如果存在则 y-=1

问题3:敌机创建和移动?

敌机也不可能只有一辆,所以用数组保存起来,其原理和子弹一样


敌机移动和子弹一样,比较简单,只要一直 y+=1 就行了

问题4:碰撞处理方式?

这个碰撞方式也比较简单,看图就明白了

当然如果想更加严格的话,就需要细心去处理,当然这个碰撞比较简单粗暴

问题5:整个游戏的逻辑是什么样的?

问题6:什么是定时器?

来了,定时器是啥?

通俗来讲,就是某一个周期去执行一个任务,或者到某一个时间去执行任务

为什么要使用定时器,在创建敌机的时候,如果不用定时器,那么所有的战机会被一起创建出来,这是不合理的,所以我们给一个周期,比如每 500ms 去创建一个,这样游戏体验比较好,敌人是源源不断的来,而不是一股脑的倾巢而出

封装定时器

以上就是本章全部问题了

四、奉上源码

头文件 flane.h

#pragma once
#include <iostream>
#include <graphics.h>
#include <conio.h>
#include <time.h>
#pragma comment (lib, "Winmm.lib")//导入Winmm.lib库enum my{WIDTH = 591,     // 窗口宽度HEIGHT = 664,       // 窗口高度BULLLET_NUM = 1,    // 子弹数量ENEMY_NUM = 15,     // 敌机数量BIG,             // 敌机类型大SMALL,              // 敌机类型小
};// 飞机、子弹状态
struct Plance{int x;        // x 坐标int y;       // y 坐标bool live;   // 是否存活int width;   // 飞机宽度int height;  // 飞机高度int hp;      // 血量值int type; // 敌机类型
};void loadImg();                   //加载资源
bool Timer(size_t ms, int id);  //定时器
void enemyHp(int i);            //敌机生命值
void gameInit();                //游戏初始化
void  createBullet();           //创建子弹
void createEnemy();             //创建敌机
void enemyMove();               //敌机移动
void bulletMove();              //子弹移动
void gameDraw();                //游戏图片绘制
void playerMove(int speed);     //监听角色移动
void playPlance();              //碰撞检测
void startGame();               //启动游戏

功能文件function.cpp

#include "flane.h"
IMAGE bk;               //背景资源
IMAGE img_role[2];      //战机图片
IMAGE img_bull[2];      //子弹图片
IMAGE img_enemy[2][2];  //敌机图片
struct Plance player, bull[BULLLET_NUM], enemy[ENEMY_NUM];void loadImg(){loadimage(&bk, "./images/background.jpg");loadimage(&img_role[0], "./images/planeNormal_1.jpg");loadimage(&img_role[1], "./images/planeNormal_2.jpg");loadimage(&img_bull[0], "./images/bullet1.jpg");loadimage(&img_bull[1], "./images/bullet2.jpg");//加载敌机图片loadimage(&img_enemy[0][0], "./images/enemy_1.jpg");loadimage(&img_enemy[0][1], "./images/enemy_2.jpg");loadimage(&img_enemy[1][0], "./images/enemyPlane1.jpg");loadimage(&img_enemy[1][1], "./images/enemyPlane2.jpg");mciSendString("open \"./images/game_music.mp3\" alias mymusic", NULL, 0, NULL);mciSendString("play mymusic repeat", NULL, 0, NULL);}bool Timer(size_t ms, int id){static DWORD t[10];if (clock() - t[id] > ms){t[id] = clock();return true;}return false;
}void enemyHp(int i){if (rand() % 10 == 0){enemy[i].type = BIG;enemy[i].hp = 3;enemy[i].width = 104;enemy[i].height = 148;}else{enemy[i].type = SMALL;enemy[i].hp = 1;enemy[i].width = 52;enemy[i].height = 39;}
}
void gameInit(){initgraph(WIDTH, HEIGHT, EW_SHOWCONSOLE);   // 创建游戏窗口srand((int)time(NULL)); // 随机种子HWND hWnd = GetHWnd(); // 获取窗口句柄SetWindowText(hWnd, "飞机大战"); // 设置标题loadImg(); // 加载资源player.x = WIDTH / 2;player.y = HEIGHT - 120;player.live = true;// 初始化子弹for (size_t i = 0; i < BULLLET_NUM; ++i){bull[i].x = 0;bull[i].y = 0;bull[i].live = false;}// 初始化敌机for (size_t i = 0; i < ENEMY_NUM; ++i){enemy[i].live = false;enemyHp(i);}
}void  createBullet(){for (size_t i = 0; i < BULLLET_NUM; ++i){if (!bull[i].live){bull[i].x = player.x + 45;bull[i].y = player.y - 10;bull[i].live = true;break;}}
}void createEnemy(){for (size_t i = 0; i < ENEMY_NUM; ++i){if (!enemy[i].live){enemy[i].x = rand() % (WIDTH - 104);enemy[i].y = 0;enemy[i].live = true;enemyHp(i);break;}}
}void enemyMove(){for (size_t i = 0; i < ENEMY_NUM; ++i){if (enemy[i].live){enemy[i].y += 1;if (enemy[i].y > HEIGHT){enemy[i].live = false;}}}
}void bulletMove(){for (size_t i = 0; i < BULLLET_NUM; ++i){if (bull[i].live){bull[i].y -= 1;if (bull[i].y < 0){bull[i].live = false;}}}
}// 游戏图片绘制
void gameDraw(){putimage(0, 0, &bk);putimage(player.x, player.y, &img_role[0], NOTSRCERASE);putimage(player.x, player.y, &img_role[1], SRCINVERT);for (size_t i = 0; i < BULLLET_NUM; ++i){if (bull[i].live){putimage(bull[i].x, bull[i].y, &img_bull[0], NOTSRCERASE);putimage(bull[i].x, bull[i].y, &img_bull[1], SRCINVERT);}}for (size_t i = 0; i < ENEMY_NUM; ++i){if (enemy[i].live){if (enemy[i].type == BIG){putimage(enemy[i].x, enemy[i].y, &img_enemy[1][0], NOTSRCERASE);putimage(enemy[i].x, enemy[i].y, &img_enemy[1][1], SRCINVERT);}else{putimage(enemy[i].x, enemy[i].y, &img_enemy[0][0], NOTSRCERASE);putimage(enemy[i].x, enemy[i].y, &img_enemy[0][1], SRCINVERT);}}}
}// 角色移动
void playerMove(int speed){if (GetAsyncKeyState(VK_UP) || GetAsyncKeyState('W')){if (player.y > 0){player.y -= speed;}}else if (GetAsyncKeyState(VK_DOWN) || GetAsyncKeyState('S')){if (player.y + 60< HEIGHT){player.y += speed;}}else if (GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState('A')){if (player.x + 60> 0){player.x -= speed;}}else if (GetAsyncKeyState(VK_RIGHT) || GetAsyncKeyState('D')){if (player.x + 60< WIDTH){player.x += speed;}}if (GetAsyncKeyState(VK_SPACE) && Timer(100, 2)){createBullet();}}//  碰撞检测
void playPlance(){for (int i = 0; i < ENEMY_NUM; ++i){if (!enemy[i].live){continue;}//子弹for (int k = 0; k < BULLLET_NUM; ++k){if (!bull[i].live){continue;}// 碰撞检测if (bull[k].x >= enemy[i].x && bull[k].x <= enemy[i].x + enemy[i].width&&  bull[k].y >= enemy[i].y && bull[k].y <= enemy[i].y + enemy[i].height){bull[k].live = false;enemy[i].hp -= 1;}}if (enemy[i].hp <= 0){enemy[i].live = false;}}
}void startGame(){gameInit();BeginBatchDraw();//双缓冲绘图// 游戏主循环while (1){gameDraw();FlushBatchDraw();playerMove(1);bulletMove();if (Timer(500, 0)){createEnemy();}if (Timer(1, 1)){enemyMove();}playPlance();}EndBatchDraw();}

主程序 main.cpp

#include "flane.h"int main(){startGame();system("pause");return 0;
}

五、拓展

  1. 可以增加更大的难度,比如敌机也会发子弹
  2. 增加我方战机的分数
  3. 战机爆炸处理,加音效,敌机爆炸处理
  4. 记录数据保存在文件或数据库

提示:后期会采用 Python 重新写这个游戏,在 【Python 专栏里面】并且把拓展的内容增加进行,因为 C++ 这个图形处理库比较轻量,功能很少


素材资源下载 点这个=》GitHub

使用 C++ 开发出 【飞机大战】相关推荐

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

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

  2. [Unity3D]Unity3D游戏开发之飞机大战项目讲解

    大家好,我是秦元培,欢迎大家继续关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 首先感谢大家对我博客的关注,今天我想和大家分享的是一个飞机大战的项目.这是一个比较综合的 ...

  3. 用Unity快速开发太空飞机大战游戏实战经验分享(上)

    用unity动手先来试试一个简单的太空飞机大战吧.看官请继续往下... 最终效果,可控制己方战机,朝目标敌机发射子弹,打飞机~~~!伴随想象,慢慢呈现这个太空飞机大战游戏. 1. 新建打飞机unity ...

  4. Java窗口游戏开发,飞机大战,打飞机,打大飞机,打无敌飞机妙啊!!!!————————香啊~~~~~~~~~~~~~~~~~

    身无分文宅家,细发日渐稀疏. 双亲日益劳累,奈何无心寻工. 复试遥遥无期,心情惨惨戚戚. 若问此时作甚?抽烟喝酒扣叮.---杂记2020/3/25-2020/4/12 矫情下,莫认真 接下来奉上近日学 ...

  5. html5飞机大战小游戏开发,html5 飞机大战

    [实例简介]自定义飞机图片数量,子弹图片,速度 [实例截图] [核心代码] var canvas=document.getElementById("myCanvas"); var ...

  6. java飞机大战案例讲解_JAVA开发_飞机大战.pdf

    <Java 程序设计>实验报告 年级.专业.班级 2012 级物联网1 班 姓名 陈点 实验题目 飞行射击游戏 实验时间 2014/11/09-2014/11/13 实验地点 主教0410 ...

  7. Swing游戏开发——飞机大战

    本章讲解利用javax.swing包下的Swing技术来开发一个飞机大战. 完整源码:https://download.csdn.net/download/JavaFanHuman/12713192 ...

  8. Vue 开发一个简略版的飞机大战小游戏

    文章目录 使用 Vue 开发一个简略版的飞机大战小游戏 一.实现思路 二.所需知识点 三.实现步骤 使用 Vue 开发一个简略版的飞机大战小游戏 如题,假设你为了向更多访问你博客的人展示你的技术,你决 ...

  9. java飞机大战流程图_飞机大战说明文档

    JIANGXI AGRICULTURAL UNIVERSITY精彩内容,尽在百度攻略:https://gl.baidu.com 科技月月评设计报告 精彩内容,尽在百度攻略:https://gl.bai ...

  10. HTML+CSS+JS制作【飞机大战】小游戏(键盘版和鼠标版)

    文章目录 一.效果演示 设计思路 二.鼠标版飞机大战代码展示 1.HTML结构代码 2.CSS样式代码 3.JavaScript代码 js.js文件 plane.js文件 三.键盘版飞机大战代码展示 ...

最新文章

  1. wamp支持win10吗?怎么设置?
  2. Java学习笔记(八)--字符串生成器
  3. php text留言本,PHP+TEXT留言本(五)
  4. WordPress /wp-admin/includes/post.php user_ID 参数操作权限提升漏洞
  5. 01_Influxdb1.7.7的安装配置启动
  6. case class和trait
  7. 小米12 Ultra外观设计曝光:白色陶瓷机身 后置硕大相机模组
  8. 工程数学(数值分析)第二讲:非线性方程求根
  9. navtab触底 小程序_微信小程序TAB切换效果
  10. SDUT_经典线型DP
  11. java 删除文件夹及文件夹中的子文件
  12. [RL 13] VDN (201706, DeepMind)
  13. IBM 人工智能黑科技
  14. 甘超波:NLP理解层次
  15. 世界最早投入运行的计算机网络是,世界上最早投入运行的计算机网络是。
  16. 【优化求解】基于生物地理学结合重力引力搜索优化求解算法matlab代码
  17. 花了我一个晚上时间整理的Python魂斗罗小游戏源代码
  18. 采用计算机辅助数据收集,关于计算机在数据收集中的作用分析
  19. 《周鸿祎自述》新书发布会十大经典语录
  20. 悟空问答如何高效引流,这几个技巧让你上首页

热门文章

  1. 智慧工厂是什么 智慧工厂方案举例 智慧工厂案例
  2. 视频教程-图解Python编程神器Jupyter Notebook-Python
  3. 微信小程序系列一:获取头像昵称
  4. stimulsoft oracle,Stimulsoft Reports
  5. python flask上传Excel并把Excel的数据导入数据库
  6. 该网页无法正常运作解决方法
  7. 18、DQL(分页查询:limt)
  8. Mysql中,order by + limt的大坑
  9. 格兰杰因果( Granger causality test)在神经科学中脑区功能连接上的应用
  10. 9.2 react受控组件和非受控组件