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.rhkb.cn/news/495662.html

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

相关文章

Docker数据库的主从复制

有很多种方式,我这里使用的是docker镜像配置两个mysql容器做主从复制,一个做主服务器&#xff0c;另一个做从服务器&#xff0c;前提是有docker。 创建容器: 第一个容器: mkdir mysql cd mysql docker run -id \ -p 3307:3306 \ --namels \ -v /root/mysql/conf:/etc/mysql/co…

CH32V307VCT6---工程template创建

一、硬件&#xff1a;沁恒官网申请的CH32V307VCT6开发板 二、开发环境&#xff1a;Mounriver 三、最终效果 1.PB9连接LED1&#xff0c;使其闪烁 2.OLED屏幕显示&#xff1a;软件IIC&#xff0c;PB10----SDA&#xff0c;PB11---SCL 3.工程链接&#xff1a;CH32V307VCT6 lo…

mac中idea菜单工具栏没有git图标了

1.右击菜单工具栏 2.选中VCS&#xff0c;点击添加 3.搜索你要的工具&#xff0c;选中点击确定就添加了 4.回到上面一个界面&#xff0c;选中你要放到工具栏的工具&#xff0c;点击应用就好了 5.修改图标&#xff0c;快捷键或者右击选中编辑图标 6.选择你要的图标就好了

使用 Python 创建多栏 Word 文档 – 详解

目录 引言 一、工具与安装 二、Python 在 Word 中创建简单的多栏布局 三、Python 在 Word 文档的栏间添加分隔线 四、Python 从Word文档的指定位置开启多栏设置 五、Python 为多栏 Word 文档的各栏添加页码 引言 在文档设计中&#xff0c;排版不仅决定了内容的呈现方式&…

JZ31 栈的压入、弹出序列

题目来源&#xff1a;栈的压入、弹出序列_牛客题霸_牛客网 题目&#xff1a;如下 输入两个整数序列&#xff0c;第一个序列表示栈的压入顺序&#xff0c;请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序&#xf…

Spring源码_05_IOC容器启动细节

前面几章&#xff0c;大致讲了Spring的IOC容器的大致过程和原理&#xff0c;以及重要的容器和beanFactory的继承关系&#xff0c;为后续这些细节挖掘提供一点理解基础。掌握总体脉络是必要的&#xff0c;接下来的每一章都是从总体脉络中&#xff0c; 去研究之前没看的一些重要…

【Linux】进程间通信 -> 匿名管道命名管道

进程间通信的目的 数据传输&#xff1a;一个进程许需要将它的数据发送给另外一个进程。资源共享&#xff1a;多个进程之间共享同样的资源。通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它们发生了某种事件&#xff08;如进程终止时要通知父进程…

大模型-使用Ollama+Dify在本地搭建一个专属于自己的聊天助手与知识库

大模型-使用OllamaDify在本地搭建一个专属于自己的知识库 1、本地安装Dify2、本地安装Ollama并解决跨越问题3、使用Dify搭建聊天助手4、使用Dify搭建本地知识库 1、本地安装Dify 参考往期博客&#xff1a;https://guoqingru.blog.csdn.net/article/details/144683767 2、本地…

黑盒测试/白盒测试知识总结

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 对于很多刚开始学习软件测试的小伙伴来说&#xff0c;如果能尽早将黑盒、白盒测试弄明白&#xff0c;掌握两种测试的结论和基本原理&#xff0c;将对自己后期的学习…

数据结构之线性表之顺序表

定义&#xff1a; 由n&#xff08;n>0&#xff09;个数据特性相同的元素构成的有限序列称为线性表 简单来说n个相同数据类型的数据组wsw合在一起的这么一个集合就是一个线性表 线性表包括顺序表和链表 1. 顺序表&#xff08;我们所有的代码实现都用函数来封装&#xff09…

ReactPress 1.6.0:重塑博客体验,引领内容创新

ReactPress 是一个基于Next.js的博客&CMS系统&#xff0c; Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎Star。 体验地址&#xff1a;http://blog.gaoredu.com/ 今天&#xff0c;我们自豪地宣布ReactPress 1.6.0版本的正式发布&#xff0c;…

(echarts)数据地图散点类型根据条件设置不同的标记图片

(echarts)数据地图散点类型根据条件设置不同的标记图片 1.用在线工具将本地图片转化base64格式 data(){return { base64Img:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQ...",} }在线转换地址&#xff1a;https://www.jyshare.com/front-end/59/ 2.symbol属…

傅里叶变换原理

本文学习自YuHWEI最浅显易懂的傅里叶变换公式和原理_采样率和信号频率计算镜像频率-CSDN博客 本文会对公式实现 更加详细的补充 连续与离散 一般人们口中所说的傅里叶变换都是指连续傅里叶变换&#xff0c;针对的是连续时域信号. 对于计算设备的信号处理&#xff0c;因为采样…

STM32高级 以太网通讯案例2:搭建TCP服务端

需求描述 在TCP通讯的时候&#xff0c;客户端必须主动联系服务器&#xff0c;这样才能实现通讯。服务器与客户端之间的连接是一种长连接&#xff0c;一旦连上一般是不会断开的。 在STM32上启动一个TCP的服务端&#xff0c;在电脑上用TCP客户端去连接服务端。客户端给服务端发…

系统架构师考试 常错题记录 01

1.按照《中华人民共和国著作权法》的权利保护期&#xff08; &#xff09;受到永久保护。 A.发表权 B.修改权 C.复制权 D.发行权 正确答案&#xff1a;B 解析&#xff1a;本题考查知识产权法中的《中华人民共和著作权法》保护期限知识点。 《中华人民共和著作权法》中约定署名权…

WebPack3项目升级webpack5的配置调试记录

文章目录 前言一、webpack3环境1.1、知识点记录1.1.1、配置解释1.1.2、webpack与sass版本对应关系1.1.3、CommonJS与ESModule1.1.4、node版本管理nvm1.1.5、sass-loader、sass与node-sass 1.2、其他1.2.1、.d.ts是什么文件1.2.2、react与types/react版本对应关系1.2.3、webpack…

[源码解析] 模型并行分布式训练Megatron (2) --- 整体架构

link [源码解析] 模型并行分布式训练Megatron (2) --- 整体架构 目录 [源码解析] 模型并行分布式训练Megatron (2) --- 整体架构 0x00 摘要0x01 启动 1.1 分布式启动1.2 构造基础 1.2.1 获取模型1.2.2 获取数据集1.2.3 步进函数 1.2.3.1 广播数据0x02 Pretrain0x03 初始化 3.1 …

事件驱动编程与异步编程:原理、对比及实践案例

在编程领域&#xff0c;事件驱动编程&#xff08;Event-Driven Programming&#xff09;与异步编程&#xff08;Asynchronous Programming&#xff09;是两种极为关键的编程范式&#xff0c;它们对于提升程序运行效率与响应速度效果显著&#xff0c;尤其在应对I/O密集型任务以及…

基于earthSDK三维地图组件开发

上效果 功能点 测量分析相机位置切换geojson数据加载地图打点&#xff0c;显示信息点击回传数据二三位切换 这里二三维切换通上篇openlayers分享&#xff0c;技术交流V:bloxed <template><div class"h100 w100"><div style"width:100%; heig…

计算机毕业设计Python+Spark知识图谱酒店推荐系统 酒店价格预测系统 酒店可视化 酒店爬虫 酒店大数据 neo4j知识图谱 深度学习 机器学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…