游戏引擎从零开始(3)-日志系统spdlog

前言

日志系统是所有程序中的刚需,本章节将开源的spdlog集成到引擎中。

spdlog是一个只有头文件,性能很好的C++日志库

集成spdlog

spdlog以submodule的形式集成到项目中。

所有的第三方库我们放到/Sanbox/Hazel/vendor下面

vendor供应商的意思,也可以表示第三方库

download spdlog

在项目根目录下执行下面命令:

bash 复制代码
git submodule add https://github.com/gabime/spdlog.git Sanbox/Hazel/vendor/spdlog

在根目录下会生成一个.gitmodules文件,而spdlog并不会加入到本项目的git记录中。

.gitmodules

ini 复制代码
[submodule "Sandbox/Hazel/vendor/spdlog"]
	path = Sandbox/Hazel/vendor/spdlog
	url = https://github.com/gabime/spdlog.git

增加了一些ignore

Hazel/.gitignore

bash 复制代码
/Sandbox/cmake-build-debug/
.idea/
build

更新Hazel引擎的CMake

更新CMake文件,增加spdlog引用

参考diff,修改的地方一目了然

实现Log封装

Log.h

声明两个静态的log实例,分别用于引擎内核的日志打印,和业务层的日志打印。这样做可以设置不同的tag,以及设置不同的日志策略。

两个Log对应两个静态的获取实例的函数。

c++ 复制代码
namespace Hazel {
    class Log {
    public:

        static void Init();

        inline static std::shared_ptr<spdlog::logger>& GetCoreLogger(){
            return s_CoreLogger;
        }

        inline static std::shared_ptr<spdlog::logger>& GetClientLogger(){
            return s_ClientLogger;
        };

    private:
        static std::shared_ptr<spdlog::logger> s_CoreLogger;
        static std::shared_ptr<spdlog::logger> s_ClientLogger;
    };
}

Log.cpp中初始化spdlog。

spdlog的使用可以参考官方文档,有详细的说明,此处不做展开spdlog文档

c++ 复制代码
#include "Log.h"

namespace Hazel{
    std::shared_ptr<spdlog::logger> Log::s_CoreLogger;
    std::shared_ptr<spdlog::logger> Log::s_ClientLogger;

    void Log::Init() {
        spdlog::set_pattern("%^[%T] %n : %v%$");
        Log::s_CoreLogger = spdlog::stdout_color_mt("HAZEL", spdlog::color_mode::always);
        Log::s_CoreLogger->set_level(spdlog::level::trace);

        Log::s_ClientLogger = spdlog::stdout_color_mt("APP", spdlog::color_mode::always);
        Log::s_ClientLogger->set_level(spdlog::level::trace);
    }
}

这里我们两个日志等级都设置成trace级别,tag分别设置为"HAZEL"和"APP"

注意,C++中,静态变量定义和声明需要分开写。

如Log::s_CoreLogger和Log::s_ClientLogger声明和定义。

Hazel.h文件中增加Log.h的引用

c++ 复制代码
#ifndef SANBOX_HAZEL_H
#define SANBOX_HAZEL_H

#include <stdio.h>
#include "Hazel/Application.h"
#include "Hazel/Log.h"

// -----Entry Point-------
#include "Hazel/EntryPoint.h"

#endif //SANBOX_HAZEL_H

Log的使用及优化

回到EntryPoint.h文件中,使用Log打印日志

c++ 复制代码
int main(int argc, char** argv) {
    Hazel::Log::Init();
    Hazel::Log::GetCoreLogger()->warn("Initialized Log!");
    Hazel::Log::GetClientLogger()->info("Hello!");

    auto app = Hazel::CreateApplication();
    app->Run();
    delete app;
}

可以看到虽然可以用了,但是打印一行日志的代码有点啰嗦,用宏定义简化。

回到Log.h中,在末尾增加宏定义

c++ 复制代码
// Core log macros
#define HZ_CORE_TRACE(...)  ::Hazel::Log::GetCoreLogger()->trace(__VA_ARGS__)
#define HZ_CORE_INFO(...)   ::Hazel::Log::GetCoreLogger()->info(__VA_ARGS__)
#define HZ_CORE_WARN(...)   ::Hazel::Log::GetCoreLogger()->warn(__VA_ARGS__)
#define HZ_CORE_ERROR(...)  ::Hazel::Log::GetCoreLogger()->error(__VA_ARGS__)
#define HZ_CORE_FATAL(...)  ::Hazel::Log::GetCoreLogger()->fatal(__VA_ARGS__)


// Client log macros
#define HZ_TRACE(...)  ::Hazel::Log::GetClientLogger()->trace(__VA_ARGS__)
#define HZ_INFO(...)   ::Hazel::Log::GetClientLogger()->info(__VA_ARGS__)
#define HZ_WARN(...)   ::Hazel::Log::GetClientLogger()->warn(__VA_ARGS__)
#define HZ_ERROR(...)  ::Hazel::Log::GetClientLogger()->error(__VA_ARGS__)
#define HZ_FATAL(...)  ::Hazel::Log::GetClientLogger()->fatal(__VA_ARGS__)

EntryPoint.h中的调用就简单多了

c++ 复制代码
int main(int argc, char** argv) {
    Hazel::Log::Init();
//    Hazel::Log::GetCoreLogger()->warn("Initialized Log!");
//    Hazel::Log::GetClientLogger()->info("Hello!");
    HZ_CORE_WARN("Initialed Log!");
    int a = 5;
    HZ_INFO("Hello! Var={0}", a);

    auto app = Hazel::CreateApplication();
    app->Run();
    delete app;
}

基于宏定义的日志除了简化调用逻辑,还有个重要的作用,区分不同包做不同的逻辑,比如在正式版本不希望打印调试日志,可以增加宏定义:

#define HZ_TRACE(...)

这样预编译的时候替换成空,相当于什么都没干。

完整代码commit参考:

commit-include spdlog into Hazel

相关推荐
汝生淮南吾在北2 小时前
SpringBoot+Vue游戏攻略网站
前端·vue.js·spring boot·后端·游戏·毕业设计·毕设
weixin_307779133 小时前
满足游戏应用低延迟和历史查询需求的解决方案
游戏·云原生·架构·云计算·aws
da_vinci_x3 小时前
PS 图案预览 + Sampler:告别“修接缝”,AI 量产 4K 无缝 PBR
人工智能·游戏·aigc·贴图·技术美术·游戏美术·法线贴图
SmalBox5 小时前
【基础】UnityShader Graph 的编辑器介绍
unity3d·游戏开发·图形学
摘星编程7 小时前
从云游戏到Mac远程操控:UU远程游戏、办公场景全覆盖
游戏·macos·uu远程
wanhengidc1 天前
云手机 网络连接与持续性的表现如何
运维·服务器·科技·游戏·智能手机
无限进步_1 天前
C语言实现贪吃蛇游戏详解
c语言·开发语言·数据结构·c++·后端·算法·游戏
wanhengidc1 天前
云手机深度解析其原理与功能
服务器·科技·游戏·智能手机
TTGGGFF1 天前
人工智能:用 Gemini3 一键生成视觉炸裂的粒子躲避游戏!流体粒子 + 渐变流光全实现
人工智能·游戏
SmalBox1 天前
【基础】Unity着色器编程的语言和数学基础介绍
unity3d·游戏开发·图形学