/** * @file main.cpp * @brief Extra2D 文字渲染示例 * * 演示如何使用 RenderBackend 抽象接口渲染文字 * 此示例不依赖任何特定渲染后端(如 OpenGL) */ #include #include #include #include #include #include #include #include #include #include using namespace extra2d; class TextRenderingScene : public Scene { public: void onEnter() override { // 加载字体 // 注意:请确保有字体文件在 assets/fonts/ 目录下 // 如果没有,可以使用系统字体路径 if (!renderer_) { std::cerr << "Renderer not available!" << std::endl; return; } try { font_ = renderer_->createFontAtlas("assets/fonts/arial.ttf", 24); } catch (...) { std::cerr << "Failed to load font from assets/fonts/arial.ttf" << std::endl; // 尝试使用备用路径 try { font_ = renderer_->createFontAtlas("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; } float y = 100.0f; float x = 100.0f; // 渲染标题(自动批处理,无需手动调用 begin/end) renderText(renderer, "Extra2D Text Rendering Demo", x, y, Color(1.0f, 0.8f, 0.2f, 1.0f)); y += font_->getLineHeight() * 2; // 渲染不同颜色的文字 renderText(renderer, "Red Text", x, y, Color(1.0f, 0.2f, 0.2f, 1.0f)); y += font_->getLineHeight(); renderText(renderer, "Green Text", x, y, Color(0.2f, 1.0f, 0.2f, 1.0f)); y += font_->getLineHeight(); renderText(renderer, "Blue Text", x, y, Color(0.2f, 0.2f, 1.0f, 1.0f)); y += font_->getLineHeight() * 2; // 渲染多行文字 renderText(renderer, "This is a multi-line text example.", x, y, Color(1.0f, 1.0f, 1.0f, 1.0f)); y += font_->getLineHeight(); renderText(renderer, "You can render text with different colors", x, y, Color(0.8f, 0.8f, 0.8f, 1.0f)); y += font_->getLineHeight(); renderText(renderer, "and styles using FontAtlas.", x, y, Color(0.6f, 0.6f, 0.6f, 1.0f)); y += font_->getLineHeight() * 2; // 渲染半透明文字 renderText(renderer, "Semi-transparent text (50% opacity)", x, y, Color(1.0f, 1.0f, 1.0f, 0.5f)); y += font_->getLineHeight() * 2; // 渲染操作提示 renderText(renderer, "Press ESC to exit", x, y, Color(0.5f, 0.5f, 0.5f, 1.0f)); // 注意:无需手动调用 renderer.endSpriteBatch(),帧结束时会自动刷新 } void setRenderer(RenderBackend* renderer) { renderer_ = renderer; } private: void renderText(RenderBackend &renderer, const std::string &text, float x, float y, const Color &color) { if (!font_) { return; } // 使用 RenderBackend 的 drawText 方法 renderer.drawText(*font_, text, Vec2(x, y), color); } Ptr font_; RenderBackend* renderer_ = nullptr; }; 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(); } }); } // 获取渲染器 RenderBackend* renderer = app.renderer(); // 创建并配置场景 auto scene = makeShared(); scene->setRenderer(renderer); 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; }