游戏引擎从零开始(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

相关推荐
电报号dapp1195 小时前
链游系统定制化开发:引领游戏产业的新时代
游戏·机器人·去中心化·区块链
敲敲敲-敲代码6 小时前
游戏设计:推箱子【easyx图形界面/c语言】
c语言·开发语言·游戏
神仙别闹15 小时前
基本MFC类框架的俄罗斯方块游戏
c++·游戏·mfc
erxij1 天前
【游戏引擎之路】登神长阶(十四)——OpenGL教程:士别三日,当刮目相看
c++·经验分享·游戏·3d·游戏引擎
单音GG1 天前
推荐一个基于协程的C++(lua)游戏服务器
服务器·c++·游戏·lua
erxij2 天前
【游戏引擎之路】登神长阶(十三)——Vulkan教程:讲个笑话:离开舒适区
c++·经验分享·游戏·3d·游戏引擎
无敌最俊朗@2 天前
unity3d————Sprite(精灵图片)
学习·游戏·unity·c#·游戏引擎
IDC02_FEIYA3 天前
游戏服务器和普通服务器的区别
运维·服务器·游戏
虞书欣的63 天前
Python小游戏25——黄金矿工
开发语言·人工智能·游戏·小程序·pygame