当前位置: 首页 > news >正文

Hazel游戏引擎(005)

本人菜鸟,文中若有代码、术语等错误,欢迎指正

我写的项目地址:https://github.com/liujianjie/GameEngineLightWeight(中文的注释适合中国人的你)

文章目录

  • 前言
  • 关键操作
  • 代码文件+关键代码+代码流程
    • 代码文件
    • 关键代码
      • extern外部定义CreateApplication
      • 包含头文件+条件编译和宏定义实现Dll导入与导出
    • 代码流程
  • 运行效果
  • Github
  • 涉及的C++知识

前言

  • 此节目的

    将上一小节的main函数入口点写在Hazel项目中,由引擎内部控制。

    优化dll导出导入代码,用条件编译+宏定义来编写dll导出与导入代码

  • Cherno本节完整代码链接

    https://github.com/TheCherno/Hazel/commit/f9fbbd2bf3d870a6586c5c4f70a867d78e27b113

关键操作

  • Hzel项目

    右键属性(所有配置)=>C/C++=>预处理器=>预处理器定义

    输入

    HZ_PLATFORM_WINDOWS;HZ_BUILD_DLL

  • Sandbox项目

    • 右键属性(所有配置)=>C/C++=>预处理器=>预处理器定义

      输入

      HZ_PLATFORM_WINDOWS;

    • 右键属性(所有配置)=>C/C++=>常规=>附加包含目录

      输入

      $(SolutionDir)Hazel\src

      为了Sandbox项目能引入Hazel项目的文件

      #include <Hazel.h>
      

代码文件+关键代码+代码流程

代码文件

  • Hazel项目

    • Application类

      引擎内部功能实现

    • Core.h

      来根据不同项目的条件编译,而写dll导入还是导出的宏定义

    • EntryPoint.h

      入口点,main函数

    • Hazel.h

      引入其它头文件,控制给Sandbox项目提供哪些引擎内部功能

  • Sandbox项目

    • SanboxApp.cpp

      应用层实现

关键代码

extern外部定义CreateApplication

  • 在Hazel项目的Application.h中

    namespace Hazel {class HAZEL_API Application{....};// To be defined in CLIENTApplication* CreateApplication();
    }
    

    在Hazel命名空间内声明了CreateApplication函数

  • 在Sandbox项目的SandboxApp.cpp中

    Hazel::Application* Hazel::CreateApplication()
    {return new Sandbox();
    }
    

    定义了CreateApplication函数

  • 在EntryPoint.h中调用

    extern Hazel::Application* Hazel::CreateApplication();
    int main(int argc, char** argv){auto app = Hazel::CreateApplication();...
    }
    

    将CreateApplication函数声明为extern,表示此函数会在外部定义,接下来使用的这函数时将使用在外部定义的CreateApplication

包含头文件+条件编译和宏定义实现Dll导入与导出

  • 在Core.h中

    #pragma once
    #ifdef HZ_PLATFORM_WINDOWS#ifdef HZ_BUILD_DLL#define HAZEL_API __declspec(dllexport)#else#define HAZEL_API __declspec(dllimport)#endif
    #else#error Hazel only supports Windows!
    #endif
    

    根据条件编译定义HAZEL_API是dll导入还是导出,由上的关键操作小点可知Hazel项目将是__declspec(dllexport),Sandbox项目是__declspec(dllimport)

  • 问题在于:这关Sandbox项目何事,这明明是Hazel项目中的头文件

    由于Sandbox#include <Hazel.h>,而Hazel项目的Hazel.h包含了Application.h,Application.h又包含了Core.h文件,

    所以这Core.h的代码也会被拷贝到Sandbox项目的SandboxApp.cpp中#include <Hazel.h>的位置,

    并且Application.h也会被拷贝到<Hazel.h>的位置。

    #include <Hazel.h>
    class Sandbox : public Hazel::Application
    {
    public:Sandbox(){}~Sandbox(){}
    };
    .....
    

    所以Sandbox项目也有HAZEL_API宏定义,且是__declspec(dllimport)

  • 所以SandboxApp.cpp的代码将变成

    #pragma once
    #ifdef HZ_PLATFORM_WINDOWS#ifdef HZ_BUILD_DLL#define HAZEL_API __declspec(dllexport)#else#define HAZEL_API __declspec(dllimport)#endif
    #else#error Hazel only supports Windows!
    #endif
    namespace Hazel {class HAZEL_API Application// HAZEL_API被替换成__declspec(dllimport){public:Application();virtual ~Application();void Run();};// To be defined in CLIENTApplication* CreateApplication();
    }
    ....省略EntryPoint.h的代码(下面将运行流程会有)....
    class Sandbox : public Hazel::Application
    {
    public:Sandbox(){}~Sandbox(){}
    };
    .....
    

    所以Sandbox类导入了dll中的Application类,且可以继承Application。

    对应003节的代码

    #pragma once
    namespace Hazel {_declspec(dllexport) void Print();// 导出
    }
    
    namespace Hazel {_declspec(dllimport) void Print(); // 导入
    }
    void main() {Hazel::Print();// 使用
    }
    

代码流程

  • 开始运行Sandbox.exe

    由于Sandbox中#include <Hazel.h>,而Hazel项目的Hazel.h包含了Application.h和EntryPoint.h入口文件

    Hazel.h

    #pragma once
    // For use by Hazel applications
    #include <iostream>
    #include "Hazel/Application.h"
    // ---Entry Point---------------------
    #include "Hazel/EntryPoint.h"
    // -----------------------------------
    
  • EntryPoint.h定义了main函数,即写了入口点,所以程序会在这运行

    因为SandboxApp.cpp在第一行包含Hazel.h,Hazel.h又包含EntryPoint.h,那么EntryPoint.h的代码会被拷贝到SandboxApp.cpp中

    #include <Hazel.h>
    

    将拥有以下EntryPoint.h中的代码

    #pragma once
    #ifdef HZ_PLATFORM_WINDOWS
    extern Hazel::Application* Hazel::CreateApplication();
    int main(int argc, char** argv)
    {std::cout << "Core::main" << std::endl;auto app = Hazel::CreateApplication();app->Run();delete app;
    }
    #endif
    

    main函数中执行CreateApplication函数,将调用定义在SandboxApp.cpp中的CreateApplication函数

    Hazel::Application* Hazel::CreateApplication()
    {return new Sandbox();
    }
    

    这函数返回的指针是Hazel项目中的Application父类指针,所以auto app的类型是Application*。

  • 当执行app->Run()函数时,由于Run()函数没有声明为虚函数,所以会调用Application中的Run()函数

    #include "Application.h"
    namespace Hazel {Application::Application(){}Application::~Application(){}void Application::Run(){while (true);}
    }
    

    Application的Run函数是一个while循环,所以循环会无限制运行中

运行效果

请添加图片描述

需要把最新生成的Hazel.dll放在Sandbox.exe文件夹下

请添加图片描述

Github

  • .gitignore

    在.git文件夹下新建.gitignore文件,可以声明一些不想提交到暂存区的文件

    # Binaries
    **/bin/
    bin-int/# Visual Studio files and folder
    .vs/
    **.sln
    **.vcxproj
    **.vcxproj.filters
    **.vcxproj.user
    **.csproj
    
  • 其它命令

    git add *// 提交文件到暂存区
    git reset . // 将暂存区文件返回
    git status // 查看文件有无提交到暂存区状态
    git commit -m "注释"// 将暂存区的内容添加到仓库
    git push origin main // 将本地的分支版本上传到远程并合并
    

涉及的C++知识

对应此节代码地方

Hazel::Application* Hazel::CreateApplication()
{return new Sandbox();
}
auto app = Hazel::CreateApplication();
app->Run();

转换为以下容易理解的代码

#include <iostream>
using namespace std;class Application {
public:void Run() {cout << "Application::Run()" << endl;}
};
class Sandbox : public Application {
public:void Run() {cout << "Sandbox::Run()" << endl;}
};
void main() {Application* app = new Sandbox();app->Run();// 由于Run()函数没有声明为virtual虚函数,所以执行父类的Run函数
}

请添加图片描述

