feat: 添加窗口和输入模块支持并简化示例程序
重构应用类以支持窗口和输入模块,添加相关接口方法 移除碰撞演示示例,简化hello world示例为控制台输出 启用控制台子系统以便在mingw平台查看输出
This commit is contained in:
parent
418d2c8f92
commit
ebf73a4492
|
|
@ -1,280 +0,0 @@
|
||||||
#include <cmath>
|
|
||||||
#include <extra2d.h>
|
|
||||||
|
|
||||||
using namespace extra2d;
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// 碰撞测试节点 - 有实际边界框
|
|
||||||
// ============================================================================
|
|
||||||
class CollisionBox : public Node {
|
|
||||||
public:
|
|
||||||
CollisionBox(float width, float height, const Color &color)
|
|
||||||
: width_(width), height_(height), color_(color), isColliding_(false) {
|
|
||||||
// 启用空间索引,这是碰撞检测的关键
|
|
||||||
setSpatialIndexed(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setColliding(bool colliding) { isColliding_ = colliding; }
|
|
||||||
|
|
||||||
Rect boundingBox() const override {
|
|
||||||
// 返回实际的矩形边界
|
|
||||||
Vec2 position = pos();
|
|
||||||
return Rect(position.x - width_ / 2, position.y - height_ / 2, width_,
|
|
||||||
height_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onRender(Renderer &renderer) override {
|
|
||||||
Vec2 position = pos();
|
|
||||||
|
|
||||||
// 绘制填充矩形
|
|
||||||
Color fillColor = isColliding_ ? Color(1.0f, 0.2f, 0.2f, 0.8f) : color_;
|
|
||||||
renderer.fillRect(Rect(position.x - width_ / 2, position.y - height_ / 2,
|
|
||||||
width_, height_),
|
|
||||||
fillColor);
|
|
||||||
|
|
||||||
// 绘制边框
|
|
||||||
Color borderColor = isColliding_ ? Color(1.0f, 0.0f, 0.0f, 1.0f)
|
|
||||||
: Color(1.0f, 1.0f, 1.0f, 0.5f);
|
|
||||||
float borderWidth = isColliding_ ? 3.0f : 2.0f;
|
|
||||||
renderer.drawRect(Rect(position.x - width_ / 2, position.y - height_ / 2,
|
|
||||||
width_, height_),
|
|
||||||
borderColor, borderWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
float width_, height_;
|
|
||||||
Color color_;
|
|
||||||
bool isColliding_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// 碰撞检测场景
|
|
||||||
// ============================================================================
|
|
||||||
class CollisionDemoScene : public Scene {
|
|
||||||
public:
|
|
||||||
void onEnter() override {
|
|
||||||
E2D_LOG_INFO("CollisionDemoScene::onEnter - 碰撞检测演示");
|
|
||||||
|
|
||||||
// 设置背景色
|
|
||||||
setBackgroundColor(Color(0.05f, 0.05f, 0.1f, 1.0f));
|
|
||||||
|
|
||||||
// 获取屏幕中心
|
|
||||||
auto &app = Application::instance();
|
|
||||||
float centerX = app.getConfig().width / 2.0f;
|
|
||||||
float centerY = app.getConfig().height / 2.0f;
|
|
||||||
|
|
||||||
// 创建静态碰撞框
|
|
||||||
createStaticBoxes(centerX, centerY);
|
|
||||||
|
|
||||||
// 创建移动的中心方块
|
|
||||||
centerBox_ =
|
|
||||||
shared<CollisionBox>(80.0f, 80.0f, Color(0.2f, 0.6f, 1.0f, 0.8f));
|
|
||||||
centerBox_->setPosition(Vec2(centerX, centerY));
|
|
||||||
addChild(centerBox_);
|
|
||||||
|
|
||||||
// 加载字体并创建UI
|
|
||||||
loadFonts();
|
|
||||||
|
|
||||||
E2D_LOG_INFO("创建了 {} 个碰撞框", boxes_.size() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onUpdate(float dt) override {
|
|
||||||
Scene::onUpdate(dt);
|
|
||||||
|
|
||||||
// 旋转中心方块
|
|
||||||
rotationAngle_ += rotationSpeed_ * dt;
|
|
||||||
if (rotationAngle_ >= 360.0f)
|
|
||||||
rotationAngle_ -= 360.0f;
|
|
||||||
|
|
||||||
// 让中心方块沿圆形路径移动
|
|
||||||
float radius = 150.0f;
|
|
||||||
float rad = rotationAngle_ * 3.14159f / 180.0f;
|
|
||||||
|
|
||||||
auto &app = Application::instance();
|
|
||||||
Vec2 center =
|
|
||||||
Vec2(app.getConfig().width / 2.0f, app.getConfig().height / 2.0f);
|
|
||||||
|
|
||||||
centerBox_->setPosition(Vec2(center.x + std::cos(rad) * radius,
|
|
||||||
center.y + std::sin(rad) * radius));
|
|
||||||
centerBox_->setRotation(rotationAngle_);
|
|
||||||
|
|
||||||
// 执行碰撞检测
|
|
||||||
performCollisionDetection();
|
|
||||||
|
|
||||||
// 更新UI文本
|
|
||||||
updateUI();
|
|
||||||
|
|
||||||
// 检查退出按键
|
|
||||||
auto &input = Application::instance().input();
|
|
||||||
if (input.isButtonPressed(GamepadButton::Start)) {
|
|
||||||
E2D_LOG_INFO("退出应用");
|
|
||||||
Application::instance().quit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief 加载字体资源并创建UI文本
|
|
||||||
*/
|
|
||||||
void loadFonts() {
|
|
||||||
auto &resources = Application::instance().resources();
|
|
||||||
titleFont_ = resources.loadFont("assets/font.ttf", 60, true);
|
|
||||||
infoFont_ = resources.loadFont("assets/font.ttf", 28, true);
|
|
||||||
|
|
||||||
// 创建标题文本
|
|
||||||
titleText_ = Text::create("碰撞检测演示", titleFont_);
|
|
||||||
titleText_->setPosition(50.0f, 30.0f);
|
|
||||||
titleText_->setTextColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
|
|
||||||
addChild(titleText_);
|
|
||||||
|
|
||||||
// 创建说明文本
|
|
||||||
descText_ = Text::create("蓝色方块旋转并检测碰撞", infoFont_);
|
|
||||||
descText_->setPosition(50.0f, 80.0f);
|
|
||||||
descText_->setTextColor(Color(0.8f, 0.8f, 0.8f, 1.0f));
|
|
||||||
addChild(descText_);
|
|
||||||
|
|
||||||
collideHintText_ = Text::create("红色 = 检测到碰撞", infoFont_);
|
|
||||||
collideHintText_->setPosition(50.0f, 105.0f);
|
|
||||||
collideHintText_->setTextColor(Color(1.0f, 0.5f, 0.5f, 1.0f));
|
|
||||||
addChild(collideHintText_);
|
|
||||||
|
|
||||||
// 创建动态统计文本
|
|
||||||
collisionText_ = Text::create("", infoFont_);
|
|
||||||
collisionText_->setPosition(50.0f, 150.0f);
|
|
||||||
collisionText_->setTextColor(Color(1.0f, 1.0f, 0.5f, 1.0f));
|
|
||||||
addChild(collisionText_);
|
|
||||||
|
|
||||||
fpsText_ = Text::create("", infoFont_);
|
|
||||||
fpsText_->setPosition(50.0f, 175.0f);
|
|
||||||
fpsText_->setTextColor(Color(0.8f, 1.0f, 0.8f, 1.0f));
|
|
||||||
addChild(fpsText_);
|
|
||||||
|
|
||||||
// 创建退出提示文本
|
|
||||||
float screenHeight =
|
|
||||||
static_cast<float>(Application::instance().getConfig().height);
|
|
||||||
exitHintText_ = Text::create("按 + 键退出", infoFont_);
|
|
||||||
exitHintText_->setPosition(50.0f, screenHeight - 50.0f);
|
|
||||||
exitHintText_->setTextColor(Color(0.8f, 0.8f, 0.8f, 1.0f));
|
|
||||||
addChild(exitHintText_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 更新UI文本
|
|
||||||
*/
|
|
||||||
void updateUI() {
|
|
||||||
auto &app = Application::instance();
|
|
||||||
|
|
||||||
// 使用 setFormat 更新动态文本
|
|
||||||
collisionText_->setFormat("碰撞数: %zu", collisionCount_);
|
|
||||||
fpsText_->setFormat("FPS: %u", app.fps());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 创建静态碰撞框
|
|
||||||
*/
|
|
||||||
void createStaticBoxes(float centerX, float centerY) {
|
|
||||||
// 创建围绕中心的静态碰撞框
|
|
||||||
std::vector<std::pair<Vec2, Color>> positions = {
|
|
||||||
{Vec2(centerX - 200, centerY - 150), Color(0.3f, 1.0f, 0.3f, 0.7f)},
|
|
||||||
{Vec2(centerX + 200, centerY - 150), Color(1.0f, 0.3f, 0.3f, 0.7f)},
|
|
||||||
{Vec2(centerX - 200, centerY + 150), Color(0.3f, 0.3f, 1.0f, 0.7f)},
|
|
||||||
{Vec2(centerX + 200, centerY + 150), Color(1.0f, 1.0f, 0.3f, 0.7f)},
|
|
||||||
{Vec2(centerX, centerY - 220), Color(1.0f, 0.3f, 1.0f, 0.7f)},
|
|
||||||
{Vec2(centerX, centerY + 220), Color(0.3f, 1.0f, 1.0f, 0.7f)},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto &[pos, color] : positions) {
|
|
||||||
auto box = shared<CollisionBox>(70.0f, 70.0f, color);
|
|
||||||
box->setPosition(pos);
|
|
||||||
addChild(box);
|
|
||||||
boxes_.push_back(box);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 执行碰撞检测
|
|
||||||
*/
|
|
||||||
void performCollisionDetection() {
|
|
||||||
// 清除之前的碰撞状态
|
|
||||||
centerBox_->setColliding(false);
|
|
||||||
for (auto &box : boxes_) {
|
|
||||||
box->setColliding(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用空间索引进行碰撞检测
|
|
||||||
auto collisions = queryCollisions();
|
|
||||||
|
|
||||||
collisionCount_ = collisions.size();
|
|
||||||
|
|
||||||
// 标记碰撞的节点
|
|
||||||
for (const auto &[nodeA, nodeB] : collisions) {
|
|
||||||
if (auto boxA = dynamic_cast<CollisionBox *>(nodeA)) {
|
|
||||||
boxA->setColliding(true);
|
|
||||||
}
|
|
||||||
if (auto boxB = dynamic_cast<CollisionBox *>(nodeB)) {
|
|
||||||
boxB->setColliding(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<CollisionBox> centerBox_;
|
|
||||||
std::vector<Ptr<CollisionBox>> boxes_;
|
|
||||||
float rotationAngle_ = 0.0f;
|
|
||||||
float rotationSpeed_ = 60.0f; // 旋转速度(度/秒)
|
|
||||||
size_t collisionCount_ = 0;
|
|
||||||
|
|
||||||
// 字体资源
|
|
||||||
Ptr<FontAtlas> titleFont_;
|
|
||||||
Ptr<FontAtlas> infoFont_;
|
|
||||||
|
|
||||||
// UI 文本组件
|
|
||||||
Ptr<Text> titleText_;
|
|
||||||
Ptr<Text> descText_;
|
|
||||||
Ptr<Text> collideHintText_;
|
|
||||||
Ptr<Text> collisionText_;
|
|
||||||
Ptr<Text> fpsText_;
|
|
||||||
Ptr<Text> exitHintText_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// 程序入口
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
// 初始化日志系统
|
|
||||||
Logger::init();
|
|
||||||
Logger::setLevel(LogLevel::Debug);
|
|
||||||
|
|
||||||
E2D_LOG_INFO("========================");
|
|
||||||
E2D_LOG_INFO("Easy2D 碰撞检测演示");
|
|
||||||
E2D_LOG_INFO("========================");
|
|
||||||
|
|
||||||
// 获取应用实例
|
|
||||||
auto &app = Application::instance();
|
|
||||||
|
|
||||||
// 配置应用
|
|
||||||
AppConfig config;
|
|
||||||
config.title = "Easy2D - 碰撞检测演示";
|
|
||||||
config.width = 1280;
|
|
||||||
config.height = 720;
|
|
||||||
config.vsync = true;
|
|
||||||
config.fpsLimit = 60;
|
|
||||||
|
|
||||||
// 初始化应用
|
|
||||||
if (!app.init(config)) {
|
|
||||||
E2D_LOG_ERROR("应用初始化失败!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 进入场景
|
|
||||||
app.enterScene(shared<CollisionDemoScene>());
|
|
||||||
|
|
||||||
E2D_LOG_INFO("开始主循环...");
|
|
||||||
|
|
||||||
// 运行应用
|
|
||||||
app.run();
|
|
||||||
|
|
||||||
E2D_LOG_INFO("应用结束");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
|
@ -1,76 +0,0 @@
|
||||||
-- ==============================================
|
|
||||||
-- Collision Demo 示例 - Xmake 构建脚本
|
|
||||||
-- 支持平台: MinGW (Windows), Nintendo Switch
|
|
||||||
-- ==============================================
|
|
||||||
|
|
||||||
-- 获取当前脚本所在目录(示例根目录)
|
|
||||||
local example_dir = os.scriptdir()
|
|
||||||
|
|
||||||
-- 可执行文件目标
|
|
||||||
target("collision_demo")
|
|
||||||
set_kind("binary")
|
|
||||||
add_files("main.cpp")
|
|
||||||
add_includedirs("../../include")
|
|
||||||
add_deps("extra2d")
|
|
||||||
|
|
||||||
-- 使用与主项目相同的平台配置
|
|
||||||
if is_plat("switch") then
|
|
||||||
set_targetdir("../../build/examples/collision_demo")
|
|
||||||
|
|
||||||
-- 构建后生成 NRO 文件
|
|
||||||
after_build(function (target)
|
|
||||||
local devkitPro = os.getenv("DEVKITPRO") or "C:/devkitPro"
|
|
||||||
local elf_file = target:targetfile()
|
|
||||||
local output_dir = path.directory(elf_file)
|
|
||||||
local nacp_file = path.join(output_dir, "collision_demo.nacp")
|
|
||||||
local nro_file = path.join(output_dir, "collision_demo.nro")
|
|
||||||
local nacptool = path.join(devkitPro, "tools/bin/nacptool.exe")
|
|
||||||
local elf2nro = path.join(devkitPro, "tools/bin/elf2nro.exe")
|
|
||||||
|
|
||||||
if os.isfile(nacptool) and os.isfile(elf2nro) then
|
|
||||||
os.vrunv(nacptool, {"--create", "Collision Demo", "Extra2D Team", "1.0.0", nacp_file})
|
|
||||||
local romfs = path.join(example_dir, "romfs")
|
|
||||||
if os.isdir(romfs) then
|
|
||||||
os.vrunv(elf2nro, {elf_file, nro_file, "--nacp=" .. nacp_file, "--romfsdir=" .. romfs})
|
|
||||||
else
|
|
||||||
os.vrunv(elf2nro, {elf_file, nro_file, "--nacp=" .. nacp_file})
|
|
||||||
end
|
|
||||||
print("Generated NRO: " .. nro_file)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- 打包时将 NRO 文件复制到 package 目录
|
|
||||||
after_package(function (target)
|
|
||||||
local nro_file = path.join(target:targetdir(), "collision_demo.nro")
|
|
||||||
local package_dir = target:packagedir()
|
|
||||||
if os.isfile(nro_file) and package_dir then
|
|
||||||
os.cp(nro_file, package_dir)
|
|
||||||
print("Copied NRO to package: " .. package_dir)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
elseif is_plat("mingw") then
|
|
||||||
set_targetdir("../../build/examples/collision_demo")
|
|
||||||
add_ldflags("-mwindows", {force = true})
|
|
||||||
|
|
||||||
-- 复制资源到输出目录
|
|
||||||
after_build(function (target)
|
|
||||||
local romfs = path.join(example_dir, "romfs")
|
|
||||||
if os.isdir(romfs) then
|
|
||||||
local target_dir = path.directory(target:targetfile())
|
|
||||||
local assets_dir = path.join(target_dir, "assets")
|
|
||||||
|
|
||||||
-- 创建 assets 目录
|
|
||||||
if not os.isdir(assets_dir) then
|
|
||||||
os.mkdir(assets_dir)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 复制所有资源文件(包括子目录)
|
|
||||||
os.cp(path.join(romfs, "assets/**"), assets_dir)
|
|
||||||
print("Copied assets from " .. romfs .. " to " .. assets_dir)
|
|
||||||
else
|
|
||||||
print("Warning: romfs directory not found at " .. romfs)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
target_end()
|
|
||||||
|
|
@ -1,124 +1,27 @@
|
||||||
#include <extra2d.h>
|
#include <extra2d.h>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
using namespace extra2d;
|
using namespace extra2d;
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Hello World 场景
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Hello World 场景类
|
|
||||||
* 显示简单的 "Hello World" 文字
|
|
||||||
*/
|
|
||||||
class HelloWorldScene : public Scene {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief 场景进入时调用
|
|
||||||
*/
|
|
||||||
void onEnter() override {
|
|
||||||
E2D_LOG_INFO("HelloWorldScene::onEnter - 进入场景");
|
|
||||||
|
|
||||||
// 设置背景颜色为深蓝色
|
|
||||||
setBackgroundColor(Color(0.1f, 0.1f, 0.3f, 1.0f));
|
|
||||||
|
|
||||||
// 加载字体(支持多种字体后备)
|
|
||||||
auto &resources = Application::instance().resources();
|
|
||||||
font_ = resources.loadFont("assets/font.ttf", 48, true);
|
|
||||||
|
|
||||||
if (!font_) {
|
|
||||||
E2D_LOG_ERROR("字体加载失败,文字渲染将不可用!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建 "你好世界" 文本组件 - 使用节点位置
|
|
||||||
auto text1 = Text::create("你好世界", font_);
|
|
||||||
text1->setPosition(640.0f, 360.0f); // 屏幕中心
|
|
||||||
text1->setAnchor(0.5f, 0.5f); // 中心锚点,让文字中心对准位置
|
|
||||||
text1->setTextColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
|
|
||||||
addChild(text1);
|
|
||||||
|
|
||||||
// 创建提示文本组件 - 固定在屏幕底部
|
|
||||||
auto text2 = Text::create("退出按键(START 按钮)", font_);
|
|
||||||
text2->setPosition(640.0f, 650.0f); // 屏幕底部
|
|
||||||
text2->setAnchor(0.5f, 0.5f);
|
|
||||||
text2->setTextColor(Color(1.0f, 1.0f, 0.0f, 1.0f));
|
|
||||||
addChild(text2);
|
|
||||||
|
|
||||||
// 创建带偏移的文本 - 使用相对位置
|
|
||||||
auto text3 = Text::create("偏移文本", font_);
|
|
||||||
text3->setPosition(50.0f, 50.0f); // 左上角偏移
|
|
||||||
text3->setAnchor(0.0f, 0.0f); // 左上角锚点,文字从指定位置开始显示
|
|
||||||
text3->setTextColor(Color(0.0f, 1.0f, 1.0f, 1.0f));
|
|
||||||
addChild(text3);
|
|
||||||
|
|
||||||
// 创建世界空间文本 - 随相机移动(默认行为)
|
|
||||||
auto text4 = Text::create("世界空间文本", font_);
|
|
||||||
text4->setPosition(100.0f, 100.0f); // 世界坐标
|
|
||||||
text4->setAnchor(0.0f, 0.0f); // 左上角锚点,文字从指定位置开始显示
|
|
||||||
text4->setTextColor(Color(1.0f, 0.5f, 0.5f, 1.0f));
|
|
||||||
addChild(text4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 每帧更新时调用
|
|
||||||
* @param dt 时间间隔(秒)
|
|
||||||
*/
|
|
||||||
void onUpdate(float dt) override {
|
|
||||||
Scene::onUpdate(dt);
|
|
||||||
|
|
||||||
// 检查退出按键
|
|
||||||
auto &input = Application::instance().input();
|
|
||||||
|
|
||||||
// 使用手柄 START 按钮退出 (GamepadButton::Start)
|
|
||||||
if (input.isButtonPressed(GamepadButton::Start)) {
|
|
||||||
E2D_LOG_INFO("退出应用 (START 按钮)");
|
|
||||||
Application::instance().quit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ptr<FontAtlas> font_; // 字体图集
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// 程序入口
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
// 初始化日志系统
|
// 创建应用(自动创建窗口)
|
||||||
Logger::init();
|
auto app = Application::create();
|
||||||
Logger::setLevel(LogLevel::Debug);
|
|
||||||
|
|
||||||
E2D_LOG_INFO("========================");
|
|
||||||
E2D_LOG_INFO("Easy2D Hello World Demo");
|
|
||||||
E2D_LOG_INFO("========================");
|
|
||||||
|
|
||||||
// 获取应用实例
|
|
||||||
auto &app = Application::instance();
|
|
||||||
|
|
||||||
// 配置应用
|
|
||||||
AppConfig config;
|
AppConfig config;
|
||||||
config.title = "Easy2D - Hello World";
|
config.title = "Hello World";
|
||||||
config.width = 1280;
|
config.width = 1280;
|
||||||
config.height = 720;
|
config.height = 720;
|
||||||
config.vsync = true;
|
|
||||||
config.fpsLimit = 60;
|
if (!app->init(config)) {
|
||||||
|
printf("Failed to initialize!\n");
|
||||||
// 初始化应用
|
|
||||||
if (!app.init(config)) {
|
|
||||||
E2D_LOG_ERROR("应用初始化失败!");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 进入 Hello World 场景
|
printf("Window: %dx%d\n", app->getWindowWidth(), app->getWindowHeight());
|
||||||
app.enterScene(shared<HelloWorldScene>());
|
|
||||||
|
|
||||||
E2D_LOG_INFO("开始主循环...");
|
|
||||||
|
|
||||||
// 运行应用
|
// 运行应用
|
||||||
app.run();
|
app->run();
|
||||||
|
|
||||||
E2D_LOG_INFO("应用结束");
|
// 自动销毁
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,8 @@ target("hello_world")
|
||||||
|
|
||||||
elseif is_plat("mingw") then
|
elseif is_plat("mingw") then
|
||||||
set_targetdir("../../build/examples/hello_world")
|
set_targetdir("../../build/examples/hello_world")
|
||||||
add_ldflags("-mwindows", {force = true})
|
-- 使用控制台子系统以便查看输出
|
||||||
|
-- add_ldflags("-mwindows", {force = true})
|
||||||
|
|
||||||
-- 复制资源到输出目录
|
-- 复制资源到输出目录
|
||||||
after_build(function (target)
|
after_build(function (target)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ namespace extra2d {
|
||||||
|
|
||||||
// 前向声明
|
// 前向声明
|
||||||
class Context;
|
class Context;
|
||||||
|
class WindowModule;
|
||||||
|
class InputModule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 应用程序配置
|
* @brief 应用程序配置
|
||||||
|
|
@ -112,6 +114,31 @@ public:
|
||||||
*/
|
*/
|
||||||
Context* getContext() const { return context_.get(); }
|
Context* getContext() const { return context_.get(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口模块
|
||||||
|
*/
|
||||||
|
WindowModule* getWindow() const { return windowModule_.get(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取输入模块
|
||||||
|
*/
|
||||||
|
InputModule* getInput() const { return inputModule_.get(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口宽度
|
||||||
|
*/
|
||||||
|
int32 getWindowWidth() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口高度
|
||||||
|
*/
|
||||||
|
int32 getWindowHeight() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口标题
|
||||||
|
*/
|
||||||
|
const char* getWindowTitle() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Application();
|
Application();
|
||||||
|
|
||||||
|
|
@ -119,6 +146,8 @@ private:
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
std::unique_ptr<Context> context_;
|
std::unique_ptr<Context> context_;
|
||||||
|
std::unique_ptr<WindowModule> windowModule_;
|
||||||
|
std::unique_ptr<InputModule> inputModule_;
|
||||||
|
|
||||||
AppConfig config_;
|
AppConfig config_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#include <context/context.h>
|
#include <context/context.h>
|
||||||
#include <event/events.h>
|
#include <event/events.h>
|
||||||
#include <platform/sdl2.h>
|
#include <platform/sdl2.h>
|
||||||
|
#include <platform/window.h>
|
||||||
|
#include <platform/input.h>
|
||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
@ -84,6 +86,27 @@ bool Application::init(const AppConfig &config) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建窗口模块
|
||||||
|
windowModule_ = std::make_unique<WindowModule>();
|
||||||
|
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<InputModule>();
|
||||||
|
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
running_ = true;
|
running_ = true;
|
||||||
|
|
||||||
|
|
@ -103,7 +126,11 @@ void Application::shutdown() {
|
||||||
|
|
||||||
E2D_LOG_INFO("Shutting down application...");
|
E2D_LOG_INFO("Shutting down application...");
|
||||||
|
|
||||||
// 关闭上下文(会自动关闭模块和插件)
|
// 智能指针自动销毁窗口和输入模块
|
||||||
|
inputModule_.reset();
|
||||||
|
windowModule_.reset();
|
||||||
|
|
||||||
|
// 关闭上下文
|
||||||
context_.reset();
|
context_.reset();
|
||||||
|
|
||||||
Sdl2::shutdown();
|
Sdl2::shutdown();
|
||||||
|
|
@ -155,6 +182,15 @@ void Application::resume() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::mainLoop() {
|
void Application::mainLoop() {
|
||||||
|
// 处理窗口事件
|
||||||
|
if (windowModule_) {
|
||||||
|
if (!windowModule_->pollEvents()) {
|
||||||
|
// 窗口关闭事件
|
||||||
|
quit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double currentTime = getTimeSeconds();
|
double currentTime = getTimeSeconds();
|
||||||
deltaTime_ = static_cast<float>(currentTime - lastFrameTime_);
|
deltaTime_ = static_cast<float>(currentTime - lastFrameTime_);
|
||||||
lastFrameTime_ = currentTime;
|
lastFrameTime_ = currentTime;
|
||||||
|
|
@ -173,6 +209,11 @@ void Application::mainLoop() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 交换缓冲区
|
||||||
|
if (windowModule_) {
|
||||||
|
windowModule_->swapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
// 帧率限制
|
// 帧率限制
|
||||||
if (!config_.vsync && config_.fpsLimit > 0) {
|
if (!config_.vsync && config_.fpsLimit > 0) {
|
||||||
double frameEndTime = getTimeSeconds();
|
double frameEndTime = getTimeSeconds();
|
||||||
|
|
@ -192,4 +233,24 @@ void Application::update() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 Application::getWindowWidth() const {
|
||||||
|
if (windowModule_) {
|
||||||
|
Size size = windowModule_->getSize();
|
||||||
|
return static_cast<int32>(size.w);
|
||||||
|
}
|
||||||
|
return config_.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 Application::getWindowHeight() const {
|
||||||
|
if (windowModule_) {
|
||||||
|
Size size = windowModule_->getSize();
|
||||||
|
return static_cast<int32>(size.h);
|
||||||
|
}
|
||||||
|
return config_.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Application::getWindowTitle() const {
|
||||||
|
return config_.title.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -91,11 +91,10 @@ includes("xmake/engine.lua")
|
||||||
-- 定义引擎库
|
-- 定义引擎库
|
||||||
define_extra2d_engine()
|
define_extra2d_engine()
|
||||||
|
|
||||||
-- -- 示例程序目标(作为子项目)
|
-- 示例程序目标(作为子项目)
|
||||||
-- if is_config("examples","true") then
|
if is_config("examples","true") then
|
||||||
-- includes("examples/hello_world", {rootdir = "examples/hello_world"})
|
includes("examples/hello_world", {rootdir = "examples/hello_world"})
|
||||||
-- includes("examples/collision_demo", {rootdir = "examples/collision_demo"})
|
end
|
||||||
-- end
|
|
||||||
|
|
||||||
-- 测试套件目标(作为子项目)
|
-- 测试套件目标(作为子项目)
|
||||||
if is_config("tests","true") then
|
if is_config("tests","true") then
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue