古之学者必有师,对于技术的提升,只靠自己的摸索虽然能得到深刻的经验,但往往没有较高的效率。笔者这些天学习了BV1eM4m1S74K“提瓦特幸存者”的C++开发,也是实现了该类型游戏的开发。

今天,就通过经验总结,亲手结束这一小段学习过程!


游戏的基本框架

所有游戏的底层框架都是通过一个主循环来刷新画布,每个循环中都实现读取操作、处理数据、绘制画面这三个步骤。

int main() {while (running) {//动态延时(记录本次循环开始的时间)DWORD start_time = GetTickCount();  //32位无符号整数,长度不随编译器变化//读取操作区域while (peekmessage(&msg)) {}//处理数据区域cleardevice();//渲染画面区域FlushBatchDraw();//记录循环结束时间DWORD end_time = GetTickCount();DWORD delta_time = end_time - start_time;//1秒144次刷新,即帧率为144,一个循环就是一帧if (delta_time < 1000 / 144) {Sleep(1000 / 144 - delta_time);}}EndBatchDraw();return 0;
}

在这些操作执行完后,加上动态延时从而实现游戏开发中“帧”的概念。这也是游戏引擎设计的基本框架,是不是很有Update()函数的感觉?

关于渲染缓冲区:

为了隐藏渲染或其他处理的过程,BeginBatchDraw函数会让后续的渲染操作在缓冲区中进行,像一块闲置的画布,当调用FlushBatchDraw或EndBatchDraw,即所有操作绘制结束时,直接代替当前画布,达到无缝衔接的效果。

一些代码细节:

视频的创作者在许多地方都体现了C++的编码细节,比如使用static静态变量只在第一次调用时创建(后续调用会跳过)复用同一内存;使用TCHAR这一Windows兼容类型适应非英文环境;同样使用宽字符串适应非英文环境……

头文件依赖问题

在这次C++开发的过程中,我总是被所谓“出现未定义的变量名”给搞到破防。这是头文件重复包含导致的。

一个项目各个区域的执行顺序是全局变量->静态全局变量->函数声明->静态函数声明->类定义->静态类成员定义->命名空间变量->函数定义……头文件一般用来包含变量与函数的声明、类的定义等重要信息。

头文件的循环包含引发编译错误的原因:

编译器处理 #include 时,会把对应头文件内容嵌入包含位置。若头文件循环包含,其可能会陷入无限递归尝试展开头文件的情形。即便使用包含守卫( #ifndef 三件套 )或 #pragma once 规避重复展开,由于头文件解析时需要对方类型完成自身声明或定义,循环依赖会导致部分必要的声明或定义无法在依赖解析阶段正确处理。

类似A.h在第一行包含了B.h,同时B.h的第一行包含了A.h, B类使用的A类的定义,但是在头文件依赖解析A.h时,先展开B.h,但B.h遍历到A.h会因为包含守卫而跳过,这下B类里A就没有了定义……

这里有三个编程习惯可以尽量避免头文件重复包含的问题:

1、使用前向声明,在使用A的头文件中声明声明一下A类。不需要访问具体成员时需要。

2、使用包含守卫,即 #ifndef、#define、#endif 连招。

3、使用 #pragma once,可替代包含守卫,使头文件在一个编译单元中只包含一次。

但这些方法只能尽量避免我们遇到的问题,最重要的还是在一开始就规划好项目的结构。保持头文件声明、源文件定义的好习惯,在必要时进行重构,让文件包含的脉络清晰,一目了然。

动画与MCI工具

游戏中使用的动画分为骨骼动画(关键帧动画)与序列帧动画。序列帧动画就是让图片素材以若干个帧为单位进行交替,从而达到动画播放的效果。

这里使用自定义图集类来批量载入名称有规律的图片素材。

Atlas::Atlas(LPCTSTR path, int num) {TCHAR path_file[256];for (size_t i = 0; i < num; ++i) {_stprintf_s(path_file, path, i);IMAGE* frame = new IMAGE();loadimage(frame, path_file);frame_list.push_back(frame);}
}

这种方法依次用从零开始的自然数代替图集中的数字部分,实现图片载入。

MCI工具(媒体控制接口)能够让我们以字符串的形式对windows系统发出指令,控制音乐的播放。

但在我的测试中,mp3文件在播放时,会明显影响游戏的帧率。经过测试与查询,这与MP3格式文件的特性有关:编解码边播放。而MCI解码的消息可能会打断Sleep,让主循环提前醒来,导致帧率变高。

所以在加载音频文件时,更推荐使用WAV格式:1、MCI 加载 MP3 资源时,底层会创建额外的线程或窗口,并且会向主消息队列发送消息(比如 MM_MCINOTIFY),EasyX 的 peekmessage 也会处理这些消息。2、WAV 文件是无压缩格式,处理简单,不会影响主线程;而 MP3 需要解码,可能会影响主线程的消息分发和定时精度。3、某些 Windows 环境下,MCI 加载MP3会让Sleep变得不准确,主循环实际刷新频率变高。


小结

虽然本篇图文列出的点很少,但是这次学习经历切切实实加深了游戏开发的理解。我想这些框架性的东西也可能成为游戏引擎开发的一个开端,而通过C++而不是依赖引擎的开发,更能深入底层逻辑,让日后对代码的优化的方向更清晰。

如有补充纠正欢迎留言。

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

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

相关文章

Python OpenCV图像处理与深度学习:Python OpenCV图像分割入门

图像分割&#xff1a;从基础到实践 学习目标 通过本课程&#xff0c;学员们将了解图像分割的基本概念&#xff0c;掌握使用OpenCV实现图像分割的方法&#xff0c;包括基于阈值的分割和基于区域的分割技术。同时&#xff0c;学员将能够独立完成简单的图像分割任务&#xff0c;并…

MQ使用场景分析

异步解耦‌系统间通过消息队列通信&#xff0c;降低耦合度&#xff08;如订单系统与库存系统&#xff09;典型场景&#xff1a;电商下单后异步通知物流系统‌流量削峰‌应对突发流量&#xff0c;将请求暂存到消息队列逐步处理典型场景&#xff1a;秒杀活动时缓冲高并发请求‌数…

人工智能学习:NLP文本处理的基本方法

一、分词 1、分词介绍 概念 分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符。分词过程就是找到这样分界符的过程…

Vue3 中 Proxy 在组件封装中的妙用

目录 Vue3 中 Proxy 在组件封装中的妙用&#xff1a;让组件交互更优雅 组件封装中的常见痛点 Proxy 是什么&#xff1f; Proxy 在组件封装中的应用 基础组件结构 使用 Proxy 实现方法透传 代码解析 父组件中的使用方式 Proxy 的其他应用场景 1. 权限控制 2. 方法调用…

DevExpress WinForms中文教程:Data Grid - 过滤编辑器

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

华为云CCE

华为云CCE&#xff1a;重构云原生应用的全栈引擎 一、云原生时代的"操作系统" 在数字经济浪潮中&#xff0c;容器化和微服务架构已成为企业数字化转型的标配。华为云容器引擎&#xff08;CCE&#xff09;作为云原生领域的"操作系统"&#xff0c;通过深度…

STM32——Uinx时间戳+BKP+RTC实时时钟

目录 一、Uinx时间戳 1.1Uinx简介 1.2UTC/GMT 1.3时间戳转换 1.3.1主要数据类型 1.3.2主要函数 1.3.3C语言时间戳转换示例 1.3.4时间格式化说明符 1.3.5注意事项 二、BKP 2.1BKP简介 2.2BKP基本结构 三、RTC 3.1RTC简介 3.2RTC框图 3.3RTC基本结构 3.4RTC硬件…

Java设计模式是什么?核心设计原则有哪些?

文章目录什么是设计模式&#xff1f;为什么使用设计模式&#xff1f;设计模式的核心设计原则是什么&#xff1f;1. 开闭原则&#xff08;Open-Closed Principle, OCP&#xff09;2. 里氏替换原则&#xff08;Liskov Substitution Principle, LSP&#xff09;3. 依赖倒置原则&am…

网络层和数据链路层

目录 1.网络层 2.数据链路层 1.网络层 我们知道&#xff0c;我们的消息为了从A端发送到B端&#xff0c;达成远距离传输&#xff0c;我们为此设计了很多协议层&#xff0c;分别是应用层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层&#xff0c;网卡&#xff0c…

Redis 的字典:像智能文件柜一样高效的哈希表实现

目录 一、从传统查找的痛点到哈希表的优势​ 二、哈希表的核心结构&#xff1a;文件柜的构成​ 2.1、 dictht 结构体&#xff1a;文件柜本体​ 2.2、dictEntry 结构体&#xff1a;带链条的文件夹​ 2.2.1、 哈希冲突的解决&#xff1a;抽屉里的链条​ 2.3、字典的高层封装…

FAST API部署和使用

第一部分&#xff1a;FastAPI 的使用&#xff08;开发环境&#xff09; 1. 安装 首先&#xff0c;你需要安装 FastAPI 和一个 ASGI 服务器&#xff0c;最常用的是 Uvicorn。 pip install "fastapi[standard]"这个命令会安装 FastAPI 以及所有推荐的依赖&#xff0c;包…

【JavaWeb】之HTML(对HTML细节的一些总结)

大家天天开心&#xff01; 文章目录 前言一、HTML的简介二、HTML运行方式三、html 的标签/元素-说明四、表单注意事项总结 前言 首先我们在把Java基础学习完之后&#xff0c;我们就要进行网站方面的开发了&#xff0c;我们要了解网页的组成&#xff0c;而网页的组成有HTML,CSS,…

互联网医院品牌IP的用户体验和生态构建

一、患者体验与信任构建互联网医院品牌IP的价值核心在于获得患者的深度信任&#xff0c;而卓越的用户体验是实现这一目标的关键路径。在医疗服务同质化严重的当下&#xff0c;患者体验已成为医疗机构差异化竞争的重要维度。研究表明&#xff0c;良好的用户体验能够提高用户满意…

【Node.js教程】Express框架入门:从搭建到动态渲染商品列表

前言 Visual Studio Code(简称VSCode)是微软开发的一款免费开源跨平台代码编辑器,凭借其免费、开源、跨平台的特性,以及丰富的插件生态和美观的界面,成为前端开发者的首选工具。 本文将带你从零开始学习Express框架,包括搭建项目、配置路由、使用中间件以及实现动态渲染…

众擎机器人开源代码解读

一&#xff0c;综述 EngineAI ROS 包&#xff1a; 高层开发模式&#xff1a;用户可通过发布身体速度指令&#xff0c;直接调用 EngineAI 机器人的行走控制器。底层开发模式&#xff1a;用户可通过发布关节指令&#xff0c;自主开发专属的控制器。 ROS2 package&#xff1a;全…

Windows系统安装Git详细教程

文章目录步骤 1&#xff1a;下载 Git 安装包步骤 2&#xff1a;运行安装程序步骤 3&#xff1a;选择安装路径步骤 4&#xff1a;选择组件步骤 5&#xff1a;选择默认编辑器步骤 6&#xff1a;选择路径环境变量步骤 7&#xff1a;选择 HTTPS 协议的传输方式步骤 8&#xff1a;配…

leetcode 3446. 按对角线进行矩阵排序 中等

给你一个大小为 n x n 的整数方阵 grid。返回一个经过如下调整的矩阵&#xff1a;左下角三角形&#xff08;包括中间对角线&#xff09;的对角线按 非递增顺序 排序。右上角三角形 的对角线按 非递减顺序 排序。示例 1&#xff1a;输入&#xff1a; grid [[1,7,3],[9,8,2],[4,…

携程旅行 web 验证码 分析

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向分析 部分python代码 result cp…

JavaEE 进阶第一期:开启前端入门之旅(上)

专栏&#xff1a;JavaEE 进阶跃迁营 个人主页&#xff1a;手握风云 一、HTML基础 1.1. 什么是HTML HTML(Hyper Text Markup Language)&#xff0c;超文本标记语言。 超文本&#xff1a;比文本要强大&#xff0c;通过链接和交互式方式来组织和呈现信息的文本形式。不仅仅有文本…

4.5 PBR

1.PBR简介 2.高光工作流 3.金属工作流1.PBR简介 PBR(Physically Based Rendering, 基于物理的渲染)的工作流分为金属工作流和高光工作流2.高光工作流 高光工作流是一种传统的工作流, 现在用的相对较少, 但是在某些特定情况下能提供更精细的控制a.核心思想它不区分金属和非金属,…