/** * @file main.cpp * @brief Extra2D 图片显示示例 * * 演示如何使用 RenderBackend 抽象接口加载和显示图片 * 此示例不依赖任何特定渲染后端(如 OpenGL) */ #include #include #include #include #include #include #include #include #include #include using namespace extra2d; class ImageDisplayScene : public Scene { public: void onEnter() override { // 加载图片 // 注意:请确保有图片文件在 assets/images/ 目录下 try { texture_ = renderer_->loadTexture("assets/images/demo.jpg"); std::cout << "Image loaded successfully!" << std::endl; std::cout << " Size: " << texture_->getWidth() << "x" << texture_->getHeight() << std::endl; } catch (...) { std::cerr << "Failed to load image from assets/images/demo.jpg" << std::endl; // 尝试使用备用路径 try { texture_ = renderer_->loadTexture("examples/image_display/assets/images/demo.jpg"); std::cout << "Image loaded from alternate path!" << std::endl; } catch (...) { std::cerr << "Failed to load image from alternate path!" << std::endl; texture_ = nullptr; } } } void onExit() override { texture_.reset(); } void onRender(RenderBackend& renderer) override { Scene::onRender(renderer); if (!texture_) { return; } // 使用 RenderBackend 的抽象接口绘制图片 // 不依赖任何特定后端(如 OpenGL) // 自动批处理:无需手动调用 begin/endSpriteBatch // 计算图片显示位置(居中显示) float windowWidth = 1280.0f; float windowHeight = 720.0f; float imgWidth = static_cast(texture_->getWidth()); float imgHeight = static_cast(texture_->getHeight()); // 缩放图片以适应窗口(保持宽高比) float scale = 1.0f; if (imgWidth > windowWidth * 0.8f || imgHeight > windowHeight * 0.8f) { float scaleX = (windowWidth * 0.8f) / imgWidth; float scaleY = (windowHeight * 0.8f) / imgHeight; scale = std::min(scaleX, scaleY); } float displayWidth = imgWidth * scale; float displayHeight = imgHeight * scale; float x = (windowWidth - displayWidth) * 0.5f; float y = (windowHeight - displayHeight) * 0.5f; // 使用 RenderBackend 的 drawSprite 方法绘制图片 // 参数:纹理、目标矩形、源矩形、颜色、旋转角度、锚点 Rect destRect(x, y, displayWidth, displayHeight); Rect srcRect(0, 0, imgWidth, imgHeight); renderer.drawSprite(*texture_, destRect, srcRect, Colors::White, 0.0f, Vec2(0, 0)); // 注意:无需手动调用 renderer.endSpriteBatch(),帧结束时会自动刷新 } void setRenderer(RenderBackend* renderer) { renderer_ = renderer; } private: Ptr texture_; RenderBackend* renderer_ = nullptr; }; int main(int argc, char* argv[]) { (void)argc; (void)argv; std::cout << "Extra2D Image Display Demo - Starting..." << std::endl; Application& app = Application::get(); // 注册模块 app.use([](auto& cfg) { cfg.w = 1280; cfg.h = 720; cfg.title = "Extra2D Image Display 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; }