C语言项目 天天酷跑(上篇)

前言

这里讲述这个天天酷跑是怎么实现的,我会在天天酷跑的下篇添加源代码,这里会讲述天天酷跑这个项目是如何实现的每一个思路,都是作者自己学习于别人的代码而创作的项目和思路,这个代码和网上有些许不一样,因为掺杂了作者的思路


建立一个窗口

我们要先安装EaxyX图库,安装到我们的开发工具里面去,这样我们才可以实现窗口的实现和图片的加载

这个头文件我们一定要调用,这样才可以实现我们一系列的EaxyX图库函数的实现,对于一个小型的项目设计,我们不可以全部都堆在main函数里面,要不然可读性极差,后面编写项目的时候,内容会很乱,我们也不好去查找错误,我们应该把每一个功能都分装到一个函数里面去,后者创建更多的cpp源文件来是实现多功能

窗口的设计

这里我们在main函数里面写一个init();函数,把所有的初始化分装到这个函数里面去,把窗口的长宽都用宏定义来定义,这样后面方便使用,还具有很高的可读性

根据以上,我们就有了

Main函数-----控制台函数

Init函数-----初始化函数

EaxyX图形库函数的学习

我们可以转到initgraph函数的定义来看里面的参数是什么

这里的参数HWND是一个是窗口句手柄(包括程序窗口,对话框,按钮等)都有一个唯一的标识符号,这个就是窗口句柄

参数:

Width 这个是窗口的宽            height 这个是窗口的高 

Flag:

作用:可以取不同的值来实现特定的功能或效果,常见的取值及作用如下:

0:默认模式,通常表示普通的图形显示模式,会创建一个标准的图形窗口,根据width和height指定的大小进行显示。

EW_SHOWCONSOLE:在创建图形窗口的同时显示控制台窗口。这对于在图形程序中需要同时在控制台输出调试信息或与用户进行命令行交互的情况非常有用。

EW_NOCLOSE:创建的图形窗口没有关闭按钮,用户无法通过点击关闭按钮来关闭窗口。这种模式通常用于需要限制用户对窗口关闭操作的特定应用场景

初始化背景

设计思路

我们在实现玩窗口的设置的时候,我们接下来的目的就是要把背景画出来,这就是初始化背景,但是我们要知道这个该怎么设计,我们角色是原地奔跑的,只要背景进行移动,我们就可以达到角色奔跑的效果,所以我们的代码就是要实现背景的挪动,我们可以近处的景色移动快一点,远处的移动的慢一点

这个是我们要实现的一个程序,我们分别把图片的右上角放到x为0,y为对应的位置即可,接下来这个就是我们的思路,我们用代码来实现一波

定义背景图的全局变量

这里我们就用这三个全局变量来存放背景图片,这里就以两个背景图片为例子

第一个为IMAGE类型的图片数组

第二个为存放背景的对于x的坐标

第三个为背景移动的速度,快的为远的物体,慢的为进的物体

初始化背景属性

我们有两个图片就是要实现两次的循环(init函数)

Name 数组:我们利用该数组来存放这个文件的名

Sprintf:这个是把我们输入的内容格式化,可以存放到char类型的数组里面

Loadimage:是把这个name的东西加载到这个imgbgs数组里面

然后初始化一下这个背景的X坐标为0,因为都是在0处,只需要改y即可

(如果想加全局变量的y不加x也是可以的,后面只需再putimage函数加上x)

加载图片的内容到窗口

Putimage是放置到窗口的特定位置,这里就是实现窗口放置图片

背景的奔跑

我们已经放置好图片在窗口处,我们这个时候就要实现图片的移动,我们就写一个run函数运行所有可以运动的东西

这里上面的srand函数是后面用的,这里不用看,我们按照我们的步骤走

我们需要执行两次循环,然后让图片向后面移动,由于我们执行的是一个小游戏,所以这个几毫秒是微乎其微的,不会影响我们的游戏的性能,注意我们是减不是加,因为我们背景往后面移动,我们的人才可以往前面跑动,我们的图片的长度设计应该为窗口长度的两倍,当这个图片运动到—长,那么我们就重置我们背景图片的位置

