基于easyx库的C/C++游戏编程实例-飞机大战
飞机大战游戏设计
首先创建飞机/子弹结构:
struct Plane
{int x;int y;bool live;int width;int height;int type;int hp;
}player,bul[BUL_NUM],enemy[ENE_NUM];
你需要加载图片:
void ImageLoad()
{//背景loadimage(&bg[0], "./image/飞机大战bg.png");loadimage(&bg[1], "./image/Background.png");loadimage(&bg[2], "./image/restart.png");//飞机loadimage(&img_player[0], "./image/Plane1.png");loadimage(&img_player[1], "./image/Plane2.png");//子弹loadimage(&img_bullet[0], "./image/Bullet1.png");loadimage(&img_bullet[1], "./image/Bullet2.png");//敌机loadimage(&img_enemy[0][0], "./image/enemy_small1.png");loadimage(&img_enemy[0][1], "./image/enemy_small2.png");loadimage(&img_enemy[1][0], "./image/enemy_big1.png");loadimage(&img_enemy[1][1], "./image/enemy_big2.png");
}
游戏初始化设置:
void GameInit()
{//创建一个窗口,控制窗口台是自动创建的,图形窗口是需要自己手动创建的(后加 SHOWCONSOLE)initgraph(WIDTH, HEIGHT );//飞机初始状态player.x = WIDTH / 2-53;player.y = HEIGHT - 130;player.live = true;//子弹初始状态for (int i = 0; i < BUL_NUM; i++){bul[i].live = false;}//敌机初始状态for (int i = 0; i < ENE_NUM; i++){enemy[i].live = false;EnemyType(i);}//游戏初始界面ImageLoad();putimage(0, 0, &bg[0]);setbkmode(TRANSPARENT);//设置透明背景settextcolor(YELLOW);settextstyle(60, 0, "黑体");char begin[] = { "打飞机" };outtextxy(WIDTH / 3, HEIGHT / 4, begin);settextstyle(20, 0, "黑体");char b[] = { "按“B”开始游戏" };outtextxy(WIDTH / 3, HEIGHT / 2+50, b);while (!GetAsyncKeyState('B'));
}
游戏界面加载:
游戏界面加载
void GameDraw()
{//双缓冲绘图BeginBatchDraw();//加载图片ImageLoad();//背景putimage(0, 0, &bg[1]);//飞机putimage(player.x, player.y , &img_player[0],NOTSRCERASE);//先贴透明图putimage(player.x, player.y, &img_player[1],SRCINVERT);//子弹for (int i = 0; i < BUL_NUM; i++){if (bul[i].live){putimage(bul[i].x, bul[i].y, &img_bullet[0], NOTSRCERASE);//先贴透明图putimage(bul[i].x, bul[i].y, &img_bullet[1], SRCINVERT);}}//敌机for (int i = 0; i < ENE_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 //if (enemy[i].type == SMALL){putimage(enemy[i].x, enemy[i].y, &img_enemy[0][0], NOTSRCERASE);//先贴透明图putimage(enemy[i].x, enemy[i].y, &img_enemy[0][1], SRCINVERT);}}}//分数settextstyle(20, 0, "黑体");char str[] = { "当前分数:" };outtextxy(WIDTH-150, 10, str);char t[500];sprintf_s(t, "%d", score);outtextxy(WIDTH - 30, 10, t);EndBatchDraw();
}
随机一定比例地分配敌机类型:
void EnemyType(int i)
{int flag = rand() % 10;if (flag>=0&&flag<2){enemy[i].type = BIG;enemy[i].hp = 3;enemy[i].width = 86;enemy[i].height = 125;}else{enemy[i].type = SMALL;enemy[i].hp = 1;enemy[i].width = 71;enemy[i].height = 52;}
}
子弹发射配置:
void BulletCreate()
{for (int i = 0; i < BUL_NUM; i++){if (!bul[i].live){bul[i].x = player.x + 41;bul[i].y = player.y;bul[i].live = true;break;}}
}
子弹移动设置:
void BulletMove(int speed)
{for (int i = 0; i < BUL_NUM; i++){if (bul[i].live){bul[i].y -= speed;if (bul[i].y < 0){ bul[i].live = false;}}}
}
飞机移动和子弹发射控制:
void PlayerMove(int speed)
{
#if 0if (_kbhit()) //有按键按下返回真{char key = _getch(); //阻塞函数,不按下停住不执行switch (key){case 'w':case 'W':case 72:player.y -= speed;break;case 's':case 'S':case 80:player.y += speed;break;case 'a':case 'A':case 75:player.x -= speed;break;case 'd':case 'D':case 77:player.x += speed;break;}}
#elif 1//Windows函数, 非阻塞//按键大写可检测到大小写,小写都检测不到if (GetAsyncKeyState(VK_UP)|| GetAsyncKeyState('W')){if (player.y > 0){player.y -= speed;}}if (GetAsyncKeyState(VK_DOWN) | GetAsyncKeyState('S')){if (player.y < HEIGHT - 124){player.y += speed;}}if (GetAsyncKeyState(VK_LEFT) | GetAsyncKeyState('A')){if (player.x > 0){player.x -= speed;}}if (GetAsyncKeyState(VK_RIGHT) | GetAsyncKeyState('D')){if (player.x < WIDTH - 106){player.x += speed;} }
#endif // 0if (GetAsyncKeyState(VK_SPACE)&&Timer(100,0)){BulletCreate();}
}
随机位置产生一个敌机(敌机会重叠,未优化。可以利用坐标判断飞机之间是否重叠,不重叠则可以创建敌机,否则重新生成坐标进行循环):
void EnemyCreate()
{for (int i = 0; i < ENE_NUM; i++){if (!enemy[i].live){enemy[i].x = rand() % (WIDTH - 86);enemy[i].y = rand()%20;enemy[i].live = true;EnemyType(i);//printf("pos(%d,%d) %d %d\n", enemy[i].x, enemy[i].y, enemy[i].live, enemy[i].hp); //检测敌机状态,用于调试break;}}
}
敌机移动设置:
void EnemyMove(int speed)
{for (int i = 0; i < ENE_NUM; i++){if (enemy[i].live){enemy[i].y +=speed;if(enemy[i].y>HEIGHT){ enemy[i].live = false;}}}
}
敌机与子弹碰撞检测设置:
bool Bump()
{for (int i = 0; i < ENE_NUM; i++){if (!enemy[i].live)continue;for (int j = 0; j < BUL_NUM; j++){if (!bul[j].live)continue;if (bul[j].x + 12 > enemy[i].x && bul[j].x + 12 < enemy[i].x + enemy[i].width/2&& bul[j].y > enemy[i].y && bul[j].y < enemy[i].y + enemy[i].height/2){bul[j].live = false;enemy[i].hp--;}}if (enemy[i].hp <= 0){enemy[i].live = false;if (enemy[i].type == BIG){score += 3;}else if (enemy[i].type == SMALL){score++;} }if (player.x + 106/2 > enemy[i].x && player.x < enemy[i].x + enemy[i].width/2&& player.y > enemy[i].y && player.y < enemy[i].y + enemy[i].height/2){return false;}}return true; // 默认true,可不写
}
由于文件执行速度较快,需要加一定的延时,以便肉眼可见。
再着需要一个定时器,定时发射敌机:
bool Timer(int ms, int id)
{static DWORD t[TimerNum];if (clock() - t[id] > ms){t[id] = clock();return true;}return false;
}
执行主函数:
int main()
{srand((unsigned int)time(NULL)); //让随机数每次进入时都不同,只调用一次!!!GameInit();while (1){while (1){//Sleep(1); //可以让速度更慢GameDraw();PlayerMove(3);BulletMove(5);if (Timer(300, 1)){EnemyCreate();}if (Timer(10, 2)){EnemyMove(2);}FlushBatchDraw();if (!Bump())break;//printf("无人能挡,所向披靡"); //用于阻塞测试}settextcolor(RED);settextstyle(70, 0, "黑体");char end[] = { "GAME OVER!" };outtextxy(WIDTH / 6, HEIGHT / 3, end);settextstyle(40, 0, "黑体");char b[] = { "按“V”重新开始游戏" };outtextxy(WIDTH / 6, HEIGHT / 2, b);while (!GetAsyncKeyState('V'));GameInit();}return 0;
}
示例视频:
由视频可见,一个基本的飞机大战游戏已经成功设计了,不过在画面上可以进行进一步的优化,玩法上可以自己增加机制提高游戏的趣味性。
相关文章:
基于easyx库的C/C++游戏编程实例-飞机大战
飞机大战游戏设计 首先创建飞机/子弹结构: struct Plane {int x;int y;bool live;int width;int height;int type;int hp; }player,bul[BUL_NUM],enemy[ENE_NUM];你需要加载图片: void ImageLoad() {//背景loadimage(&bg[0], "./image/飞机大…...

stitcher类实现多图自动拼接
效果展示 第一组: 第二组: 第三组: 第四组: 运行代码 import os import sys import cv2 import numpy as npdef Stitch(imgs,savePath): stitcher cv2.Stitcher.create(cv2.Stitcher_PANORAMA)(result, pano) stitcher.st…...
Ubuntu下udp通信
一、知识准备阶段 socket是什么?套接字是什么? https://blog.csdn.net/m0_37925202/article/details/80286946 Socket程序从Windows移植到Linux下的一些注意事项 sockaddr和sockaddr_in详解 bzero和memset函数 函数原型:void bzero&…...

拌合楼管理软件开发(十三) 对接耀华XK3190-A9地磅(实战篇)
前言: 实战开整 目前而言对于整个拌合楼管理软件开发,因为公司对这个项目还处于讨论中,包括个人对其中的商业逻辑也存在一些质疑,都是在做一些技术上的储备.很早就写好了串口与地磅对接获取代码,也大概知道真个逻辑,这次刚好跟库区沟通,远程连接到磅房电脑,开始实操一下. 一、地…...
FastAPI+React全栈开发10 MongoDB聚合查询
Chapter02 Setting Up the Document Store with MongoDB 10 Aggregation framework FastAPIReact全栈开发10 MongoDB聚合查询 In the following pages, we will try to provide a brief introducton to the MongoDB aggregation framework, what it is, what benefits it of…...
python 报错问题汇总
error: [WinError 32] 另一个程序正在使用此文件,进程无法访问。: d:\\anaconda\\envs\\yolov5\\lib\\site-packages\\ISR-2.2.0-py3.7.egg 解决方法:重启pycharm python-contrib 无法安装 opencv-contrib-python 安装包网址:安装包下载链接…...

6.5物联网RK3399项目开发实录-驱动开发之LCD显示屏使用(wulianjishu666)
90款行业常用传感器单片机程序及资料【stm32,stc89c52,arduino适用】 链接:https://pan.baidu.com/s/1M3u8lcznKuXfN8NRoLYtTA?pwdc53f LCD使用 简介 AIO-3399J开发板外置了两个LCD屏接口,一个是EDP,一个是LVDS,接口对应板…...

「Android高级工程师」BAT大厂面试基础题集合-下-Github标星6-5K
C、 com.android.provider.contact D、 com.android.provider.contacts 11.下面关于ContentProvider描述错误的是()。 A、 ContentProvider可以暴露数据 B、 ContentProvider用于实现跨程序共享数据 C、 ContentProvider不是四大组件 D、 ContentP…...
【算法】基数排序
简介 基数排序(*Radix sort)是一种非比较排序算法(non-comparative sorting algorithm)。现代计算机的基数排序算法由 计数排序 算法的开发人哈罗德H西华德(Harold H. Seward)于1954年于麻省理工大学开发。…...

2核2G服务器优惠价格轻量61元一年,CVM价格313元15个月
腾讯云2核2G服务器多少钱一年?轻量服务器61元一年,CVM 2核2G S5服务器313.2元15个月,轻量2核2G3M带宽、40系统盘,云服务器CVM S5实例是2核2G、50G系统盘。腾讯云2核2G服务器优惠活动 txybk.com/go/txy 链接打开如下图:…...

不同Python版本和wxPython版本用pyinstaller打包文件大小对比
1、确定wxPython和Python版本的对应关系 在这里可以找到Python支持的所有wxPython版本:https://pypi.tuna.tsinghua.edu.cn/simple/wxpython/ 由于Python从3.6版本开始支持f字符串、从3.9版本开始不支持Windows7操作系统,所以我仅筛选3.6-3.8之间的版本…...

【C语言】结构体详解(一)
目录 1、什么是结构体? 2、结构体成分 3、结构体变量的定义与初始化 3.1、结构体变量的三种定义方式 3.2、结构体变量的初始化 4、结构体成员的访问(两种方式) 4.1、直接访问 4.2、间接访问 5、结构的特殊声明 5.1、不完全声明(匿…...

AI时代-普通人的AI绘画工具对比(Midjouney与Stable Diffusion)
AI时代-普通人的AI绘画工具对比(Midjouney与Stable Diffusion) 前言1、基础对比Stable Diffusion(SD)SD界面安装与使用SD Midjouney(MJ) 2、硬件与运行要求对比Stable Diffusion硬件要求内存硬盘显卡 Midjo…...

【蓝桥杯】矩阵快速幂
一.快速幂概述 1.引例 1)题目描述: 求A^B的最后三位数表示的整数,A^B表示:A的B次方。 2)思路: 一般的思路是:求出A的B次幂,再取结果的最后三位数。但是由于计算机能够表示的数字…...

C语言使用STM32开发板手搓高端家居洗衣机
目录 概要 成品效果 背景概述 1.开发环境 2.主要传感器。 技术细节 1. 用户如何知道选择了何种功能 2.启动后如何进行洗衣 3.如何将洗衣机状态上传至服务器并通过APP查看 4.洗衣过程、可燃气检测、OLED屏显示、服务器通信如何并发进行 小结 概要 本文章主要是讲解如…...

【Hello,PyQt】QTextEdit和QSplider
PyQt5 是一个强大的Python库,用于创建图形用户界面(GUI)。其中,QTextEdit 控件作为一个灵活多用的组件,常用于显示和编辑多行文本内容,支持丰富的格式设置和文本操作功能。另外,QSlider 控件是一…...
【力扣】191.位 1 的个数、485.最大连续 1 的个数
191.位 1 的个数 题目描述 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中 设置位 的个数(也被称为汉明重量)。 示例 1: 输入:n 11 输出࿱…...

蓝桥杯 java 承压计算
题目: 思路: 1:其中的数字代表金属块的重量(计量单位较大) 说明每个数字后面不一定有多少个0 2:假设每块原料的重量都十分精确地平均落在下方的两个金属块上,最后,所有的金属块的重量都严格精确地平分落在最底层的电子…...
leetcode268-Missing Number
这道题目要求缺失的数字,一般解决数组的问题,要么往排序数组,要么往双指针遍历这些方向上靠,要么往异或方向上靠,总之落点无非就只有这几个。我们要求缺失的数字,可以依次让1~n和数组元素进行异…...

【jenkins+cmake+svn管理c++项目】jenkins回传文件到svn(windows)
书接上文:创建一个项目 在经过cmakemsbuild顺利生成动态库之后,考虑到我一个项目可能会生成多个动态库,它们分散在build内的不同文件夹,我希望能将它们收拢到一个文件夹下,并将其回传到svn。 一、动态库移位—cmake实…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...