基于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;
}

示例视频:

由视频可见,一个基本的飞机大战游戏已经成功设计了,不过在画面上可以进行进一步的优化,玩法上可以自己增加机制提高游戏的趣味性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/782738.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器人运动控制

一、基础 1.1 矢量速度和旋转速度 矢量速度用来控制运动方向&#xff0c;任何一个方向都可以看成x、y、z三轴方向的合。单位规定是m/s。 旋转速度用来控制旋转方向&#xff0c;可以看成x、y、z三轴方向旋转的合。单位规定是pi/s。 速度消息包&#xff0c;可以在ROS Index上搜…

助力福建新型职业农民培育 北方天途推进无人机植保应用培训

为加强新型职业农民的职业培育&#xff0c;扩展新型农民的知识范围和专业技术水平&#xff0c;推进农业供给侧结构性改革。日前&#xff0c;在农业部门的大力支持下&#xff0c;北方天途航空和宁德天禾科技服务携手为福建省农民朋友开展了植保无人机驾驶员的应用培训。福建省农…

同步复位和异步复位的优缺点

同步复位 优点&#xff1a;能确保电路是100%的&#xff1b; 同步复位可以综合处更小的触发器&#xff1b; 可以保证复位只发生在有效时钟边沿&#xff0c;过滤掉复位信号毛刺&#xff1b; 内部逻辑产生的复位信号&#xff0c;采用同步复位可以有效过滤掉毛刺。 缺点&#xff1a…

网页布局案例 浮动