这样我们就可以实现一个背景的奔跑,利用死循环来不断是实现背景奔跑

目前为止我们实现了一下的函数

Main函数-----控制台函数

Init函数-----初始化函数

Updatebg-----更新背景函数

Run-----所有的运行程序函数

EaxyX图形库的函数学习

这里是loadimage函数参数

pDstImg保存图像的 IMAGE 对象指针。如果为 NULL,表示图片将读取至绘图窗口

(一般这个都是NULL,直接绘制到窗口里面)

pImgFile图片文件名。支持 bmp / gif / jpg / png / tif / emf / wmf / ico 格式的图片

gif 格式的图片仅加载第一帧;gif png 均不支持透明

(我们一般都是用pngjpg,但是图片在这个函数一直都是有一个bug,不可以重叠图片)

nWidth图片的拉伸宽度。加载图片后,会拉伸至该宽度。如果为 0,表示使用原图的宽度

nHeight图片的拉伸高度。加载图片后,会拉伸至该高度。如果为 0,表示使用原图的高度

bResize

是否调整 IMAGE 的大小以适应图片

void putimage(

   int dstX,           // 绘制位置的 x 坐标

   int dstY,           // 绘制位置的 y 坐标

   IMAGE *pSrcImg,        // 要绘制的 IMAGE 对象指针

   DWORD dwRop = SRCCOPY   // 三元光栅操作码

);

void putimage(

   int dstX,           // 绘制位置的 x 坐标

   int dstY,           // 绘制位置的 y 坐标

   int dstWidth,       // 绘制的宽度

   int dstHeight,         // 绘制的高度

   IMAGE *pSrcImg,        // 要绘制的 IMAGE 对象指针

   int srcX,           // 绘制内容在 IMAGE 对象中的左上角 x 坐标

   int srcY,           // 绘制内容在 IMAGE 对象中的左上角 y 坐标

   DWORD dwRop = SRCCOPY   // 三元光栅操作码

);

这里我们一般都是写出x和y的坐标,然后利用指针指向那个图片的位置,然后进行放置图片

实现角色的跑动

根据我们实现背景的步骤,我们就有了一个很清晰的认知

定义相关属性(全局变量)—>初始化相关属性(init)-->加载相关图片(update…)

-->运行该物体(run)

定义角色的全局变量

角色的图片(12帧)

角色的x与y坐标

角色加载的帧数

初始化角色属性

这里就是同样的操作,把图片加载到name数组里面,然后初始化这个图片和角色的坐标和角色的帧

加载角色的图片

下面那个是下蹲所需要,这个后面会讲,我们理解下面这个就好

我们这里是放置一个角色在(heroX,heroY)这个坐标的位置,放置的是这个imgHero这个数组里面的图片,那么我们现在最后的一步就是不断逐帧的显示图片即可

逐帧显示图片

我们利用这个可以进行逐帧动画,实现玩家的不断奔跑,用取模运算改变数组的下角标来实现角色的运动

目前我们设计的函数有

Main函数-----主控制台

Init-----初始化每一个东西的属性

Updatebg-----加载背景

UpdateHero-----加载角色

Run-----运行每一个事物

实现玩家的跳跃

这里我们利用这几个全局变量来是实现跳跃的功能

Herojump 这个是一个布尔变量,实现是否进行跳跃

Jump HeightMax 这个每一次进行的循环,这个角色该上移和下移动多少

初始化跳跃的属性

herojump是进行判断是否进行跳跃

jump HeightMax 是跳跃的最大限度

herojumpOff 是每次所减少的量

输入空格键来实现玩家的跳跃

这里就是如果有键盘输入的话,这个_kbhit()这个就会返回为真,否则返回为假

我们有了这个然后判断一下输入的是什么键盘就可以进行操作的执行了,ch是用来接受这个他输入的是什么东西就执行什么东西,我们如果输入空格之后就会跳到jump函数的里面

Jump的开关函数

跳跃的实现

