游戏引擎学习第11天

视频参考:https://www.bilibili.com/video/BV1QLmDYQE3n

平台层的编写 应该是平台可移植什么的吧

逐项补充说明:

  1. 存档位置
    在游戏或应用程序中,需要保存用户的进度、设置和数据,存档位置是指存放这些数据的文件夹路径。通常,平台层需要处理不同操作系统或设备的存档目录,并确保数据能够正确保存和加载。

  2. 获取自己可执行文件的句柄
    在某些情况下,程序需要获得自己的可执行文件路径或句柄。这对于进行文件操作、获取程序资源或与操作系统交互非常有用。例如,在Windows平台下,可以通过 GetModuleFileName 获取当前程序的路径。

  3. 资源加载路径
    在平台层中,资源加载路径指的是存储游戏或应用程序资源(如图像、音频文件等)的目录。平台层通常会确定资源文件的位置,并确保正确的路径设置,从而使程序能够正确加载所需的资源。

  4. 线程(启动线程)
    多线程编程是提高程序效率和响应速度的重要方法。平台层可能需要提供对线程的支持,例如通过操作系统的API启动、管理和销毁线程。Windows平台可以使用 CreateThread 或 C++ 标准库中的线程支持。

  5. 原始输入(支持多个键盘)
    原始输入支持指的是直接访问输入设备(如键盘、鼠标等)的能力,绕过操作系统的标准输入处理。这对于需要精确控制的应用程序(如游戏)非常重要。支持多个键盘意味着应用程序能够同时接收来自多个输入设备的事件。

  6. 睡眠/TimeBeginPeriod
    Sleep 是一种暂停当前线程执行的方式。在某些情况下,程序可能需要改变系统的时钟频率,以便提高时间分辨率,特别是与游戏或动画帧速率相关的部分。TimeBeginPeriod 是Windows API,用于提高系统时钟精度,通常会影响定时器的行为。

  7. ClipCursor()(多显示器支持)
    ClipCursor 是一个 Windows API 函数,它可以限制鼠标光标的活动范围,通常用于多显示器环境。通过限制光标在某个特定区域内移动,应用程序可以避免用户无意中把光标移出屏幕。

  8. 全屏支持
    全屏模式在游戏和某些多媒体应用中常见,它能够将应用程序窗口扩展到整个屏幕,并且不显示任务栏或其他桌面元素。全屏支持涉及到窗口管理和图形渲染的设置,通常需要通过平台层的API来调整显示模式。

  9. WM_SETCURSOR(控制光标可见性)
    WM_SETCURSOR 是 Windows 消息之一,用于控制鼠标光标的显示与隐藏。平台层需要能够管理和更新鼠标光标的状态,以便在不同的应用场景中(如游戏内或应用界面)决定是否显示光标。

  10. QueryCancelAutoplay
    QueryCancelAutoplay 是用于询问操作系统是否应该取消自动播放功能的一种机制。通常与多媒体设备(如CD/DVD驱动器)有关,平台层可以使用它来防止自动启动的程序干扰当前应用。

  11. WM_ACTIVATEAPP(当我们不是活动应用程序时)
    WM_ACTIVATEAPP 是 Windows 消息之一,用于处理应用程序的激活和失去激活状态。当应用程序从前台切换到后台或从后台切换到前台时,这条消息会被触发。平台层需要对这种情况做出反应,以便调整程序的行为(如暂停游戏、降低处理器负载等)。

  12. Blit速度优化(BitBlt)
    BitBlt 是一种常见的图像处理函数,用于在屏幕或图形缓冲区之间复制像素数据。Blit速度优化涉及通过优化 BitBlt 的调用或使用硬件加速,来提高图像渲染速度。对于需要大量图形更新的应用程序,如游戏或视频播放器,这是至关重要的。

  13. 硬件加速(OpenGL或Direct3D或两者?)
    硬件加速指的是使用图形处理单元(GPU)而不是中央处理单元(CPU)来处理图形渲染任务。常见的图形API有 OpenGL 和 Direct3D,平台层需要决定支持哪个API,或者是否同时支持两者,以便充分利用硬件加速的优势。

  14. GetKeyboardLayout(支持法语键盘、国际化WASD键支持)
    GetKeyboardLayout 是一个 Windows API 函数,用于获取当前系统的键盘布局。这对于需要支持多语言、多地区的程序非常重要,特别是在游戏中,可能需要根据用户的键盘布局调整控制映射,例如在法语键盘上调整 WASD 键的默认位置。

