diff --git a/Extra2D/include/extra2d/scene/transition_box_scene.h b/Extra2D/include/extra2d/scene/transition_box_scene.h index de9ed25..c48b481 100644 --- a/Extra2D/include/extra2d/scene/transition_box_scene.h +++ b/Extra2D/include/extra2d/scene/transition_box_scene.h @@ -26,7 +26,7 @@ public: protected: void onTransitionStart() override; void renderContent(RenderBackend &renderer) override; - void updateTransition(float dt); + void updateTransition(float dt) override; private: int divisions_; diff --git a/Extra2D/include/extra2d/scene/transition_flip_scene.h b/Extra2D/include/extra2d/scene/transition_flip_scene.h index fa470ff..116529e 100644 --- a/Extra2D/include/extra2d/scene/transition_flip_scene.h +++ b/Extra2D/include/extra2d/scene/transition_flip_scene.h @@ -29,7 +29,7 @@ public: protected: void onTransitionStart() override; void renderContent(RenderBackend &renderer) override; - void updateTransition(float dt); + void updateTransition(float dt) override; private: Axis axis_; diff --git a/Extra2D/include/extra2d/scene/transition_scale_scene.h b/Extra2D/include/extra2d/scene/transition_scale_scene.h index cad1948..59628a7 100644 --- a/Extra2D/include/extra2d/scene/transition_scale_scene.h +++ b/Extra2D/include/extra2d/scene/transition_scale_scene.h @@ -24,7 +24,7 @@ public: protected: void onTransitionStart() override; void renderContent(RenderBackend &renderer) override; - void updateTransition(float dt); + void updateTransition(float dt) override; }; } // namespace extra2d diff --git a/Extra2D/include/extra2d/scene/transition_slide_scene.h b/Extra2D/include/extra2d/scene/transition_slide_scene.h index 7775182..7457c64 100644 --- a/Extra2D/include/extra2d/scene/transition_slide_scene.h +++ b/Extra2D/include/extra2d/scene/transition_slide_scene.h @@ -27,7 +27,7 @@ public: protected: void onTransitionStart() override; void renderContent(RenderBackend &renderer) override; - void updateTransition(float dt); + void updateTransition(float dt) override; private: TransitionDirection direction_; diff --git a/README.md b/README.md index 2d101ff..f44e230 100644 --- a/README.md +++ b/README.md @@ -407,6 +407,7 @@ eventService->addListener(EventType::GamepadButtonPressed, [](Event& e) { | 示例 | 说明 | |-----|------| | `demo_basic` | 基础示例:场景图、输入事件、视口适配 | +| `demo_text_rendering` | 文字渲染示例:使用 GLFontAtlas 渲染文字 | 运行示例: diff --git a/examples/text_rendering/assets/fonts/arial.ttf b/examples/text_rendering/assets/fonts/arial.ttf new file mode 100644 index 0000000..8682d94 Binary files /dev/null and b/examples/text_rendering/assets/fonts/arial.ttf differ diff --git a/examples/text_rendering/main.cpp b/examples/text_rendering/main.cpp new file mode 100644 index 0000000..d09152f --- /dev/null +++ b/examples/text_rendering/main.cpp @@ -0,0 +1,206 @@ +/** + * @file main.cpp + * @brief Extra2D 文字渲染示例 + * + * 演示如何使用 GLFontAtlas 渲染文字 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace extra2d; + +class TextRenderingScene : public Scene { +public: + void onEnter() override { + // 加载字体 + // 注意:请确保有字体文件在 assets/fonts/ 目录下 + // 如果没有,可以使用系统字体路径 + try { + font_ = std::make_shared("assets/fonts/arial.ttf", 24); + } catch (...) { + std::cerr << "Failed to load font from assets/fonts/arial.ttf" + << std::endl; + // 尝试使用备用路径 + try { + font_ = std::make_shared("C:/Windows/Fonts/arial.ttf", 24); + } catch (...) { + std::cerr << "Failed to load font from system path!" << std::endl; + font_ = nullptr; + } + } + + if (font_) { + std::cout << "Font loaded successfully!" << std::endl; + std::cout << " Font size: " << font_->getFontSize() << std::endl; + std::cout << " Line height: " << font_->getLineHeight() << std::endl; + std::cout << " Ascent: " << font_->getAscent() << std::endl; + std::cout << " Descent: " << font_->getDescent() << std::endl; + } + } + + void onExit() override { font_.reset(); } + + void onRender(RenderBackend &renderer) override { + Scene::onRender(renderer); + + if (!font_) { + return; + } + + // 获取渲染器 + auto *glRenderer = dynamic_cast(&renderer); + if (!glRenderer) { + return; + } + + // 开始精灵批处理 + glRenderer->beginSpriteBatch(); + + float y = 100.0f; + float x = 100.0f; + + // 渲染标题 + renderText(glRenderer, "Extra2D Text Rendering Demo", x, y, + Color(1.0f, 0.8f, 0.2f, 1.0f)); + y += font_->getLineHeight() * 2; + + // 渲染不同颜色的文字 + renderText(glRenderer, "Red Text", x, y, Color(1.0f, 0.2f, 0.2f, 1.0f)); + y += font_->getLineHeight(); + + renderText(glRenderer, "Green Text", x, y, Color(0.2f, 1.0f, 0.2f, 1.0f)); + y += font_->getLineHeight(); + + renderText(glRenderer, "Blue Text", x, y, Color(0.2f, 0.2f, 1.0f, 1.0f)); + y += font_->getLineHeight() * 2; + + // 渲染多行文字 + renderText(glRenderer, "This is a multi-line text example.", x, y, + Color(1.0f, 1.0f, 1.0f, 1.0f)); + y += font_->getLineHeight(); + renderText(glRenderer, "You can render text with different colors", x, y, + Color(0.8f, 0.8f, 0.8f, 1.0f)); + y += font_->getLineHeight(); + renderText(glRenderer, "and styles using GLFontAtlas.", x, y, + Color(0.6f, 0.6f, 0.6f, 1.0f)); + y += font_->getLineHeight() * 2; + + // 渲染半透明文字 + renderText(glRenderer, "Semi-transparent text (50% opacity)", x, y, + Color(1.0f, 1.0f, 1.0f, 0.5f)); + y += font_->getLineHeight() * 2; + + // 渲染操作提示 + renderText(glRenderer, "Press ESC to exit", x, y, + Color(0.5f, 0.5f, 0.5f, 1.0f)); + + // 结束精灵批处理 + glRenderer->endSpriteBatch(); + } + +private: + void renderText(GLRenderer *renderer, const std::string &text, float x, + float y, const Color &color) { + if (!font_ || !renderer) { + return; + } + + // 使用渲染器的 drawText 方法 + renderer->drawText(*font_, text, Vec2(x, y), color); + } + + std::shared_ptr font_; +}; + +int main(int argc, char *argv[]) { + (void)argc; + (void)argv; + + std::cout << "Extra2D Text Rendering Demo - Starting..." << std::endl; + + Application &app = Application::get(); + + // 注册模块 + app.use([](auto &cfg) { + cfg.w = 1280; + cfg.h = 720; + cfg.title = "Extra2D Text Rendering Demo"; + cfg.priority = 0; + cfg.backend = "glfw"; + }); + + app.use([](auto &cfg) { cfg.priority = 10; }); + + app.use([](auto &cfg) { cfg.priority = 20; }); + + std::cout << "Initializing application..." << std::endl; + if (!app.init()) { + std::cerr << "Failed to initialize application!" << std::endl; + return -1; + } + + std::cout << "Application initialized successfully!" << std::endl; + + auto *win = app.window(); + if (win) { + std::cout << "Window: " << win->width() << "x" << win->height() + << std::endl; + } + + // 设置事件监听 + auto eventService = ServiceLocator::instance().getService(); + if (eventService) { + eventService->addListener(EventType::KeyPressed, [](Event &e) { + auto &keyEvent = std::get(e.data); + if (keyEvent.keyCode == static_cast(Key::Escape)) { + e.handled = true; + Application::get().quit(); + } + }); + } + + // 创建并配置场景 + auto scene = makeShared(); + scene->setBackgroundColor(Color(0.1f, 0.1f, 0.15f, 1.0f)); + + if (win) { + scene->setViewportSize(static_cast(win->width()), + static_cast(win->height())); + } + + // 配置相机 + auto cameraService = ServiceLocator::instance().getService(); + if (cameraService && win) { + ViewportConfig vpConfig; + vpConfig.logicWidth = static_cast(win->width()); + vpConfig.logicHeight = static_cast(win->height()); + vpConfig.mode = ViewportMode::AspectRatio; + cameraService->setViewportConfig(vpConfig); + cameraService->updateViewport(win->width(), win->height()); + cameraService->applyViewportAdapter(); + } + + app.enterScene(scene); + + std::cout << "\nControls:" << std::endl; + std::cout << " ESC - Exit" << std::endl; + std::cout << "\nRunning main loop...\n" << std::endl; + + app.run(); + + std::cout << "Shutting down..." << std::endl; + app.shutdown(); + + std::cout << "Goodbye!" << std::endl; + return 0; +} diff --git a/xmake.lua b/xmake.lua index 4231541..0a3bd00 100644 --- a/xmake.lua +++ b/xmake.lua @@ -202,6 +202,65 @@ target("demo_basic") after_build(install_shaders) target_end() +-- 文字渲染示例 +target("demo_text_rendering") + set_kind("binary") + set_default(false) + + add_deps("extra2d") + add_files("examples/text_rendering/main.cpp") + + -- 平台配置 + local plat = get_config("plat") or os.host() + local backend = get_config("window_backend") or "sdl2" + if plat == "mingw" or plat == "windows" then + add_packages("glm", "nlohmann_json") + if backend == "glfw" then + add_packages("glfw") + else + add_packages("libsdl2") + end + add_syslinks("opengl32", "glu32", "winmm", "imm32", "version", "setupapi") + elseif plat == "linux" then + add_packages("glm", "nlohmann_json") + if backend == "glfw" then + add_packages("glfw") + else + add_packages("libsdl2") + end + add_syslinks("GL", "dl", "pthread") + elseif plat == "macosx" then + add_packages("glm", "nlohmann_json") + if backend == "glfw" then + add_packages("glfw") + else + add_packages("libsdl2") + end + add_frameworks("OpenGL", "Cocoa", "IOKit", "CoreVideo") + end + + -- 构建后安装Shader文件和assets + after_build(function (target) + -- 安装shaders + local plat = get_config("plat") or os.host() + local targetdir = target:targetdir() + local shader_src = "Extra2D/shaders" + local shader_dest = path.join(targetdir, "shaders") + os.rm(shader_dest) + os.cp(shader_src, shader_dest) + print("Shaders installed to: " .. shader_dest) + + -- 复制assets目录 + local assets_src = "examples/text_rendering/assets" + local assets_dest = path.join(targetdir, "assets") + if os.exists(assets_src) then + os.rm(assets_dest) + os.cp(assets_src, assets_dest) + print("Assets installed to: " .. assets_dest) + end + end) +target_end() + -- Hello Module 示例 - 展示如何创建自定义模块 target("demo_hello_module") set_kind("binary")