#include #include #include #include #include #include #include #include #include #ifdef __SWITCH__ #include #endif namespace extra2d { /** * @brief 获取当前时间(秒) */ static double getTimeSeconds() { #ifdef __SWITCH__ struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return static_cast(ts.tv_sec) + static_cast(ts.tv_nsec) / 1000000000.0; #else using namespace std::chrono; auto now = steady_clock::now(); auto duration = now.time_since_epoch(); return duration_cast>(duration).count(); #endif } std::unique_ptr Application::create() { return std::unique_ptr(new Application()); } Application::Application() = default; Application::~Application() { shutdown(); } Application::Application(Application&&) noexcept = default; Application& Application::operator=(Application&&) noexcept = default; bool Application::init(const AppConfig &config) { if (initialized_) { E2D_LOG_WARN("Application already initialized"); return true; } config_ = config; #ifdef __SWITCH__ Result rc; rc = romfsInit(); if (R_SUCCEEDED(rc)) { E2D_LOG_INFO("RomFS initialized successfully"); } else { E2D_LOG_WARN("romfsInit failed: {:#08X}", rc); } rc = socketInitializeDefault(); if (R_FAILED(rc)) { E2D_LOG_WARN("socketInitializeDefault failed"); } #endif if (!Sdl2::initAll()) { E2D_LOG_ERROR("Failed to initialize SDL2"); return false; } // 创建引擎上下文 context_ = Context::create(); if (!context_) { E2D_LOG_ERROR("Failed to create context"); return false; } // 初始化引擎 if (!context_->init()) { E2D_LOG_ERROR("Failed to initialize context"); return false; } // 创建窗口模块 windowModule_ = std::make_unique(); WindowCfg wcfg; wcfg.title = config_.title; wcfg.width = config_.width; wcfg.height = config_.height; wcfg.fullscreen = config_.fullscreen; wcfg.resizable = config_.resizable; wcfg.vsync = config_.vsync; wcfg.glMajor = config_.glMajor; wcfg.glMinor = config_.glMinor; if (!windowModule_->create(wcfg)) { E2D_LOG_ERROR("Failed to create window"); return false; } windowModule_->setVisible(true); // 创建输入模块 inputModule_ = std::make_unique(); initialized_ = true; running_ = true; events::OnInit::emit(); E2D_LOG_INFO("Application initialized successfully"); E2D_LOG_INFO("Window: {}x{}, Fullscreen: {}, VSync: {}", config_.width, config_.height, config_.fullscreen, config_.vsync); return true; } void Application::shutdown() { if (!initialized_) return; events::OnShutdown::emit(); E2D_LOG_INFO("Shutting down application..."); // 智能指针自动销毁窗口和输入模块 inputModule_.reset(); windowModule_.reset(); // 关闭上下文 context_.reset(); Sdl2::shutdown(); #ifdef __SWITCH__ romfsExit(); socketExit(); #endif initialized_ = false; running_ = false; E2D_LOG_INFO("Application shutdown complete"); } void Application::run() { if (!initialized_) { E2D_LOG_ERROR("Application not initialized"); return; } lastFrameTime_ = getTimeSeconds(); while (running_) { mainLoop(); } } void Application::quit() { shouldQuit_ = true; running_ = false; } void Application::pause() { if (!paused_) { paused_ = true; events::OnPause::emit(); E2D_LOG_INFO("Application paused"); } } void Application::resume() { if (paused_) { paused_ = false; events::OnResume::emit(); lastFrameTime_ = getTimeSeconds(); E2D_LOG_INFO("Application resumed"); } } void Application::mainLoop() { // 处理窗口事件 if (windowModule_) { if (!windowModule_->pollEvents()) { // 窗口关闭事件 quit(); return; } } double currentTime = getTimeSeconds(); deltaTime_ = static_cast(currentTime - lastFrameTime_); lastFrameTime_ = currentTime; totalTime_ += deltaTime_; frameCount_++; fpsTimer_ += deltaTime_; if (fpsTimer_ >= 1.0f) { currentFps_ = frameCount_; frameCount_ = 0; fpsTimer_ -= 1.0f; } if (!paused_) { update(); } // 交换缓冲区 if (windowModule_) { windowModule_->swapBuffers(); } // 帧率限制 if (!config_.vsync && config_.fpsLimit > 0) { double frameEndTime = getTimeSeconds(); double frameTime = frameEndTime - currentTime; double target = 1.0 / static_cast(config_.fpsLimit); if (frameTime < target) { std::this_thread::sleep_for( std::chrono::duration(target - frameTime)); } } } void Application::update() { // 通过上下文更新引擎 if (context_) { context_->tick(deltaTime_); } } int32 Application::getWindowWidth() const { if (windowModule_) { Size size = windowModule_->getSize(); return static_cast(size.w); } return config_.width; } int32 Application::getWindowHeight() const { if (windowModule_) { Size size = windowModule_->getSize(); return static_cast(size.h); } return config_.height; } const char* Application::getWindowTitle() const { return config_.title.c_str(); } } // namespace extra2d