这里主要讲浮动 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><style>*{padding: 0;margin: 0;}.header{height: 40px;background-color: #333;}.nav{width: 1226px;heig…

深入理解数据结构(2):顺序表和链表详解

文章主题&#xff1a;顺序表和链表详解&#x1f331;所属专栏&#xff1a;深入理解数据结构&#x1f4d8;作者简介&#xff1a;更新有关深入理解数据结构知识的博主一枚&#xff0c;记录分享自己对数据结构的深入解读。&#x1f604;个人主页&#xff1a;[₽]的个人主页&#x…

单片机串口通过查询接收数据,同时具备接收超时、异常判断,常规通用处理算法实现

单片机串口通过查询接收数据,同时具备接收超时、异常判断,常规通用处理算法实现;1、实现过程 (1)初始化串口:首先,需要配置串口的基本参数,如波特率、数据位、停止位和校验位等。这通常涉及到GPIO引脚的配置(如PA2为发送引脚,PA3为接收引脚),以及USART的初始化。 …

Day38 动态规划

Day38 动态规划 509. 斐波那契数 我的思路&#xff1a; 很简单的递归 解答&#xff1a; class Solution {public int fib(int n) {if(n 0 || n 1) {return n;}return fib(n - 1) fib(n - 2);} }70. 爬楼梯 我的思路&#xff1a; 看了题解才明白本质上还是第一题的斐波那…

机器学习——降维算法-奇异值分解(SVD)

机器学习——降维算法-奇异值分解&#xff08;SVD&#xff09; 在机器学习中&#xff0c;降维是一种常见的数据预处理技术&#xff0c;用于减少数据集中特征的数量&#xff0c;同时保留数据集的主要信息。奇异值分解&#xff08;Singular Value Decomposition&#xff0c;简称…

csp资料

头文件 #include <bits/stdc.h> using namespace std isdigit(c); isalpha(c); switch(type){case value : 操作 } continue;//结束本轮循环 break;//结束所在的整个循环tips: //除法变乘法来算 //减法变加法 num1e42;//"1e4"表示10的4次方//用于移除容器中相…

某国投集团知识竞赛活动方案

一、抽签分组办法 1.抽签&#xff1a;参赛队伍赛前进行抽签分组。 2.分组&#xff1a;全部报名参赛队伍按照抽签顺序分为4组&#xff0c;每组7支队伍进行预赛&#xff0c;9月16日上午1、2组进行初赛&#xff0c;9月16日下午3、4组进行初赛。每组决出的前三名进入决赛。 二、初…

蓝桥杯2014年第十三届省赛真题-切面条

一、题目 切面条 一根高筋拉面&#xff0c;中间切一刀&#xff0c;可以得到2根面条。 如果先对折1次&#xff0c;中间切一刀&#xff0c;可以得到3根面条。 如果连续对折2次&#xff0c;中间切一刀&#xff0c;可以得到5根面条。 那么&#xff0c;连续对折10次&#xff0c;中间…

并查集进阶——带权并查集

带权并查集是在并查集的基础上加入数组来记录某些值&#xff0c;比如说当前家族的人数 原理也较简单&#xff0c;直接在合并时相加赋值就可以了&#xff0c;但是不要忘记初始化 例题一.合并家族 给定一个数n&#xff0c;代表总人数&#xff0c;一开始每个人自己是一家&#x…

二维码门楼牌管理应用平台建设:引领现代化小区管理新篇章

文章目录 前言一、二维码门楼牌管理应用平台概述二、三维动态单体化技术的优势三、二维码门楼牌管理应用平台的应用场景四、展望未来 前言 随着城市化的快速推进&#xff0c;现代化小区如雨后春笋般涌现&#xff0c;对小区管理的效率和智能化提出了更高要求。二维码门楼牌管理…

代码随想录Day39

Day 39 动态规划 part02 今日任务 62.不同路径 不同路径 II 代码实现 62.不同路径 public int uniquePaths(int m, int n) {if (m < 1 || n< 1) return 1;int[][] dp new int[m][n];for (int i 0; i < dp.length; i) {for (int j 0; j < dp[i].length; j) …

鸿蒙OS开发实例:【瀑布流式图片浏览】

介绍 瀑布流式展示图片文字&#xff0c;在当前产品设计中已非常常见&#xff0c;本篇将介绍关于WaterFlow的图片浏览场景&#xff0c;顺便集成Video控件&#xff0c;以提高实践的趣味性 准备 请参照[官方指导]&#xff0c;创建一个Demo工程&#xff0c;选择Stage模型熟读Har…

【算法】基数排序

简介 基数排序&#xff08;*Radix sort&#xff09;是一种非比较排序算法&#xff08;non-comparative sorting algorithm&#xff09;。现代计算机的基数排序算法由 计数排序 算法的开发人哈罗德H西华德&#xff08;Harold H. Seward&#xff09;于1954年于麻省理工大学开发。…

智能换气系统的设计与实现

智能换气系统的设计与实现 摘要&#xff1a; 随着现代家居对室内空气质量要求的日益提高&#xff0c;智能换气系统成为了确保室内环境舒适与健康的关键技术。本文详细探讨了智能换气系统的设计与实现过程&#xff0c;该系统结合了传感器技术、微控制器技术和智能控制算法&…

vue.router和vue.route

Vue Router 和 Vue Route 是 Vue.js 中用于构建单页面应用&#xff08;SPA&#xff09;路由系统的两个核心概念。Vue Router 是 Vue.js 的官方路由管理器&#xff0c;而 Vue Route 则是在 Vue 组件内部通过 $route 对象来访问当前路由的信息。 Vue Router 的使用 Vue Router …

图像分割论文阅读:Automatic Polyp Segmentation via Multi-scale Subtraction Network

这篇论文的主要内容是介绍了一种名为多尺度差值网络&#xff08;MSNet&#xff09;的自动息肉分割方法。 1&#xff0c;模型整体结构 整体结构包括编码器&#xff0c;解码器&#xff0c;编码器和解码器之间是多尺度差值模块模块&#xff08;MSM&#xff09;&#xff0c;以及一…

【前端】-

相对路径和绝对路径是描述文件位置的两种方式。 1. 相对路径&#xff1a;相对于自己的目标文件的位置&#xff0c;以引用文件之间网页所在位置为参考基础&#xff0c;而建立出的目录路径。因此&#xff0c;当保存于不同目录的网页引用同一个文件时&#xff0c;所使用的路径将不…