这个是我们实现跳跃的函数,如果jump被打开,那么就让heroY先上升,但是我们是往0靠近的,所以我要加负数,然后下降的时候是要加正数来实现下下降然后当我们角色下降到合适的位置,我们就可以关掉这个角色跳跃的开关即可

优化帧

这个就是我们用来实现这个优化帧的

这个是我们一般来写的,每间隔30毫秒执行一次循环里面的语句,但是我们在这30毫秒里面去输入空格的话,这个电脑是执行休眠期的,所以这个空格就不会执行,胡出现掉帧的情况,虽然我们这种小型的游戏看不出什么,但是大型游戏就很明显,所以我们来优化一下

我们定义了一个update来执行是否进行更新,虽然跟sleep的功能很相似,但是这个是受我们控制的keyEvent(),在更新的前面,方便控制更新getdaly()执行的就是不断的输入1毫秒,当这个到达30次就执行一次清零,然后就update打开,跟sleep很像,但是当我们输入空格的时候,那个jump开关函数里面也有一个update打开,这样就可以在30毫秒里执行跳跃,不至于掉帧

到目前我们所实现的程序:

Main-----控制台函数

Init-----初始化函数

Update(xxx)---加载各种图片

keyEvent—判断输入的键盘的功能-

jump的开关函数

实现多种障碍物的出现

我们把定义一个枚举,里面放置各种类型的障碍物

这里是定义一个存储每一个障碍物的数组,这里使用的c++的容器写的,大家也可也用c语言的二维数组来进行编写

这里定义了每一个障碍物的的属性,用于后面的编写

这个是定义的是,我们用于存放障碍物的,便于我们设置他们的属性

接下来我们就要把这所有的进行初始化,用于后面的操作里

这个是初始化小奶龙的

这个是我们现加载一下这个图片,创建一个容器类的一维数组用来存放图片然后把在容器里用push_back功能来实现把图片压入容器,然后在把这个一维数组放入到我们先前创建好的二维容器数组里面,这个TOTRTOISE是我们之前用枚举定义过的,用这个可读性很高,这样我们就可以分清楚哪一行对应的那一种的障碍物

这个是我们kunkun的图片初始化,跟小奶龙的初始化是一样的,只不过kunkun是一个动图,所以才需要for循环来执行逐一把图片压入到二维数组里面

这个是柱子的初始化,由于不知道为什么这个用for循环逐个压入会有问题,可能是尺寸问题,所以采取了逐一的压入的方法

OBSTACLE_CUONT是障碍物的最大个数

然后我们把每一个障碍物的存在都设置为false

这里生声明一下,我们定义了两种数组:

一个是存放照片的

vector<vector<IMAGE>>obstacleImags(OBSTACLE_TYPE_COUNT,vector<IMAGE>(12));

一个是存放每个障碍物的,这个是用于管理每一个障碍物的属性

obstacle_t obstacles[OBSTACLE_CUONT];

当我们进行图片的初始化,我们就要创造障碍物

除了伤害和移动速度对于每一个角色都不一样,其他的属性都是一样的

这里就是如果障碍物不存在的化,这个就是跳出循环,但是如果单单这样就是每一次都是第一个障碍物出现,所以我们就要在后面实现一个随机取的一个功能

这里就是随机取这个障碍物的功能,由于vs比较严谨,所以整形和枚举类型是不会兼容的,所以需要强制转换一下,这个rand前面要写一个strand函数,随机种子要写time,这样才可以实现随机出现一个数字,要不然是一直出现一种的数字,所以我们分为了两个区域一个是取奶龙,kunkun,柱子,但是柱子有出现了很多种,为了让每一个柱子出现的频率相同,下面在写一个对于柱子的随机取值

知识点:rand()%x这个是取0~(x-1)范围的值,在前面我们已经定义了枚举的类型,所以这个是十分方便的,其他与初始化反着来就可以了

我们现在初始化了每一个障碍物和实现了他们的创建,但是我们还要实现他们的出现和调整频率,要不然一直出来就完蛋了在这样就没有操作空间了

所以我们要在run函数里面进行操作