相关文章:

Hazel游戏引擎(005)

本人菜鸟&#xff0c;文中若有代码、术语等错误&#xff0c;欢迎指正 我写的项目地址&#xff1a;https://github.com/liujianjie/GameEngineLightWeight&#xff08;中文的注释适合中国人的你&#xff09; 文章目录前言关键操作代码文件关键代码代码流程代码文件关键代码exter…...

牛客网Python篇数据分析习题(四)

1.现有一个Nowcoder.csv文件&#xff0c;它记录了牛客网的部分用户数据&#xff0c;包含如下字段&#xff08;字段与字段之间以逗号间隔&#xff09;&#xff1a; Nowcoder_ID&#xff1a;用户ID Level&#xff1a;等级 Achievement_value&#xff1a;成就值 Num_of_exercise&a…...

盲盒如何创业?

所谓的“盲盒”&#xff0c;受众群体大部分是那些爱碰运气的人&#xff0c;顾客买的是那种在打开盲盒时一刹那的惊喜感和神秘感&#xff0c;在打开盲盒之前&#xff0c;谁也不知道自己会得到什么&#xff0c;这也是为什么消费者更愿意购买的原因。网上的盲盒&#xff0c;主要是…...

第1集丨Java中面向对象相关概念汇总

目录一、基本概念1.1 类1.2 属性1.3 方法1.4 静态1.5 包1.6 import二、高级概念2.1 构造方法2.2 继承2.3 super & this2.4 多态2.5 方法重载2.6 方法重写2.7 访问权限2.8 内部类2.9 final2.10 抽象2.11 接口2.12 匿名类面向对象的编程思想力图使计算机语言中对事物的描述与…...

高性能(二)

三、读写分离和分库分表 1.读写分离 1.1 概述 将数据库的读写操作分散到不同的数据库节点上 通常一主多从一台主数据库负责写&#xff0c;多台从数据库负责读。 主库和从库之间会进行数据同步&#xff0c;以保证从库中数据的准确性。 1.2 问题及解决 1.2.1 问题 主从同…...

Allegro如何实现同一个屏幕界面分屏显示操作指导

Allegro如何实现同一个屏幕界面分屏显示操作指导 在做PCB设计的时候,会需要分屏显示,比如一边是放大的视图,另外一边是缩小的视图,Allegro支持同一个屏幕界面下进行分屏显示,如下图 而且会实时同步起来 如何分屏,具体操作如下 点击View...

前后端一些下载与配置(第二篇 第10天过后)nuxt banner redis 短信服务

NUXT 应该是不用怎么装&#xff1f; 有现成的 axios 还需要在npm吗 好像已经有现成的了 banner banner 笔记汇总P396 Redis Linux安装redis tar -xzvf redis-6.2.6.tar.gz cd redis-6.2.6 照着他做 然后 cd /usr/local/redis/bin ./redis-server /usr/local/redis…...

OSG三维渲染引擎编程学习之四十八:“第五章:OSG场景渲染” 之 “5.6 多重纹理映射”

目录 第五章 OSG场景渲染 5.6 多重纹理映射 5.6.1 多重纹理映射介绍 5.6.2 多重纹理映射示例...

对Node.js 的理解?优缺点?应用场景?

一、是什么 Node.js 是一个开源与跨平台的 JavaScript 运行时环境 在浏览器外运行 V8 JavaScript 引擎&#xff08;Google Chrome 的内核&#xff09;&#xff0c;利用事件驱动、非阻塞和异步输入输出模型等技术提高性能 可以理解为 Node.js 就是一个服务器端的、非阻塞式I/…...

Bean的生命周期

所谓的生命周期指的是一个对象从诞生到销毁的整个生命过程&#xff0c;我们把这个过程就叫做一个对象的生命周期~~ Bean的生命周期分为以下五大部分&#xff1a; 实例化&#xff08;为 Bean 分配内存空间&#xff09; 设置属性&#xff08;Bean对象注入/装配&#xff09; 初…...

Python学习-----函数2.0(函数对象,名称空间,作用域-->全局变量与局部变量)

