900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 使用 C++ 开发出 【飞机大战】

使用 C++ 开发出 【飞机大战】

时间:2020-10-27 13:49:25

相关推荐

使用 C++ 开发出 【飞机大战】

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

文章目录

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

前言

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


〇、效果展示

一、准备工作

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

二、具体步骤

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

五、拓展

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

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

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。