我们定义一个静态变量,这个是每一次都是加1,达到50次就刷新怪物来调整这个怪物之后就进行创造这个障碍物,这个频率肯定不可以一直不变嘛,所以我们后面再写一个rand函数前面也写一个srand函数来以time为种子实现随机,但是创造这个障碍物还要实现移动和关闭,要不然不动还不一移动就不是游戏了

实现障碍物的移动和开关的关闭

这里我们也是在run函数里写,创建完障碍物,我们就逐一的判断每一个障碍物的存在性,存在就调用他们之前定义的速度,记住要加背景的速度,因为小奶龙是不动的,然后这个当到达这个-300的时候,就把这个图片关掉,但是由于我们的kunkun使用一个动图,所以我们就要加下面这个,计算他数组的长度,然后利用取模运算来

方法:

取模:(x+1)% n这个是确保不超出n如果等于n就自动为0了,但是小于n就是他本身加1,比如(1+1)%12为2,就是为(x+1)的值,只是为了不超过一直在0~n的区间内执行

我们现在已经初始化障碍物,创造障碍物,实现障碍物移动与关闭,现在就差一个放置在窗口了,所以我们就要写一个updatezhang这个来放置图片

这个是放置障碍物所用的看是否存在然后进行放置窗口

这样也就实现了障碍物了

实现玩家的下蹲

定义相关下蹲属性

用于下蹲的开关和存放这个角色下蹲图片的数组

初始化角色的相关属性

Down的输入设置

当我们输入s的时候就可以打开这个down的开关

这个时候我们是读取这个角色下蹲数组的图片,所以这个下角标一定要进行更新为0,然后再进去,要不然会出现bug

这里是下蹲功能的实现

我们用静态变量来实现这个次数,我们要这两个图片之间要有一定的时间间隔,要不然会很快的起来,所以我们这里定义一个delays是用于延迟的,然后延迟到一定的时间的时候,我们就可以实现这个图片的更换,完成之后,我们有初始化这个图片的下角标,这样就可以实现下蹲和然后再关掉这个开关

当下蹲和跳跃都没有实现的时候,就执行这个奔跑

当目前为止我们已经完成了大半的进度了实现了玩家的下蹲,奔跑,背景的移动,障碍物的出现,调频,帧的优化

接下来就是实现这个血条,得分,撞到检测,打包,这个会在下一篇讲到


总结

今天我们学习到了障碍物,背景,人物的制作

对于大部分的物件的实现

定义这个物件的相关属性-->初始化这个程序的相关的属性-->加载这个物件到这个窗口-->运行这个程序

对于大部分功能的实现

定义这个共能再物件的相关属性(如跳多高)-->定义这个功能的开关-->再运行函数写出这个程序-->是否需要别的函数来辅助实现(如这个障碍物就是需要creatObstacle函数)-->放置物体

关于背景

我们再实现东西的时候要知道拿一些放入到死循环里面,那些不需要,这个背景是每时每刻都是存在的,所以我们不需要放到死循环里面,放到外面即可

关于人物

我们再写人物的时候,有很多的动作,我们这个时候先创建这个人物的相关的属性,然后这个根据功能写出相关的函数,比如我们在这里就是要跳跃,下蹲,奔跑,这里我们可以用if语句来实现三种功能,在奔跑是奔跑,跳跃时不奔跑等,我们还设计了一个函数是关于键盘的输入还有开关的公控制是否需要打开,这样我们的逻辑思路是很清晰的

知识点(x+1)%n这个公式就是循环取值的时候永远都不会超过n,一直在(x+1)~n跳动这个就为我们逐帧动画提供了很好的帮助

关于障碍物

我们在写障碍物的时候,我们要写出很多的属性,这里需要用到结构体就可以简化很多的代码,结构体里面全部都是障碍物的相关属性,然后利用枚举类型,在实现数组的时候,初始化用枚举具有很高的可读性,然后到后面我们存了这个图片不知道在哪一行是这个障碍物的图片是,可以去到枚举里面查看,而且枚举在最后面定义一个sum就是障碍物的总和

障碍物的功能总结

