From 01ac7d34e959298d240013525b64e9475531b513 Mon Sep 17 00:00:00 2001 From: lenheart <947330670@qq.com> Date: Mon, 16 Feb 2026 19:19:14 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8xmake=20=E5=8C=85=E4=BB=93?= =?UTF-8?q?=E5=BA=93=20sdl2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 + .vscode/compile_commands.json | 6 +- .../include/fostbite2D/app/application.h | 215 ++++++++++++++++++ .../include/fostbite2D/config/app_config.h | 38 ++++ .../fostbite2D/config/platform_config.h | 86 +++++++ Fostbite2D/include/fostbite2D/core/types.h | 58 +++++ Fostbite2D/include/fostbite2D/module/module.h | 93 ++++++++ Fostbite2D/src/fostbite2D/app/application.cpp | 66 ++++++ .../src/fostbite2D/config/app_config.cpp | 19 ++ Fostbite2D/src/main.cpp | 94 ++++++++ folder-alias.json | 1 - platform/windows.lua | 12 + private-folder-alias.json | 1 - src/main.cpp | 6 - xmake.lua | 17 +- 15 files changed, 702 insertions(+), 14 deletions(-) create mode 100644 Fostbite2D/include/fostbite2D/app/application.h create mode 100644 Fostbite2D/include/fostbite2D/config/app_config.h create mode 100644 Fostbite2D/include/fostbite2D/config/platform_config.h create mode 100644 Fostbite2D/include/fostbite2D/core/types.h create mode 100644 Fostbite2D/include/fostbite2D/module/module.h create mode 100644 Fostbite2D/src/fostbite2D/app/application.cpp create mode 100644 Fostbite2D/src/fostbite2D/config/app_config.cpp create mode 100644 Fostbite2D/src/main.cpp delete mode 100644 folder-alias.json create mode 100644 platform/windows.lua delete mode 100644 private-folder-alias.json delete mode 100644 src/main.cpp diff --git a/.gitignore b/.gitignore index 1521057..8751bce 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ build/ .DS_Store +.vscode/ +.cache/ + +*.json diff --git a/.vscode/compile_commands.json b/.vscode/compile_commands.json index 97f0d46..7ac196c 100644 --- a/.vscode/compile_commands.json +++ b/.vscode/compile_commands.json @@ -1,6 +1,6 @@ [ { - "directory": "/home/lenheart/Game/Frostbite2D", - "arguments": ["/usr/bin/g++", "-c", "-m64", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-O3", "-std=c++17", "-finput-charset=UTF-8", "-fexec-charset=UTF-8", "-DNDEBUG", "-o", "build/.objs/Frostbite2D/linux/x86_64/release/src/main.cpp.o", "src/main.cpp"], - "file": "src/main.cpp" + "directory": "d:\\Game\\Frostbite2D", + "arguments": ["D:\\Visual Studio\\App\\VC\\Tools\\MSVC\\14.44.35207\\bin\\HostX64\\x64\\cl.exe", "/c", "/nologo", "/MD", "/O2", "/std:c++17", "/EHsc", "/utf-8", "/DNDEBUG", "/Fobuild\\.objs\\Frostbite2D\\windows\\x64\\release\\Fostbite2D\\src\\main.cpp.obj", "Fostbite2D\\src\\main.cpp", "-imsvc", "D:\\Visual Studio\\App\\VC\\Tools\\MSVC\\14.44.35207\\include", "-imsvc", "D:\\Visual Studio\\App\\VC\\Tools\\MSVC\\14.44.35207\\ATLMFC\\include", "-imsvc", "D:\\Visual Studio\\App\\VC\\Auxiliary\\VS\\include", "-imsvc", "D:\\Windows Kits\\10\\include\\10.0.26100.0\\ucrt", "-imsvc", "D:\\Windows Kits\\10\\\\include\\10.0.26100.0\\\\um", "-imsvc", "D:\\Windows Kits\\10\\\\include\\10.0.26100.0\\\\shared", "-imsvc", "D:\\Windows Kits\\10\\\\include\\10.0.26100.0\\\\winrt", "-imsvc", "D:\\Windows Kits\\10\\\\include\\10.0.26100.0\\\\cppwinrt", "-imsvc", "C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\include\\um"], + "file": "Fostbite2D\\src\\main.cpp" }] diff --git a/Fostbite2D/include/fostbite2D/app/application.h b/Fostbite2D/include/fostbite2D/app/application.h new file mode 100644 index 0000000..ed0152c --- /dev/null +++ b/Fostbite2D/include/fostbite2D/app/application.h @@ -0,0 +1,215 @@ +#pragma once + +#include +#include +#include + +namespace frostbite2D { + +/** + * @brief 应用程序类 + */ +class Application { +public: + /** + * @brief 获取单例实例 + * @return 应用程序实例引用 + */ + static Application& get(); + + Application(const Application&) = delete; + Application& operator=(const Application&) = delete; + + /** + * @brief 添加模块 + * @param m 模块引用 + */ + void use(Module& m); + + /** + * @brief 批量添加模块 + * @param modules 模块指针列表 + */ + void use(std::initializer_list modules); + + /** + * @brief 使用默认配置初始化 + * @return 初始化成功返回 true + */ + bool init(); + + /** + * @brief 使用指定配置初始化 + * @param config 应用配置 + * @return 初始化成功返回 true + */ + bool init(const AppConfig& config); + + /** + * @brief 使用配置文件初始化 + * @param configPath 配置文件路径 + * @return 初始化成功返回 true + */ + bool init(const std::string& configPath); + + /** + * @brief 关闭应用程序 + */ + void shutdown(); + + /** + * @brief 运行主循环 + */ + void run(); + + /** + * @brief 请求退出 + */ + void quit(); + + /** + * @brief 暂停应用程序 + */ + void pause(); + + /** + * @brief 恢复应用程序 + */ + void resume(); + + /** + * @brief 检查是否暂停 + * @return 暂停状态返回 true + */ + bool isPaused() const { return paused_; } + + /** + * @brief 检查是否运行中 + * @return 运行中返回 true + */ + bool isRunning() const { return running_; } + + // /** + // * @brief 获取窗口 + // * @return 窗口引用 + // */ + // IWindow& window() { return *window_; } + + // /** + // * @brief 获取渲染器 + // * @return 渲染器引用 + // */ + // RenderBackend& renderer(); + + // /** + // * @brief 获取场景服务 + // * @return 场景服务共享指针 + // */ + // SharedPtr scenes(); + + // /** + // * @brief 获取计时器服务 + // * @return 计时器服务共享指针 + // */ + // SharedPtr timers(); + + // /** + // * @brief 获取事件服务 + // * @return 事件服务共享指针 + // */ + // SharedPtr events(); + + // /** + // * @brief 获取相机服务 + // * @return 相机服务共享指针 + // */ + // SharedPtr camera(); + + // /** + // * @brief 进入场景 + // * @param scene 场景指针 + // */ + // void enterScene(Ptr scene); + + /** + * @brief 获取帧间隔时间 + * @return 帧间隔时间(秒) + */ + float deltaTime() const { return deltaTime_; } + + /** + * @brief 获取总运行时间 + * @return 总运行时间(秒) + */ + float totalTime() const { return totalTime_; } + + /** + * @brief 获取当前帧率 + * @return 帧率 + */ + int fps() const { return currentFps_; } + + /** + * @brief 获取应用配置 + * @return 应用配置常量引用 + */ + const AppConfig& getConfig() const; + +private: + Application() = default; + ~Application(); + + /** + * @brief 初始化核心模块 + * @return 初始化成功返回 true + */ + bool initCoreModules(); + + /** + * @brief 设置所有模块 + */ + void setupAllModules(); + + /** + * @brief 销毁所有模块 + */ + void destroyAllModules(); + + /** + * @brief 注册核心服务 + */ + void registerCoreServices(); + + /** + * @brief 主循环 + */ + void mainLoop(); + + /** + * @brief 更新 + */ + void update(); + + /** + * @brief 渲染 + */ + void render(); + + std::vector modules_; + // IWindow* window_ = nullptr; + + bool initialized_ = false; + bool running_ = false; + bool paused_ = false; + bool shouldQuit_ = false; + + float deltaTime_ = 0.0f; + float totalTime_ = 0.0f; + double lastFrameTime_ = 0.0; + int frameCount_ = 0; + float fpsTimer_ = 0.0f; + int currentFps_ = 0; +}; + + +} \ No newline at end of file diff --git a/Fostbite2D/include/fostbite2D/config/app_config.h b/Fostbite2D/include/fostbite2D/config/app_config.h new file mode 100644 index 0000000..3942f7a --- /dev/null +++ b/Fostbite2D/include/fostbite2D/config/app_config.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +namespace frostbite2D { + +/** + * @file app_config.h + * @brief 应用级别配置 + * + * 本文件仅包含应用级别的配置项,不包含任何模块特定配置。 + * 各模块应该在自己的模块文件中定义配置结构,并实现 IModuleConfig 接口。 + * + * 模块配置通过 ModuleRegistry 注册,由 ConfigManager 统一管理。 + * 这种设计遵循开闭原则,新增模块无需修改引擎核心代码。 + */ + +/** + * @brief 应用配置结构体 + * 仅包含应用级别的配置项,模块配置由各模块自行管理 + */ +struct AppConfig { + std::string appName = "frostbite2D App"; + std::string appVersion = "1.0.0"; + std::string organization = ""; + std::string configFile = "config.json"; + PlatformType targetPlatform = PlatformType::Auto; + + /** + * @brief 创建默认配置 + * @return 默认的应用配置实例 + */ + static AppConfig createDefault(); + +}; + +} diff --git a/Fostbite2D/include/fostbite2D/config/platform_config.h b/Fostbite2D/include/fostbite2D/config/platform_config.h new file mode 100644 index 0000000..406886c --- /dev/null +++ b/Fostbite2D/include/fostbite2D/config/platform_config.h @@ -0,0 +1,86 @@ +#pragma once + +#include + +namespace frostbite2D { + +/** + * @file platform_config.h + * @brief 平台配置接口 + * + * 平台配置只提供平台能力信息,不再直接修改应用配置。 + * 各模块通过 IModuleConfig::applyPlatformConstraints() 处理平台约束。 + */ + +/** + * @brief 平台类型枚举 + */ +enum class PlatformType { + Auto, + Windows, + Switch, + Linux, + macOS +}; + +/** + * @brief 平台能力结构 + */ +struct PlatformCapabilities { + bool supportsWindowed = true; + bool supportsFullscreen = true; + bool supportsBorderless = true; + bool supportsCursor = true; + bool supportsCursorHide = true; + bool supportsDPIAwareness = true; + bool supportsVSync = true; + bool supportsMultiMonitor = true; + bool supportsClipboard = true; + bool supportsGamepad = true; + bool supportsTouch = false; + bool supportsKeyboard = true; + bool supportsMouse = true; + bool supportsResize = true; + bool supportsHighDPI = true; + int maxTextureSize = 16384; + int preferredScreenWidth = 1920; + int preferredScreenHeight = 1080; + float defaultDPI = 96.0f; + + bool hasWindowSupport() const { return supportsWindowed || supportsFullscreen || supportsBorderless; } + bool hasInputSupport() const { return supportsKeyboard || supportsMouse || supportsGamepad || supportsTouch; } + bool isDesktop() const { return supportsKeyboard && supportsMouse && supportsWindowed; } + bool isConsole() const { return !supportsWindowed && supportsGamepad; } +}; + +/** + * @brief 平台配置抽象接口 + */ +class PlatformConfig { +public: + virtual ~PlatformConfig() = default; + + virtual PlatformType platformType() const = 0; + virtual const char* platformName() const = 0; + virtual const PlatformCapabilities& capabilities() const = 0; + + virtual int getRecommendedWidth() const = 0; + virtual int getRecommendedHeight() const = 0; + virtual bool isResolutionSupported(int width, int height) const = 0; +}; + +/** + * @brief 创建平台配置实例 + * @param type 平台类型,默认为 Auto(自动检测) + * @return 平台配置的智能指针 + */ +UniquePtr createPlatformConfig(PlatformType type = PlatformType::Auto); + +/** + * @brief 获取平台类型名称 + * @param type 平台类型枚举值 + * @return 平台名称字符串 + */ +const char* getPlatformTypeName(PlatformType type); + +} diff --git a/Fostbite2D/include/fostbite2D/core/types.h b/Fostbite2D/include/fostbite2D/core/types.h new file mode 100644 index 0000000..eb1ffaf --- /dev/null +++ b/Fostbite2D/include/fostbite2D/core/types.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include +#include + +namespace frostbite2D { + +// --------------------------------------------------------------------------- +// 宏定义 +// --------------------------------------------------------------------------- +#define E2D_CONCAT_IMPL(a, b) a##b +#define E2D_CONCAT(a, b) E2D_CONCAT_IMPL(a, b) + +// --------------------------------------------------------------------------- +// 智能指针别名 +// --------------------------------------------------------------------------- +template using Ptr = std::shared_ptr; +template using SharedPtr = std::shared_ptr; + +template using UniquePtr = std::unique_ptr; + +template using WeakPtr = std::weak_ptr; + +/// 创建 shared_ptr 的便捷函数 +template inline Ptr makePtr(Args &&...args) { + return std::make_shared(std::forward(args)...); +} + +template inline SharedPtr makeShared(Args &&...args) { + return std::make_shared(std::forward(args)...); +} + +/// 创建 unique_ptr 的便捷函数 +template +inline UniquePtr makeUnique(Args &&...args) { + return std::make_unique(std::forward(args)...); +} + +// --------------------------------------------------------------------------- +// 函数别名 +// --------------------------------------------------------------------------- +template using Function = std::function; + +// --------------------------------------------------------------------------- +// 基础类型别名 +// --------------------------------------------------------------------------- +using int8 = std::int8_t; +using int16 = std::int16_t; +using int32 = std::int32_t; +using int64 = std::int64_t; +using uint8 = std::uint8_t; +using uint16 = std::uint16_t; +using uint32 = std::uint32_t; +using uint64 = std::uint64_t; + +} // namespace frostbite2D diff --git a/Fostbite2D/include/fostbite2D/module/module.h b/Fostbite2D/include/fostbite2D/module/module.h new file mode 100644 index 0000000..2660fb5 --- /dev/null +++ b/Fostbite2D/include/fostbite2D/module/module.h @@ -0,0 +1,93 @@ +#pragma once + +namespace frostbite2D { + +/** + * @brief 模块基类 + * 所有模块只需继承此类,实现需要的生命周期方法 + */ +class Module { +public: + /** + * @brief 虚析构函数 + */ + virtual ~Module() = default; + + /** + * @brief 设置模块(初始化) + * 在 Application::run() 开始前调用 + */ + virtual void setupModule() {} + + /** + * @brief 销毁模块 + * 在 Application 关闭时调用 + */ + virtual void destroyModule() {} + + /** + * @brief 更新时 + * 每帧调用 + * @param ctx 更新上下文 + */ + virtual void onUpdate() { } + + /** + * @brief 渲染前 + * 在渲染开始前调用 + * @param ctx 渲染上下文 + */ + virtual void beforeRender() { } + + /** + * @brief 渲染时 + * 在渲染阶段调用 + * @param ctx 渲染上下文 + */ + virtual void onRender() {} + + /** + * @brief 渲染后 + * 在渲染完成后调用 + * @param ctx 渲染上下文 + */ + virtual void afterRender() { } + + /** + * @brief 事件处理 + * 处理系统事件 + * @param ctx 事件上下文 + */ + virtual void handleEvent() { } + + /** + * @brief 获取模块名称 + * @return 模块名称字符串 + */ + virtual const char *getName() const = 0; + + /** + * @brief 获取模块优先级 + * 数值越小越先执行 + * @return 优先级值 + */ + virtual int getPriority() const { return 0; } + + /** + * @brief 检查模块是否已初始化 + * @return 已初始化返回 true + */ + bool isInitialized() const { return initialized_; } + +protected: + friend class Application; + + /** + * @brief 设置初始化状态 + * @param initialized 初始化状态 + */ + void setInitialized(bool initialized) { initialized_ = initialized; } + + bool initialized_ = false; +}; +} // namespace frostbite2D \ No newline at end of file diff --git a/Fostbite2D/src/fostbite2D/app/application.cpp b/Fostbite2D/src/fostbite2D/app/application.cpp new file mode 100644 index 0000000..dcc1112 --- /dev/null +++ b/Fostbite2D/src/fostbite2D/app/application.cpp @@ -0,0 +1,66 @@ +#include "SDL2/SDL_log.h" +#include +#include +#include +namespace frostbite2D { + +Application &Application::get() { + static Application instance; + return instance; +} + + +void Application::use(Module &m) { + for (auto *existing : modules_) { + if (existing == &m) { + return; + } + } + modules_.push_back(&m); +} + +void Application::use(std::initializer_list modules) { + for (auto *m : modules) { + if (m) { + use(*m); + } + } +} + +bool Application::init() { + AppConfig cfg; + return init(cfg); +} + +bool Application::init(const AppConfig &config) { + if (initialized_) { + return true; + } + + SDL_Log("Frostbite2D 启动成功!"); + + return true; +} + + +void Application::shutdown() { + if (!initialized_) + return; + +// VRAMMgr::get().printStats(); + +// ServiceLocator::instance().clear(); + +// window_ = nullptr; + + + initialized_ = false; + running_ = false; +} + +Application::~Application() { + if (initialized_) { + shutdown(); + } +} +} // namespace frostbite2D \ No newline at end of file diff --git a/Fostbite2D/src/fostbite2D/config/app_config.cpp b/Fostbite2D/src/fostbite2D/config/app_config.cpp new file mode 100644 index 0000000..27cb896 --- /dev/null +++ b/Fostbite2D/src/fostbite2D/config/app_config.cpp @@ -0,0 +1,19 @@ +#include + +namespace frostbite2D { + +AppConfig AppConfig::createDefault() { + AppConfig config; + + config.appName = "Frostbite2D App"; + config.appVersion = "1.0.0"; + config.organization = ""; + config.configFile = "config.json"; + config.targetPlatform = PlatformType::Auto; + + return config; +} + + + +} \ No newline at end of file diff --git a/Fostbite2D/src/main.cpp b/Fostbite2D/src/main.cpp new file mode 100644 index 0000000..9ae87c6 --- /dev/null +++ b/Fostbite2D/src/main.cpp @@ -0,0 +1,94 @@ +#include +#include +#include + +using namespace frostbite2D; + +int main(int argc, char **argv) { + + // AppConfig config = AppConfig::createDefault(); + // config.appName = "Extra2D Scene Graph Demo"; + // config.appVersion = "1.0.0"; + + // Application &app = Application::get(); + // if (!app.init(config)) { + // std::cerr << "Failed to initialize application!" << std::endl; + // return -1; + // } + + // 初始化 SDL + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + std::cerr << "SDL 初始化失败: " << SDL_GetError() << std::endl; + return 1; + } + + // 创建窗口 + SDL_Window* window = SDL_CreateWindow( + "Frostbite2D - SDL2 Demo", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + 800, 600, + SDL_WINDOW_SHOWN + ); + + if (!window) { + std::cerr << "窗口创建失败: " << SDL_GetError() << std::endl; + SDL_Quit(); + return 1; + } + + // 创建渲染器 + SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, + SDL_RENDERER_ACCELERATED); if (!renderer) { + std::cerr << "渲染器创建失败: " << SDL_GetError() << std::endl; + SDL_DestroyWindow(window); + SDL_Quit(); + return 1; + } + + std::cout << "Frostbite2D 启动成功!" << std::endl; + std::cout << "按 ESC 键退出程序" << std::endl; + + // 主循环 + bool running = true; + SDL_Event event; + + while (running) { + // 处理事件 + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) { + running = false; + } + if (event.type == SDL_KEYDOWN) { + if (event.key.keysym.sym == SDLK_ESCAPE) { + running = false; + } + } + } + + // 清屏 (黑色) + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + + // 绘制一个红色矩形 + SDL_Rect rect = {350, 250, 100, 100}; + SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); + SDL_RenderFillRect(renderer, &rect); + + // 绘制一个绿色边框 + SDL_Rect border = {300, 200, 200, 200}; + SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); + SDL_RenderDrawRect(renderer, &border); + + // 更新屏幕 + SDL_RenderPresent(renderer); + } + + // 清理资源 + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + + std::cout << "程序正常退出" << std::endl; + return 0; +} diff --git a/folder-alias.json b/folder-alias.json deleted file mode 100644 index 9e26dfe..0000000 --- a/folder-alias.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/platform/windows.lua b/platform/windows.lua new file mode 100644 index 0000000..15c11be --- /dev/null +++ b/platform/windows.lua @@ -0,0 +1,12 @@ +-- MinGW 编译配置 +set_toolchains("mingw") + +add_requires("libsdl2", {configs = {shared = true}}) + +target("Frostbite2D") + set_kind("binary") + add_files(path.join(os.projectdir(), "Fostbite2D/src/**.cpp")) + add_includedirs(path.join(os.projectdir(), "Fostbite2D/include")) + + add_packages("libsdl2") +target_end() diff --git a/private-folder-alias.json b/private-folder-alias.json deleted file mode 100644 index 9e26dfe..0000000 --- a/private-folder-alias.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 9b6abff..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int main(int argc, char **argv) { - std::cout << "hello world!" << std::endl; - return 0; -} diff --git a/xmake.lua b/xmake.lua index e7a0dca..b28d648 100644 --- a/xmake.lua +++ b/xmake.lua @@ -12,7 +12,18 @@ local host_plat = os.host() local target_plat = get_config("plat") or host_plat local supported_plats = {mingw = true, windows = true, linux = true, macosx = true, switch = true} +-- 自动选择平台 +if not supported_plats[target_plat] then + raise("Unsupported platform: " .. target_plat .. ". Supported platforms: mingw, windows, linux, macosx, switch") +end + + +-- 引入对应平台的配置文件 +local platform_config_file = "platform/" .. target_plat .. ".lua" +if os.isfile(platform_config_file) then + includes(platform_config_file) +else + raise("Platform config file not found: " .. platform_config_file) +end + -target("Frostbite2D") - set_kind("binary") - add_files("src/*.cpp")