目录 前言&#xff1a; 1.函数对象 &#xff08;1&#xff09;函数对象的引用 &#xff08;2&#xff09;函数可以放到序列里面 &#xff08;3&#xff09;函数可以作为参数 &#xff0c; 传递给另一个函数 2.名称空间 3.作用域 &#xff08;1&#xff09;作用域的理解 …...

Java中Json字符串和Java对象的互转

JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式。诞生于 2002 年。易于人阅读和编写。同时也易于机器解析和生成。JSON 是目前主流的前后端数据传输方式。 JSON 采用完全独立于语言的文本格式&#xff0c;但是也使用了类似于 C 语言家族的…...

代码随想录NO42 | 动态规划_Leetcode70. 爬楼梯 (进阶) 322. 零钱兑换 279.完全平方数

动态规划_Leetcode70. 爬楼梯 &#xff08;进阶&#xff09; 322. 零钱兑换 279.完全平方数70. 爬楼梯 &#xff08;进阶&#xff09; 在原题基础上&#xff0c;改为&#xff1a;一步一个台阶&#xff0c;两个台阶&#xff0c;三个台阶&#xff0c;…&#xff0c;直到 m个台阶…...

【C++从入门到放弃】初识C++(基础知识入门详解)

&#x1f9d1;‍&#x1f4bb;作者&#xff1a; 情话0.0 &#x1f4dd;专栏&#xff1a;《C从入门到放弃》 &#x1f466;个人简介&#xff1a;一名双非编程菜鸟&#xff0c;在这里分享自己的编程学习笔记&#xff0c;欢迎大家的指正与点赞&#xff0c;谢谢&#xff01; C基础…...

企业工程项目管理系统源码+spring cloud 系统管理+java 系统设置+二次开发

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…...

【GPLT 三阶题目集】L3-016 二叉搜索树的结构

二叉搜索树或者是一棵空树&#xff0c;或者是具有下列性质的二叉树&#xff1a; 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值&#xff1b;若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结点的值&#xff1b;它的左、右子树也分…...

核心交换机安全多业务高性能万兆交换机

RG-S5750-24SFP/12GT交换机是锐捷网络推出的融合了高性能、高安全、多业务的新一代三层交换机。RG-S5750-24SFP/12GT 交换机能够提供灵活的介质接口&#xff0c;满足网络建设中不同介质的连接需要。全千兆的端口形态&#xff0c;加上可扩展的高密度万兆端口&#xff0c;提供1&a…...

Android APK 签名打包原理分析(三)【静默安装的实现方案】

背景 小编目前从事的系统定制类工作,有客户提出了,需要后台“静默安装”他们的app,也就是悄无声息的安装,而且特别强调,不可以跳出任何安装引导页面,他们的app下载完成之后,后台调用公开的android install代码,系统就后台完成安装,安装完成之后,重新打开应用就可以。…...

mulesoft MCIA 破釜沉舟备考 2023.02.14.05

mulesoft MCIA 破釜沉舟备考 2023.02.14.05 1. Refer to the exhibit.2. A Kubernetes controller automatically adds another pod replica to the resource pool in response to increased application load.3. An XA transaction Is being configured that involves a JMS c…...

结构体的三种定义方法、结构体类型名(可选标志符)什么时候可以省略

结构体的三种定义方法 一、单独定义&#xff1a; 先定义结构体类型&#xff0c;再定义变量   定义结构体的格式如下&#xff1a;    struct 结构体名 {    若干数据项&#xff1b;    } &#xff1b;   其中&#xff0c;struct为关键字&#xff1b; 结构体名是用户定…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

鸿蒙HarmonyOS 5军旗小游戏实现指南

1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;采用DevEco Studio实现&#xff0c;包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...

STL 2迭代器

文章目录 1.迭代器2.输入迭代器3.输出迭代器1.插入迭代器 4.前向迭代器5.双向迭代器6.随机访问迭代器7.不同容器返回的迭代器类型1.输入 / 输出迭代器2.前向迭代器3.双向迭代器4.随机访问迭代器5.特殊迭代器适配器6.为什么 unordered_set 只提供前向迭代器&#xff1f; 1.迭代器…...