我们在实现障碍物的时候,我们需要随机出现所以创造障碍物的时候,我们需要用到rand和strand函数来实现实现,后面就是频率的控制和障碍物的放置和移动了

知识点  rand()%n这个数字永远是0~n-1这个区间里面的,这样也可以用于调整出现频率什么时候出现,也可以用于随机出现障碍物

优化帧

我们一般都是用sleep这个来写,但是容易掉帧,所以我们需要写一个自己可以控制那30毫秒里面的东西

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

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

相关文章

公交车信息管理系统:构建智能城市交通的基石

程序设计 本系统主要使用Java语言编码设计功能&#xff0c;MySQL数据库管控数据信息&#xff0c;SSM框架创建系统架构&#xff0c;通过这些关键技术对系统进行详细设计&#xff0c;设计和实现系统相关的功能模块。最后对系统进行测试&#xff0c;这一环节的结果&#xff0c;基本…

MDS-NPV/NPIV

在存储区域网络&#xff08;SAN&#xff09;中&#xff0c;域ID&#xff08;Domain ID&#xff09;是一个用于区分不同存储区域的关键参数。域ID允许SAN环境中的不同部分独立操作&#xff0c;从而提高效率和安全性。以下是关于域ID的一些关键信息&#xff1a; 域ID的作用&…

【网络安全产品大调研系列】1. 漏洞扫描

1. 为什么会出现漏扫技术&#xff1f; 每次黑客攻击事件进行追溯的时候&#xff0c;根据日志分析后&#xff0c;我们往往发现基本都是系统、Web、 弱口令、配置这四个方面中的其中一个出现的安全问题导致黑客可以轻松入侵的。 操作系统的版本滞后&#xff0c;没有更新补丁&am…

验证 Dijkstra 算法程序输出的奥秘

一、引言 Dijkstra 算法作为解决图中单源最短路径问题的经典算法,在网络路由、交通规划、资源分配等众多领域有着广泛应用。其通过不断选择距离源节点最近的未访问节点,逐步更新邻居节点的最短路径信息,以求得从源节点到其他所有节点的最短路径。在实际应用中,确保 Dijkst…

【论文阅读笔记】Learning to sample

Learning to sample 前沿引言方法问题声明S-NET匹配ProgressiveNet: sampling as ordering 实验分类检索重建 结论附录 前沿 这是一篇比较经典的基于深度学习的点云下采样方法 核心创新点&#xff1a; 首次提出了一种学习驱动的、任务特定的点云采样方法引入了两种采样网络&…

Mysql大数据量表分页查询性能优化

一、模拟场景 1、产品表t_product,数据量500万+ 2、未做任何优化前,cout查询时间大约4秒;LIMIT offset, count 时,offset 值较大时查询时间越久。 count查询 SELECT COUNT(*) AS total FROM t_product WHERE deleted = 0 AND tenant_id = 1 分页查询 SELECT * FROM t_…

pythonWeb~伍~初识Django

初识Django 1.技术栈 Python知识点&#xff1a;函数、面向对象。前端知识点&#xff1a;HTML、CSS、JavaScript、jQuery、BootStrap。MySQL数据库。Python的Web框架&#xff1a; Flask&#xff0c;自身短小精悍 第三方组件。Django&#xff0c;内部已集成了很多组件 第三方…

kimi搜索AI多线程批量生成txt原创文章软件-不需要账号及key

kimi搜索AI多线程批量生成txt原创文章软件介绍&#xff1a; 软件可以设置三种模型写文章&#xff1a;kimi&#xff1a;默认AI模型&#xff0c;kimi-search&#xff1a;联网检索模型 &#xff0c;kimi-research&#xff1a;探索版搜索聚合模型 1、可以设置写联网搜索文章&#…

DevNow x Notion

前言 Notion 应该是目前用户量比较大的一个在线笔记软件&#xff0c;它的文档系统也非常完善&#xff0c;支持多种文档格式&#xff0c;如 Markdown、富文本、表格、公式等。 早期我也用过一段时间&#xff0c;后来有点不习惯&#xff0c;就换到了 Obsidian &#xff0c;但是…