这些功能是平台层的一部分,用于解决不同操作系统和硬件之间的兼容性问题,并确保应用程序能够在各种环境下平稳运行。

关于平台移植定义宏

在这里插入图片描述

不推荐大量使用平台相关的宏(如 #if GAME_WIN32#elif GAME_LINUX 等)来控制代码的原因有几个,尤其是在跨平台开发中,这种做法可能会带来一些潜在问题和挑战:

1. 增加代码复杂性和可维护性

  • 大量的条件编译:当代码中有多个平台的宏控制时,代码的可读性和维护性会大大降低。你必须在每次修改时考虑到不同平台下的代码,增加了调试的复杂度。
  • 冗余代码:每个平台可能需要相似的代码,但由于平台差异,你不得不为每个平台写一套不同的实现。这样会导致重复代码,增加了维护的难度。

2. 隐藏平台差异

  • 使用宏进行平台判断虽然可以解决跨平台开发的需求,但它本质上是在不同平台间硬编码了差异。这会使得开发人员忽视了平台之间的真正差异,可能导致平台特定的优化和设计无法被显式考虑,进而错失提升性能或稳定性的机会。
  • 在有多个平台时,这种方法可能会导致不同平台的行为不一致,可能发生潜在的隐藏 bug,尤其是对于一些细微的系统差异。

3. 阻碍跨平台框架的使用

  • 如果使用大量的条件编译,可能会使你放弃使用一些成熟的跨平台库或框架(如 SDL、Qt、Boost 等),因为这些框架本身已经处理了大部分平台相关的差异。
  • 使用这些库时,通常不需要手动管理 #if PLATFORM_X 类型的宏,框架已经为你屏蔽了不同平台的差异。

4. 编译时间增加

  • 每个平台特定的代码路径都需要编译,这会使编译时间变长。在某些大型项目中,频繁的条件编译可能会影响整体编译性能。

5. 可能带来难以调试的问题

  • 条件编译可能导致一些代码路径在不同的编译环境中不一致,特别是在调试时,开发者可能会遇到某些平台特有的 bug,这些 bug 在其他平台上是不存在的,可能会导致调试变得更加复杂。

6. 错误的宏定义

  • 如果宏定义没有正确配置或者被错误地引用,可能导致程序运行时出现无法预料的行为,尤其是在大型项目或团队协作中,调试此类问题会非常困难。

7. 跨平台的可移植性问题

  • 在一些特殊情况下,条件编译会使代码无法在某些平台上直接运行。例如,如果某个平台的编译器不支持某些特性或库,那么 #if 指令会把它们排除在外,导致无法运行或移植到新平台时遇到麻烦。

更好的跨平台开发方式

为了避免上述问题,可以考虑以下几种更好的跨平台开发方式:

1. 使用跨平台库和框架
  • 使用像 SDL, Qt, Boost, GLFW 等跨平台库来屏蔽平台特有的差异,这样大部分条件编译都可以被框架内部处理,你只需要编写平台无关的代码。
2. 分层抽象
  • 通过层次化抽象来解决平台差异。例如,创建一个平台无关的接口层,然后在每个平台上实现特定的功能。这样,你可以在平台特定代码中处理差异,而不是将这些差异散布在整个代码中。
  • 示例:
    // PlatformAbstraction.h
    class IPlatform {
    public:virtual void RunMainLoop() = 0;
    };// WindowsPlatform.cpp
    class WindowsPlatform : public IPlatform {
    public:void RunMainLoop() override {// Windows-specific code}
    };// LinuxPlatform.cpp
    class LinuxPlatform : public IPlatform {
    public:void RunMainLoop() override {// Linux-specific code}
    };
    
3. 利用动态链接库(DLL / .so)
  • 在平台特定的功能上使用动态链接库,平台相关的代码可以在运行时通过动态加载不同的库来解决,而不是通过编译时的宏定义。
4. 预处理器和宏的适度使用
  • 尽量减少宏的使用,只有在必须的情况下才使用宏。可以用常规的 #include 和多文件结构来处理不同平台的差异,尽量保持每个平台的实现代码与其余平台代码相对独立,减少交叉。

总结

使用大量的 #if GAME_WIN32 等宏定义来进行平台控制是一种快速解决问题的方法,但它会导致代码的复杂性增加,维护性变差,并且容易带来一些调试和移植问题。通过合理使用跨平台库、抽象和动态链接等方式,可以有效提高代码的可移植性和可维护性,从而减少平台相关宏的使用,保持代码的简洁性和可扩展性。

在这里插入图片描述

这段代码体现了一个典型的 平台抽象层(Platform Abstraction Layer, PAL) 的设计模式。通过将平台特定的功能与核心游戏逻辑分开,代码变得更具可移植性。下面对这段代码的结构和模式进行详细解释:

1. 平台相关的实现与非平台相关的逻辑分离

在这种设计中,游戏的核心功能与平台相关的功能被分开,平台相关的代码被封装在不同的文件中,如 Win32_Game.cppLinux_Game.cpp。这样做的好处是,当移植到不同的平台时,只需要修改平台特定的部分,而不需要修改游戏的核心逻辑。

2. Win32_Game.cppLinux_Game.cpp 中的平台相关代码

这两份文件分别包含了平台特定的实现:

  • Win32_Game.cpp

    • PlatformLoadFile 函数是平台特定的实现,可能是用来加载文件的方法,这里你可以使用 Windows API,例如 CreateFileLoadLibrary 等。
    • WinMain 函数是 Windows 平台的入口点,所有的 Windows 应用程序都需要一个 WinMain 函数,而不是 main 函数。
  • Linux_Game.cpp

    • 这里的 PlatformLoadFile 实现可能使用 Linux 特有的文件加载方式,例如通过 open 系统调用等。

3. game.cpp 中的游戏逻辑

game.cpp 文件中包含了游戏的核心逻辑,和平台无关。MainLoop 函数负责游戏的主循环,游戏中的文件加载操作是通过 PlatformLoadFile 函数来实现的,但这个函数并不关心具体的实现,它只依赖于外部的定义。

game.cpp 中,PlatformLoadFile("foo.bmp") 是一个平台无关的调用。无论你是运行在 Windows 还是 Linux,PlatformLoadFile 都会根据不同的定义来调用不同的实现。

4. game.h 中的声明

game.h 中声明了 PlatformLoadFile 函数,并提供给 game.cpp 调用。这里通过 #pragma once 防止头文件重复包含。这样一来,game.cpp 就可以直接调用 PlatformLoadFile,而不需要关心具体平台的实现。

5. 平台抽象层(PAL)模式

这种模式有几个关键点:

  • 核心逻辑与平台相关实现分离:游戏的核心逻辑在 game.cpp 中实现,而平台相关的实现(例如文件加载、窗口管理等)则封装在 Win32_Game.cppLinux_Game.cpp 中。这种做法确保了平台无关的代码不会因为平台差异而发生变化。

  • 接口层(game.hgame.h 作为一个接口层,提供了一个统一的接口(如 PlatformLoadFile)供 game.cpp 调用。这样在 game.cpp 中无需了解平台差异,只需要依赖接口层。

  • 平台特定实现:每个平台的特定实现代码只在对应的 .cpp 文件中,减少了平台间的耦合度,使得移植代码时更加方便。你只需为新的平台编写一个新的 PlatformLoadFile 实现并确保它遵循统一接口即可。

6. 如何理解和使用这种模式

这种模式适合于跨平台应用开发,特别是游戏开发中的平台相关功能处理。它通过分离平台相关的代码与游戏核心逻辑,提高了代码的可移植性和可维护性。

例如,假设你现在想将这款游戏从 Windows 移植到 macOS 或 Android,你只需要为每个平台实现一个 PlatformLoadFile 函数,并且保持 game.cppgame.h 的不变。这样,你就不需要修改任何游戏逻辑代码。

总结

这种设计模式通过将平台相关的代码(如文件加载、窗口管理等)封装到不同的 .cpp 文件中,并且通过接口层暴露给游戏逻辑层,确保了游戏代码的跨平台可移植性。平台抽象层(PAL)有效地减少了平台之间的差异,使得在不同平台上运行相同的游戏变得更加简单和清晰。

把RenderWeirdGradient 包装到平台无关的game.cpp中

在这里插入图片描述

后面有讲一点excel用法

在这里插入图片描述

非平台相关

理解

  1. 四个主要功能
    • 时间管理(Timing):游戏循环中的时间控制,确保每一帧按预期时间运行,通常涉及帧率管理、定时器等。
    • 控制器/键盘输入(Controller/Keyboard Input):处理玩家通过控制器、键盘等输入设备与游戏交互的部分。
    • 位图缓冲区(Bitmap Buffer):涉及游戏渲染图像的缓存管理,通常用于存储当前画面图像的位图数据。
    • 声音缓冲区(Sound Buffer):用于存储游戏中的音效或背景音乐的声音数据缓冲区,可能涉及音频播放或处理。

这些是游戏开发中的核心部分,每一部分都涉及到与硬件、输入输出、渲染等相关的操作。

  1. TODO(casey):未来,渲染将特别变成一个三层抽象
    • 三层抽象(Three-tiered abstraction):这表示渲染系统将被设计成三个层次,通常指的是更细粒度的模块化分层,使得渲染过程更加灵活、可扩展。这可以理解为将渲染从底层硬件、图形API(如OpenGL、DirectX)和高层渲染逻辑(如渲染管线、场景管理)分开,以便未来能更方便地进行优化、扩展或更换技术栈。
    • “特别”:这个词强调渲染模块的复杂性,说明未来的设计会更加具体和具有针对性。

这段代码可能出现在一个正在开发的游戏引擎中,计划将渲染部分模块化,以便将来能够更加灵活地进行调整和扩展。

平台相关

/**
T这不是最终版本的平台层

  1. 存档位置
  2. 获取自己可执行文件的句柄
  3. 资源加载路径
  4. 线程(启动线程)
  5. 原始输入(支持多个键盘)
  6. Sleep/TimeBeginPeriod
  7. ClipCursor()(多显示器支持)
  8. 全屏支持
  9. WM_SETCURSOR(控制光标可见性)
  10. QueryCancelAutoplay
  11. WM_ACTIVATEAPP(当我们不是活动应用程序时)
  12. Blit速度优化(BitBlt)
  13. 硬件加速(OpenGL或Direct3D或两者?)
  14. GetKeyboardLayout(支持法语键盘、国际化WASD键支持)
    只是一个部分清单
    */

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

炼码LintCode--数据库题库(级别:入门;数量:144道)--刷题笔记_01

目录 炼码LintCode数据库入门级别的笔记未完待续~~~ 炼码LintCode 数据库 入门级别的笔记 笔记如下,把所有涉及到的入门级别的知识点简单总结了一下。 以及一点点举一反三的写法。 增 INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...);批量增 INSERT INT…

ab (Apache Bench)的使用

Apache Bench(ab)是一个用于基准测试HTTP Web服务器的命令行工具,广泛用于评估和优化Web服务器的性能。以下是关于Apache Bench的详细介绍,包括其功能、使用方法、常用参数和输出结果解析。 功能 性能测试:通过模拟多…

Cellebrite VS IOS18Rebooting

Cellebrite VS IOS18Rebooting我们想分享一些有关 iOS 18 重启“功能”的信息。在过去一周左右的时间里,人们对 iOS 18 中一项新的未记录功能产生了极大关注,该功能会导致设备在一段时间不活动后重新启动。 这意味着,如果设备在一定时间不活…

YZ系列工具之YZ10:VBA_梦幻图像

我给VBA下的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。我的教程一共九套一部VBA手册,教程分为初级、中级、高级三大部分。是对VBA的系统讲解,从简单的…

企业网络安全管理策略

随着互联网和信息技术的飞速发展,网络安全威胁日益严峻,企业若不加强网络安全管理,可能会面临数据泄露、系统崩溃等严重后果。为了帮助企业有效应对这些挑战,以下是网络安全专家为您整理的五个策略,以提升网络安全防护…

如何禁用VMware虚拟网卡

安装VMWare虚拟机之后,会在本地创建两个虚拟网卡VMware Network Adapter VMnet1和VMware Network Adapter VMnet8,如果使用iNode客户端联网时会进行禁用多网卡检测,否则无法联网。因此,问题根源就在于虚拟网卡未禁用。 1、网络和…

11.13机器学习_贝叶斯和决策树

八 朴素贝叶斯分类 1 贝叶斯分类理论 假设现在我们有一个数据集,它由两类数据组成,数据分布如下图所示: 我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中红色圆点表示的类别)的概率,用p2(x,y)表示数据点(x,y)属于类别2(图中蓝色…

Easyui ComboBox 数据加载完成之后过滤数据

Easyui ComboBox 数据加载完成之后过滤数据 需求 在ComboBox 下拉框中过滤包含"物联网"三个字的选项 现状 期望 实现方式 使用 combobox 的方法在加载时过滤 loadFilter 方式一&#xff1a;HTML中编写 <input id"enterpriseDepartmentCode" name&…

vue跳转传参

path 跳转只能使用 query 传参 ,name 跳转都可以 params &#xff1a;获取来自动态路由的参数 query &#xff1a;获取来自 search 部分的参数

div加4个角边框 css

效果&#xff1a; :root {--corner-color: #4ba7f5; } .data-item {position: relative;width: 100px;height: 60px;overflow: hidden;background: linear-gradient(to left, var(--corner-color), var(--corner-color)) left top no-repeat,linear-gradient(to bottom, var(-…

108. UE5 GAS RPG 实现地图名称更新和加载关卡

在这一篇里&#xff0c;我们将实现对存档的删除功能&#xff0c;在删除时会有弹框确认。接着实现获取玩家的等级和地图名称和存档位置&#xff0c;我们可以通过存档进入游戏&#xff0c;玩家在游戏中可以在存档点存储存档。 实现删除存档 删除存档需要一个弹框确认&#xff0…

CAN编程示例之socket CAN

socket CAN概念 socketcan子系统是在Linux下CAN协议(Controller Area Network)实现的一种实现方法。 CAN是一种在世界范围内广泛用于自动控制、嵌入式设备和汽车领域的网络技术。Linux下最早使用CAN的方法是基于字符设备来实现的&#xff0c;与之不同的是Socket CAN使用伯克利…

如何使用.bat实现检测电脑网络连接是否正常?

1、在电脑桌面新建一个记事本文档&#xff0c;将如下内容写进去&#xff1a; echo 正在检查中...echo off ping www.baidu.com -t pause:: 这是注释2、然后&#xff0c;保存一下&#xff0c;再把桌面此文件重命名为检查电脑外网连接.bat 3、双击此程序&#xff0c;可以检测…

C#高级:使用Invoke关键字通过 Type 类型调用指定的方法

demo如下&#xff1a; using System.Reflection; using System;public class Program {public class Calculator{public int Add(int a, int b){return a b;}}public class Student{public string Name { get; set; }}public class Example{// 泛型方法public string Generi…

VTK知识学习(8)-坐标系统

1、概述 计算机图形学里常用的坐标系统有4种&#xff1a; 1&#xff09;、Model坐标系统。定义模型时所采用的坐标系统&#xff0c;通常是局部的笛卡儿坐标系。 2&#xff09;、World坐标系统。是放置Actor的三维空间坐标系。 Actor&#xff08;vtkActor类&am…

MongoDB新版本安装配置教程(7.0.15版本-zip下载)

找了半天MongoDB新版本怎么解决没有mongo命令,都没有很好的解决方法 现在分享一下: 首先下载: 然后手动创建 data 和 log 两个文件夹 然后再系统变量配置环境变量 在data的目录下&#xff0c;创建一个db文件 然后:在bin目录下cmd执行: mongod --dbpath D:\MongoDB\data\db …

在Docker环境下为Nginx配置HTTPS

前言 配置HTTPS已经成为网站部署的必要步骤。本教程将详细介绍如何在Docker环境下为Nginx配置HTTPS&#xff0c;使用自签名证书来实现加密通信。虽然在生产环境中建议使用权威CA机构颁发的证书&#xff0c;但在开发测试或内网环境中&#xff0c;自签名证书是一个很好的选择。 …

QEMU 模拟器中运行的 Linux 系统

这两个文件通常用于在 QEMU 模拟器中运行的 Linux 系统&#xff0c;具体作用如下&#xff1a; 1. linux-aarch64-qemu.ext4&#xff1a; - **文件类型**&#xff1a;这是一个文件系统镜像文件&#xff0c;通常是 ext4 文件系统格式。 - **作用**&#xff1a;它包含了 Li…

Struts扫盲

Struts扫盲 这里的struts是struts1。以本文记录我的那些复习JavaEE的痛苦并快乐的晚上 Struts是什么 框架的概念想必大家都清楚&#xff0c;框架即“半成品代码”&#xff0c;是为了简化开发而设计的。一个项目有许多分层&#xff0c;拿一个MVC架构的Web应用来说&#xff0c;有…

【论文精读】GOT-OCR2.0源码论文——打破传统OCR流程的多模态视觉-语言大模型架构:预训练VitDet 视觉模型+ 阿里通义千问Qwen语言模型

作为本系列的开篇文章&#xff0c;首先定下本系列的整体基调。论文精读系列&#xff0c;旨在记录研读深度学习、强化学习相关论文的个人心得和理解&#xff0c;仅供参考&#xff0c;欢迎指正错误和研究探讨。 所有文章只会摘选论文部分进行分析&#xff0c;且不一定按原文行文顺…