feat: 添加SDL2后端支持并实现基础示例程序

添加SDL2作为平台后端支持,包括窗口创建、输入处理和GLAD初始化
实现基础示例程序展示引擎基本功能
重构平台配置代码以提高可读性
移除未使用的input_codes.h头文件
添加demo_basic构建目标到xmake配置
This commit is contained in:
ChestnutYueyue 2026-02-15 09:22:57 +08:00
parent 34fe0bafcb
commit 38148a6c54
8 changed files with 433 additions and 292 deletions

View File

@ -48,7 +48,6 @@
#include <extra2d/event/event.h>
#include <extra2d/event/event_dispatcher.h>
#include <extra2d/event/event_queue.h>
#include <extra2d/event/input_codes.h>
// Utils
#include <extra2d/utils/logger.h>

View File

@ -79,6 +79,7 @@ private:
*/
#define E2D_REG_BACKEND(name, WinClass, InClass) \
namespace { \
__attribute__((used)) \
static struct E2D_BACKEND_REG_##name { \
E2D_BACKEND_REG_##name() { \
::extra2d::BackendFactory::reg( \

View File

@ -16,10 +16,18 @@
#include <chrono>
#include <thread>
#include <SDL.h>
#ifdef __SWITCH__
#include <switch.h>
#endif
#ifdef E2D_BACKEND_SDL2
namespace extra2d {
void initSDL2Backend();
}
#endif
namespace extra2d {
/**
@ -56,10 +64,16 @@ bool Application::init() {
bool Application::init(const AppConfig& config) {
if (initialized_) {
E2D_LOG_WARN("Application already initialized");
return true;
}
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER) != 0) {
E2D_LOG_ERROR("Failed to initialize SDL: {}", SDL_GetError());
return false;
}
Logger::init();
E2D_LOG_INFO("Initializing application with config...");
if (!ConfigManager::instance().initialize()) {
@ -92,6 +106,10 @@ bool Application::init(const std::string& configPath) {
}
bool Application::initImpl() {
#ifdef E2D_BACKEND_SDL2
initSDL2Backend();
#endif
auto& configMgr = ConfigManager::instance();
AppConfig& appConfig = configMgr.appConfig();

View File

@ -1,5 +1,5 @@
#include <extra2d/config/platform_config.h>
#include <extra2d/config/app_config.h>
#include <extra2d/config/platform_config.h>
#include <extra2d/utils/logger.h>
#ifdef _WIN32
@ -43,10 +43,14 @@ public:
const PlatformCapabilities &capabilities() const override { return caps_; }
void applyConstraints(AppConfig &config) const override {
if (config.window.width < 320) config.window.width = 320;
if (config.window.height < 240) config.window.height = 240;
if (config.window.width > caps_.maxTextureSize) config.window.width = caps_.maxTextureSize;
if (config.window.height > caps_.maxTextureSize) config.window.height = caps_.maxTextureSize;
if (config.window.width < 320)
config.window.width = 320;
if (config.window.height < 240)
config.window.height = 240;
if (config.window.width > caps_.maxTextureSize)
config.window.width = caps_.maxTextureSize;
if (config.window.height > caps_.maxTextureSize)
config.window.height = caps_.maxTextureSize;
}
void applyDefaults(AppConfig &config) const override {
@ -67,8 +71,8 @@ public:
int getRecommendedWidth() const override { return 1920; }
int getRecommendedHeight() const override { return 1080; }
bool isResolutionSupported(int width, int height) const override {
return width >= 320 && height >= 240 &&
width <= caps_.maxTextureSize && height <= caps_.maxTextureSize;
return width >= 320 && height >= 240 && width <= caps_.maxTextureSize &&
height <= caps_.maxTextureSize;
}
private:
@ -104,8 +108,10 @@ public:
const PlatformCapabilities &capabilities() const override { return caps_; }
void applyConstraints(AppConfig &config) const override {
if (config.window.width < 320) config.window.width = 320;
if (config.window.height < 240) config.window.height = 240;
if (config.window.width < 320)
config.window.width = 320;
if (config.window.height < 240)
config.window.height = 240;
}
void applyDefaults(AppConfig &config) const override {
@ -160,8 +166,10 @@ public:
const PlatformCapabilities &capabilities() const override { return caps_; }
void applyConstraints(AppConfig &config) const override {
if (config.window.width < 320) config.window.width = 320;
if (config.window.height < 240) config.window.height = 240;
if (config.window.width < 320)
config.window.width = 320;
if (config.window.height < 240)
config.window.height = 240;
}
void applyDefaults(AppConfig &config) const override {
@ -329,7 +337,7 @@ private:
};
#endif
}
} // namespace
/**
* @brief
@ -379,13 +387,19 @@ UniquePtr<PlatformConfig> createPlatformConfig(PlatformType type) {
*/
const char *getPlatformTypeName(PlatformType type) {
switch (type) {
case PlatformType::Auto: return "Auto";
case PlatformType::Windows: return "Windows";
case PlatformType::Switch: return "Switch";
case PlatformType::Linux: return "Linux";
case PlatformType::macOS: return "macOS";
default: return "Unknown";
case PlatformType::Auto:
return "Auto";
case PlatformType::Windows:
return "Windows";
case PlatformType::Switch:
return "Switch";
case PlatformType::Linux:
return "Linux";
case PlatformType::macOS:
return "macOS";
default:
return "Unknown";
}
}
}
} // namespace extra2d

View File

@ -4,6 +4,25 @@
namespace extra2d {
E2D_REG_BACKEND(sdl2, SDL2Window, SDL2Input)
namespace {
static bool s_sdl2BackendRegistered = false;
}
void initSDL2Backend() {
if (s_sdl2BackendRegistered) {
return;
}
s_sdl2BackendRegistered = true;
BackendFactory::reg(
"sdl2",
[]() -> UniquePtr<IWindow> {
return makeUnique<SDL2Window>();
},
[]() -> UniquePtr<IInput> {
return makeUnique<SDL2Input>();
}
);
}
} // namespace extra2d

View File

@ -1,6 +1,7 @@
#include "sdl2_window.h"
#include "sdl2_input.h"
#include <extra2d/utils/logger.h>
#include <glad/glad.h>
namespace extra2d {
@ -73,6 +74,16 @@ bool SDL2Window::create(const WindowConfigData& cfg) {
return false;
}
if (!gladLoadGLES2Loader((GLADloadproc)SDL_GL_GetProcAddress)) {
E2D_LOG_ERROR("Failed to initialize GLAD");
SDL_GL_DeleteContext(glContext_);
glContext_ = nullptr;
SDL_DestroyWindow(sdlWindow_);
sdlWindow_ = nullptr;
deinitSDL();
return false;
}
SDL_GL_SetSwapInterval(cfg.vsync ? 1 : 0);
SDL_GetWindowSize(sdlWindow_, &width_, &height_);

59
examples/basic/main.cpp Normal file
View File

@ -0,0 +1,59 @@
/**
* @file main.cpp
* @brief Extra2D
*
* 使 Extra2D
*/
#include <extra2d/extra2d.h>
#include <iostream>
using namespace extra2d;
/**
* @brief
*
*
*/
int main(int argc, char* argv[]) {
(void)argc;
(void)argv;
std::cout << "Extra2D Demo - Starting..." << std::endl;
AppConfig config = AppConfig::createDefault();
config.appName = "Extra2D Demo";
config.appVersion = "1.0.0";
config.window.title = "Extra2D Demo";
config.window.width = 800;
config.window.height = 600;
config.window.mode = WindowMode::Windowed;
config.window.resizable = true;
config.window.vsync = true;
config.render.targetFPS = 60;
Application& app = Application::get();
if (!app.init(config)) {
std::cerr << "Failed to initialize application!" << std::endl;
return -1;
}
std::cout << "Application initialized successfully!" << std::endl;
std::cout << "Window: " << app.window().width() << "x" << app.window().height() << std::endl;
std::cout << "Running main loop. Press ESC or close window to exit." << std::endl;
auto scene = Scene::create();
scene->setBackgroundColor(Colors::SkyBlue);
scene->setViewportSize(static_cast<float>(config.window.width),
static_cast<float>(config.window.height));
app.enterScene(scene);
app.run();
std::cout << "Shutting down..." << std::endl;
app.shutdown();
std::cout << "Goodbye!" << std::endl;
return 0;
}

View File

@ -95,3 +95,23 @@ includes("xmake/engine.lua")
-- 定义引擎库
define_extra2d_engine()
-- ==============================================
-- 示例程序
-- ==============================================
-- 基础示例
target("demo_basic")
set_kind("binary")
set_default(false)
add_deps("extra2d")
add_files("examples/basic/main.cpp")
-- 平台配置
local target_plat = get_config("plat") or os.host()
if target_plat == "mingw" then
add_packages("glm", "nlohmann_json", "libsdl2")
add_syslinks("opengl32", "glu32", "winmm", "imm32", "version", "setupapi")
end
target_end()