CSPM认证最推荐学习哪个级别?

一、什么是CSPM&#xff1f; CSPM的全称是Certified Strategic Project Manager&#xff0c;中文名称为“项目管理专业人员能力评价等级证书”。这是由中国标准化协会依据国家标准《项目管理专业人员能力评价要求》&#xff08;GB/T 41831-2022&#xff09;推出的一项认证&…

oracle: create new database

用database configuration Assistant 引导创建数据库。记得给system,sys 设置自己的口令&#xff0c;便于添加新操作用户。 创建操作用户&#xff1a; -- 别加双引号&#xff0c;否则&#xff0c;无法用 create user geovindu identified by 888888; create user geovin identi…

快速建站(网站如何在自己的电脑里跑起来) 详细步骤 一

1.选择开源网站 开源网站的建设平台有多种类型&#xff0c;每种类型都针对不同的需求和用途。我们根据自己的需求来选择 一、内容管理系统&#xff08;CMS&#xff09; 内容管理系统是开源网站建设中最常见的类型之一&#xff0c;它们提供了一个易于使用的界面&#xff0c;使用…

ECharts散点图-气泡图,附视频讲解与代码下载

引言&#xff1a; ECharts散点图是一种常见的数据可视化图表类型&#xff0c;它通过在二维坐标系或其它坐标系中绘制散乱的点来展示数据之间的关系。本文将详细介绍如何使用ECharts库实现一个散点图&#xff0c;包括图表效果预览、视频讲解及代码下载&#xff0c;让你轻松掌握…

【蓝桥杯——物联网设计与开发】拓展模块5 - 光敏/热释电模块

目录 一、光敏/热释电模块 &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;AS312 &#x1f319;简介 &#x1f319;特性 &#x1f505;LDR &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#xff08;4&#x…

Escalate_Linux靶机

Escalate_Linux靶机 前言&#xff1a;集合了多种liunx提权方法的靶场&#xff0c;通过该靶场可以简单的了解liunx提权方法 1&#xff0c;扫描一下端口 80/tcp open http 111/tcp open rpc 2049/udp nfs要知道对方的共享才能挂载 139/445 Samba SMB是一个协议名&#xff0c…

PPO算法基础(一)

PPO近端策略优化算法 我们今天还是主要来理解PPO算法的数学原理。PPO是一种策略梯度方法&#xff0c;简单的策略梯度对每个样本&#xff08;或者一组样本&#xff09;进行一次梯度更新&#xff0c;对单个样本执行多个梯度步骤会导致一些问题&#xff0c;因为梯度偏差太大&…

[机器学习]sklearn入门指南(1)

简介 scikit-learn&#xff08;简称sklearn&#xff09;是一个开源的Python机器学习库&#xff0c;它提供了简单而高效的工具用于数据挖掘和数据分析&#xff0c;并且拥有一个活跃的开发社区。它建立在NumPy、SciPy和matplotlib这些科学计算库之上&#xff0c;旨在提供一致且可…

贪心算法(三)

目录 一、k次取反后最大化的数组和 二、优势洗牌 三、最长回文串 四、增减字符串匹配 一、k次取反后最大化的数组和 k次取反后最大化的数组和 贪心策略&#xff1a; 解题代码&#xff1a; class Solution { public:int largestSumAfterKNegations(vector<int>&am…

文本的AIGC率检测原理

背景 你可能在学生群里或者视频中看过这样的消息&#xff1a;“我们学校要求论文AI率不能超过30%&#xff01;”、“你们学校查AI率吗&#xff1f;”之类的&#xff0c;这些消息到底是真是假&#xff1f; 随着人工智能的快速发展和广泛应用&#xff0c;不论是工作中还是学生学…

Linux -- 从抢票逻辑理解线程互斥

目录 抢票逻辑代码&#xff1a; thread.hpp thread.cc 运行结果&#xff1a; 为什么票会抢为负数&#xff1f; 概念前言 临界资源 临界区 原子性 数据不一致 为什么数据不一致&#xff1f; 互斥 概念 pthread_mutex_init&#xff08;初始化互斥锁&#xff09; p…