ImGui 集成到 axmol 引擎

最近研究接触了下ImGui, 发现这货结合Cocos2d-x系列引擎写游戏工具非常方便,据笔者分析,有如下优点:

  • 不会污染游戏逻辑
  • 复用游戏场景功能
  • 无需美术提供工具资源,自动布局的菜单按钮,程序员轻松搞定
  • 非常丰富的控件,可以写出非常易用的游戏工具,提高工具使用者体验和效率
  • C++可用宏来控制,避免release游戏将GM工具发布出去了

于是笔者产生了将ImGui集成到axmol引擎中的想法,本着复用原则,笔者先在github搜索一番,按stars数量排序(搜索优秀开源库的基本方法),点击查看搜索结果,按照常规,自然先使用了 c0iimguix: https://github.com/c0i/imguix,但这个最是基于3.17.1的,而axmol是基于cocos2d-x-4.0发展而来,因此经过简单修改,笔者使其支持了axmol,并给作者提了PR: https://github.com/c0i/imguix/pull/32

如果到此为止,也就是简单集成而已,但经过多番查看github相关issues,发现imguix不支持mutli-view-ports,与此同时也通过github了解到imgui官方仓库的docking分支,是支持mutli-viewports的,也就是说ImGui的窗口可以拖出游戏窗口之外,因此笔者找到了这个仓库: https://github.com/Xrysnow/cocos2d-x-imgui,通过简单了解发现,这个貌似也是基于imguix优化的版本,在imguix的基础上基于imgui官方仓库的docking分支,同时master分支主要支持cocos2d-x-4.0,于是笔者经过简单的修改,成功将该版本集成为axmol的扩展,同时做了如下重点优化:

  • Mac平台Mutli-Viewports拖动时导致游戏界面黑屏,因此禁用(tips: 跑了imgui官方的示例,也无法拖出主窗口之外)
  • 整理扩展管理单利类,重命名为: ImGuiPresenter
  • 修正概念ImGuiLayer其实仅仅做事件跟踪监测,并无实际渲染功能,因此重构为ImGuiEventTracker并隐藏到扩展本身,不暴露给外部
  • 重构为ImGuiPresenter的addRenderLoop/removeRenderLoop接口来管理ImGui的渲染循环
  • 提供非常简单易用的字体管理接口addFont,removeFont,clearFonts
  • 优化ImGui的beginFrame, endFrame时机,使用者可以在addRenderLoop的渲染循环里处理ImGui的控件逻辑来直接安全地添加或删除游戏场景里的对象,有效避免迭代器被破坏
  • 优化ImGuiPresenter单利的生命周期管理,准确清理和初始化ImGui Context,避免destroyInstance后,再次ImGuiPresenter::getInstacne使用时奔溃
  • DPI缩放支持 API: ImGuiPresenter::getInstance()->scaleAllByDPI(1.0);
  • 在扩展内部自己计算需要赋值给ImGui::GetIO()的deltaTime,以避免暂停``Director```后,ImGui报错
  • 其他代码优化

Tips: 这里有个小点,就是之前版本axmol或者cocos系列引擎,在Director暂停后会将帧率限制特别低,导致ImGui作为游戏内嵌工具的窗口拖动特别慢,笔者认为完全没必要,因此笔者加了宏来控制,详见:https://github.com/axmolengine/axmol/commit/2d5fb7f77d671b3bb0f7ee5a4ded0e4fca2b8178

有了以上优化,axmol的ImGuiPresenter才真正达到易用和稳定性的程度,用法如下:

#include "ImGui/ImGuiPresenter.h"
USING_NS_AX;
USING_NS_AX_EXT;

class GameScene : public Scene {
public:
    void onEnter() override
    {
        Scene::onEnter();
        ImGuiPresenter::getInstance()->addRenderLoop("#im01", CC_CALLBACK_0(GameScene::onImGuiDraw, this), this);
    }
    void onExit() override
    {
        ImGuiPresenter::getInstance()->removeRenderLoop("#im01");
        Scene::onExit();
    }
    void onImGuiDraw()
    {
        ImGui::Begin("window");
        ImGui::Text("FPS=%.1f", 1.f / ImGui::GetIO().DeltaTime);
        ImGui::End();
    }
}

另外axmol同时也写了test case,可以直接按照编译步骤跑ImGui的使用用例,效果如下

ImGui 集成到 axmol 引擎_第1张图片

怎么样,是不是非常简单,赶紧下载体验吧

  • https://github.com/axmolengine/axmol/tree/master/extensions/ImGui
  • https://github.com/ocornut/imgui

非常感谢github的前辈们提供的cocos2dx imgui实现版本:

  • https://github.com/c0i/imguix
  • https://github.com/Xrysnow/cocos2d-x-imgui

你可能感兴趣的:(游戏引擎,cocos2d,c++,imgui,axmol)