refactor: 将 makePtr 和 makeUnique 重命名为 shared 和 unique

统一智能指针创建函数的命名风格,使用更直观的 shared 和 unique 替代 makePtr 和 makeUnique。
修改涉及核心类型定义、场景系统、资源管理、图形渲染等多个模块,确保代码风格一致性。
同时更新了相关文档和示例代码中的调用方式。
This commit is contained in:
ChestnutYueyue 2026-02-23 22:56:31 +08:00
parent 6fbebafef3
commit c61edbb9dd
22 changed files with 275 additions and 235 deletions

View File

@ -17,13 +17,13 @@ template <typename T> using UniquePtr = std::unique_ptr<T>;
template <typename T> using WeakPtr = std::weak_ptr<T>; template <typename T> using WeakPtr = std::weak_ptr<T>;
/// 创建 shared_ptr 的便捷函数 /// 创建 shared_ptr 的便捷函数
template <typename T, typename... Args> inline Ptr<T> makePtr(Args &&...args) { template <typename T, typename... Args> inline Ptr<T> shared(Args &&...args) {
return std::make_shared<T>(std::forward<Args>(args)...); return std::make_shared<T>(std::forward<Args>(args)...);
} }
/// 创建 unique_ptr 的便捷函数 /// 创建 unique_ptr 的便捷函数
template <typename T, typename... Args> template <typename T, typename... Args>
inline UniquePtr<T> makeUnique(Args &&...args) { inline UniquePtr<T> unique(Args &&...args) {
return std::make_unique<T>(std::forward<Args>(args)...); return std::make_unique<T>(std::forward<Args>(args)...);
} }

View File

@ -34,7 +34,7 @@ bool Application::init(const AppConfig &config) {
config_ = config; config_ = config;
window_ = makeUnique<Window>(); window_ = unique<Window>();
WindowConfig winConfig; WindowConfig winConfig;
winConfig.title = config.title; winConfig.title = config.title;
winConfig.width = config.width; winConfig.width = config.width;
@ -47,15 +47,15 @@ bool Application::init(const AppConfig &config) {
return false; return false;
} }
renderer_ = makeUnique<Renderer>(); renderer_ = unique<Renderer>();
if (!renderer_->init(window_.get())) { if (!renderer_->init(window_.get())) {
E2D_LOG_ERROR("Failed to initialize renderer"); E2D_LOG_ERROR("Failed to initialize renderer");
window_->destroy(); window_->destroy();
return false; return false;
} }
eventQueue_ = makeUnique<EventQueue>(); eventQueue_ = unique<EventQueue>();
eventDispatcher_ = makeUnique<EventDispatcher>(); eventDispatcher_ = unique<EventDispatcher>();
AudioEngine::getInstance().initialize(); AudioEngine::getInstance().initialize();
@ -106,9 +106,7 @@ void Application::run() {
} }
} }
void Application::quit() { void Application::quit() { running_ = false; }
running_ = false;
}
void Application::pause() { void Application::pause() {
if (!paused_) { if (!paused_) {
@ -173,9 +171,9 @@ void Application::render() {
} }
renderer_->beginFrame(Color::Black); renderer_->beginFrame(Color::Black);
// 渲染内容可以在这里添加 // 渲染内容可以在这里添加
renderer_->endFrame(); renderer_->endFrame();
window_->swapBuffers(); window_->swapBuffers();
} }

View File

@ -210,11 +210,11 @@ glm::mat4 GLRenderer::getCurrentTransform() const {
Ptr<Texture> GLRenderer::createTexture(int width, int height, Ptr<Texture> GLRenderer::createTexture(int width, int height,
const uint8_t *pixels, int channels) { const uint8_t *pixels, int channels) {
return makePtr<GLTexture>(width, height, pixels, channels); return shared<GLTexture>(width, height, pixels, channels);
} }
Ptr<Texture> GLRenderer::loadTexture(const std::string &filepath) { Ptr<Texture> GLRenderer::loadTexture(const std::string &filepath) {
return makePtr<GLTexture>(filepath); return shared<GLTexture>(filepath);
} }
void GLRenderer::beginSpriteBatch() { spriteBatch_.begin(viewProjection_); } void GLRenderer::beginSpriteBatch() { spriteBatch_.begin(viewProjection_); }
@ -430,7 +430,7 @@ void GLRenderer::fillPolygon(const std::vector<Vec2> &points,
Ptr<FontAtlas> GLRenderer::createFontAtlas(const std::string &filepath, Ptr<FontAtlas> GLRenderer::createFontAtlas(const std::string &filepath,
int fontSize, bool useSDF) { int fontSize, bool useSDF) {
return makePtr<GLFontAtlas>(filepath, fontSize, useSDF); return shared<GLFontAtlas>(filepath, fontSize, useSDF);
} }
void GLRenderer::drawText(const FontAtlas &font, const std::string &text, void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
@ -446,7 +446,7 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
// 收集所有字符数据用于批处理 // 收集所有字符数据用于批处理
std::vector<GLSpriteBatch::SpriteData> sprites; std::vector<GLSpriteBatch::SpriteData> sprites;
sprites.reserve(text.size()); // 预分配空间 sprites.reserve(text.size()); // 预分配空间
for (char32_t codepoint : utf8ToUtf32(text)) { for (char32_t codepoint : utf8ToUtf32(text)) {
if (codepoint == '\n') { if (codepoint == '\n') {
@ -477,7 +477,7 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
data.rotation = 0.0f; data.rotation = 0.0f;
data.anchor = glm::vec2(0.0f, 0.0f); data.anchor = glm::vec2(0.0f, 0.0f);
data.isSDF = font.isSDF(); data.isSDF = font.isSDF();
sprites.push_back(data); sprites.push_back(data);
} }
} }

View File

@ -1,6 +1,7 @@
#include <extra2d/graphics/opengl/gl_texture.h>
#include <extra2d/graphics/gpu_context.h> #include <extra2d/graphics/gpu_context.h>
#include <extra2d/graphics/opengl/gl_texture.h>
#include <extra2d/graphics/vram_manager.h> #include <extra2d/graphics/vram_manager.h>
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include <cstring> #include <cstring>
#include <extra2d/utils/logger.h> #include <extra2d/utils/logger.h>
@ -455,7 +456,7 @@ Ptr<Texture> GLTexture::create(int width, int height, PixelFormat format) {
channels = 4; channels = 4;
break; break;
} }
return makePtr<GLTexture>(width, height, nullptr, channels); return shared<GLTexture>(width, height, nullptr, channels);
} }
} // namespace extra2d } // namespace extra2d

View File

@ -1,7 +1,8 @@
#include <extra2d/graphics/texture_atlas.h>
#include <extra2d/utils/logger.h>
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <extra2d/graphics/texture_atlas.h>
#include <extra2d/utils/logger.h>
namespace extra2d { namespace extra2d {
@ -13,124 +14,134 @@ TextureAtlasPage::TextureAtlasPage(int width, int height)
: width_(width), height_(height), isFull_(false), usedArea_(0) { : width_(width), height_(height), isFull_(false), usedArea_(0) {
// 创建空白纹理 // 创建空白纹理
std::vector<uint8_t> emptyData(width * height * 4, 0); std::vector<uint8_t> emptyData(width * height * 4, 0);
texture_ = makePtr<GLTexture>(width, height, emptyData.data(), 4); texture_ = shared<GLTexture>(width, height, emptyData.data(), 4);
// 初始化矩形打包根节点 // 初始化矩形打包根节点
root_ = std::make_unique<PackNode>(0, 0, width, height); root_ = std::make_unique<PackNode>(0, 0, width, height);
E2D_LOG_INFO("Created texture atlas page: {}x{}", width, height); E2D_LOG_INFO("Created texture atlas page: {}x{}", width, height);
} }
TextureAtlasPage::~TextureAtlasPage() = default; TextureAtlasPage::~TextureAtlasPage() = default;
bool TextureAtlasPage::tryAddTexture(const std::string& name, int texWidth, int texHeight, bool TextureAtlasPage::tryAddTexture(const std::string &name, int texWidth,
const uint8_t* pixels, Rect& outUvRect) { int texHeight, const uint8_t *pixels,
Rect &outUvRect) {
if (isFull_) { if (isFull_) {
return false; return false;
} }
// 添加边距 // 添加边距
int paddedWidth = texWidth + 2 * PADDING; int paddedWidth = texWidth + 2 * PADDING;
int paddedHeight = texHeight + 2 * PADDING; int paddedHeight = texHeight + 2 * PADDING;
// 如果纹理太大,无法放入 // 如果纹理太大,无法放入
if (paddedWidth > width_ || paddedHeight > height_) { if (paddedWidth > width_ || paddedHeight > height_) {
return false; return false;
} }
// 尝试插入 // 尝试插入
PackNode* node = insert(root_.get(), paddedWidth, paddedHeight); PackNode *node = insert(root_.get(), paddedWidth, paddedHeight);
if (node == nullptr) { if (node == nullptr) {
// 无法放入,标记为满 // 无法放入,标记为满
isFull_ = true; isFull_ = true;
return false; return false;
} }
// 写入像素数据(跳过边距区域) // 写入像素数据(跳过边距区域)
writePixels(node->x + PADDING, node->y + PADDING, texWidth, texHeight, pixels); writePixels(node->x + PADDING, node->y + PADDING, texWidth, texHeight,
pixels);
// 创建条目 // 创建条目
AtlasEntry entry; AtlasEntry entry;
entry.name = name; entry.name = name;
entry.originalSize = Vec2(static_cast<float>(texWidth), static_cast<float>(texHeight)); entry.originalSize =
Vec2(static_cast<float>(texWidth), static_cast<float>(texHeight));
entry.padding = PADDING; entry.padding = PADDING;
// 计算 UV 坐标(考虑边距) // 计算 UV 坐标(考虑边距)
float u1 = static_cast<float>(node->x + PADDING) / width_; float u1 = static_cast<float>(node->x + PADDING) / width_;
float v1 = static_cast<float>(node->y + PADDING) / height_; float v1 = static_cast<float>(node->y + PADDING) / height_;
float u2 = static_cast<float>(node->x + PADDING + texWidth) / width_; float u2 = static_cast<float>(node->x + PADDING + texWidth) / width_;
float v2 = static_cast<float>(node->y + PADDING + texHeight) / height_; float v2 = static_cast<float>(node->y + PADDING + texHeight) / height_;
entry.uvRect = Rect(u1, v1, u2 - u1, v2 - v1); entry.uvRect = Rect(u1, v1, u2 - u1, v2 - v1);
outUvRect = entry.uvRect; outUvRect = entry.uvRect;
entries_[name] = std::move(entry); entries_[name] = std::move(entry);
usedArea_ += paddedWidth * paddedHeight; usedArea_ += paddedWidth * paddedHeight;
E2D_LOG_DEBUG("Added texture '{}' to atlas: {}x{} at ({}, {})", E2D_LOG_DEBUG("Added texture '{}' to atlas: {}x{} at ({}, {})", name,
name, texWidth, texHeight, node->x, node->y); texWidth, texHeight, node->x, node->y);
return true; return true;
} }
TextureAtlasPage::PackNode* TextureAtlasPage::insert(PackNode* node, int width, int height) { TextureAtlasPage::PackNode *TextureAtlasPage::insert(PackNode *node, int width,
int height) {
if (node == nullptr) { if (node == nullptr) {
return nullptr; return nullptr;
} }
// 如果节点已被使用,尝试子节点 // 如果节点已被使用,尝试子节点
if (node->used) { if (node->used) {
PackNode* result = insert(node->left.get(), width, height); PackNode *result = insert(node->left.get(), width, height);
if (result != nullptr) { if (result != nullptr) {
return result; return result;
} }
return insert(node->right.get(), width, height); return insert(node->right.get(), width, height);
} }
// 检查是否适合 // 检查是否适合
if (width > node->width || height > node->height) { if (width > node->width || height > node->height) {
return nullptr; return nullptr;
} }
// 如果刚好合适,使用此节点 // 如果刚好合适,使用此节点
if (width == node->width && height == node->height) { if (width == node->width && height == node->height) {
node->used = true; node->used = true;
return node; return node;
} }
// 需要分割节点 // 需要分割节点
int dw = node->width - width; int dw = node->width - width;
int dh = node->height - height; int dh = node->height - height;
if (dw > dh) { if (dw > dh) {
// 水平分割 // 水平分割
node->left = std::make_unique<PackNode>(node->x, node->y, width, node->height); node->left =
node->right = std::make_unique<PackNode>(node->x + width, node->y, dw, node->height); std::make_unique<PackNode>(node->x, node->y, width, node->height);
node->right =
std::make_unique<PackNode>(node->x + width, node->y, dw, node->height);
} else { } else {
// 垂直分割 // 垂直分割
node->left = std::make_unique<PackNode>(node->x, node->y, node->width, height); node->left =
node->right = std::make_unique<PackNode>(node->x, node->y + height, node->width, dh); std::make_unique<PackNode>(node->x, node->y, node->width, height);
node->right =
std::make_unique<PackNode>(node->x, node->y + height, node->width, dh);
} }
// 递归插入到左子节点 // 递归插入到左子节点
return insert(node->left.get(), width, height); return insert(node->left.get(), width, height);
} }
void TextureAtlasPage::writePixels(int x, int y, int w, int h, const uint8_t* pixels) { void TextureAtlasPage::writePixels(int x, int y, int w, int h,
const uint8_t *pixels) {
if (texture_ == nullptr || pixels == nullptr) { if (texture_ == nullptr || pixels == nullptr) {
return; return;
} }
// 使用 glTexSubImage2D 更新纹理数据 // 使用 glTexSubImage2D 更新纹理数据
GLuint texID = static_cast<GLuint>( GLuint texID = static_cast<GLuint>(
reinterpret_cast<uintptr_t>(texture_->getNativeHandle())); reinterpret_cast<uintptr_t>(texture_->getNativeHandle()));
glBindTexture(GL_TEXTURE_2D, texID); glBindTexture(GL_TEXTURE_2D, texID);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
pixels);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
} }
const AtlasEntry* TextureAtlasPage::getEntry(const std::string& name) const { const AtlasEntry *TextureAtlasPage::getEntry(const std::string &name) const {
auto it = entries_.find(name); auto it = entries_.find(name);
if (it != entries_.end()) { if (it != entries_.end()) {
return &it->second; return &it->second;
@ -147,11 +158,8 @@ float TextureAtlasPage::getUsageRatio() const {
// ============================================================================ // ============================================================================
TextureAtlas::TextureAtlas() TextureAtlas::TextureAtlas()
: pageSize_(TextureAtlasPage::DEFAULT_SIZE), : pageSize_(TextureAtlasPage::DEFAULT_SIZE), sizeThreshold_(256),
sizeThreshold_(256), enabled_(true), initialized_(false) {}
enabled_(true),
initialized_(false) {
}
TextureAtlas::~TextureAtlas() = default; TextureAtlas::~TextureAtlas() = default;
@ -161,33 +169,33 @@ void TextureAtlas::init(int pageSize) {
E2D_LOG_INFO("TextureAtlas initialized with page size: {}", pageSize); E2D_LOG_INFO("TextureAtlas initialized with page size: {}", pageSize);
} }
bool TextureAtlas::addTexture(const std::string& name, int width, int height, bool TextureAtlas::addTexture(const std::string &name, int width, int height,
const uint8_t* pixels) { const uint8_t *pixels) {
if (!enabled_ || !initialized_) { if (!enabled_ || !initialized_) {
return false; return false;
} }
// 检查是否已存在 // 检查是否已存在
if (contains(name)) { if (contains(name)) {
return true; return true;
} }
// 检查纹理大小 // 检查纹理大小
if (width > sizeThreshold_ || height > sizeThreshold_) { if (width > sizeThreshold_ || height > sizeThreshold_) {
E2D_LOG_DEBUG("Texture '{}' too large for atlas ({}x{} > {}), skipping", E2D_LOG_DEBUG("Texture '{}' too large for atlas ({}x{} > {}), skipping",
name, width, height, sizeThreshold_); name, width, height, sizeThreshold_);
return false; return false;
} }
// 尝试添加到现有页面 // 尝试添加到现有页面
Rect uvRect; Rect uvRect;
for (auto& page : pages_) { for (auto &page : pages_) {
if (page->tryAddTexture(name, width, height, pixels, uvRect)) { if (page->tryAddTexture(name, width, height, pixels, uvRect)) {
entryToPage_[name] = page.get(); entryToPage_[name] = page.get();
return true; return true;
} }
} }
// 创建新页面 // 创建新页面
auto newPage = std::make_unique<TextureAtlasPage>(pageSize_, pageSize_); auto newPage = std::make_unique<TextureAtlasPage>(pageSize_, pageSize_);
if (newPage->tryAddTexture(name, width, height, pixels, uvRect)) { if (newPage->tryAddTexture(name, width, height, pixels, uvRect)) {
@ -195,16 +203,16 @@ bool TextureAtlas::addTexture(const std::string& name, int width, int height,
pages_.push_back(std::move(newPage)); pages_.push_back(std::move(newPage));
return true; return true;
} }
E2D_LOG_WARN("Failed to add texture '{}' to atlas", name); E2D_LOG_WARN("Failed to add texture '{}' to atlas", name);
return false; return false;
} }
bool TextureAtlas::contains(const std::string& name) const { bool TextureAtlas::contains(const std::string &name) const {
return entryToPage_.find(name) != entryToPage_.end(); return entryToPage_.find(name) != entryToPage_.end();
} }
const Texture* TextureAtlas::getAtlasTexture(const std::string& name) const { const Texture *TextureAtlas::getAtlasTexture(const std::string &name) const {
auto it = entryToPage_.find(name); auto it = entryToPage_.find(name);
if (it != entryToPage_.end()) { if (it != entryToPage_.end()) {
return it->second->getTexture().get(); return it->second->getTexture().get();
@ -212,10 +220,10 @@ const Texture* TextureAtlas::getAtlasTexture(const std::string& name) const {
return nullptr; return nullptr;
} }
Rect TextureAtlas::getUVRect(const std::string& name) const { Rect TextureAtlas::getUVRect(const std::string &name) const {
auto it = entryToPage_.find(name); auto it = entryToPage_.find(name);
if (it != entryToPage_.end()) { if (it != entryToPage_.end()) {
const AtlasEntry* entry = it->second->getEntry(name); const AtlasEntry *entry = it->second->getEntry(name);
if (entry != nullptr) { if (entry != nullptr) {
return entry->uvRect; return entry->uvRect;
} }
@ -223,10 +231,10 @@ Rect TextureAtlas::getUVRect(const std::string& name) const {
return Rect(0, 0, 1, 1); // 默认 UV return Rect(0, 0, 1, 1); // 默认 UV
} }
Vec2 TextureAtlas::getOriginalSize(const std::string& name) const { Vec2 TextureAtlas::getOriginalSize(const std::string &name) const {
auto it = entryToPage_.find(name); auto it = entryToPage_.find(name);
if (it != entryToPage_.end()) { if (it != entryToPage_.end()) {
const AtlasEntry* entry = it->second->getEntry(name); const AtlasEntry *entry = it->second->getEntry(name);
if (entry != nullptr) { if (entry != nullptr) {
return entry->originalSize; return entry->originalSize;
} }
@ -238,9 +246,9 @@ float TextureAtlas::getTotalUsageRatio() const {
if (pages_.empty()) { if (pages_.empty()) {
return 0.0f; return 0.0f;
} }
float total = 0.0f; float total = 0.0f;
for (const auto& page : pages_) { for (const auto &page : pages_) {
total += page->getUsageRatio(); total += page->getUsageRatio();
} }
return total / pages_.size(); return total / pages_.size();
@ -256,7 +264,7 @@ void TextureAtlas::clear() {
// TextureAtlasManager 单例实现 // TextureAtlasManager 单例实现
// ============================================================================ // ============================================================================
TextureAtlasManager& TextureAtlasManager::getInstance() { TextureAtlasManager &TextureAtlasManager::getInstance() {
static TextureAtlasManager instance; static TextureAtlasManager instance;
return instance; return instance;
} }

View File

@ -41,7 +41,8 @@ static std::string getExecutableDirectory() {
} }
#endif #endif
// 解析资源路径(优先尝试 romfs:/ 前缀,然后 sdmc:/,最后尝试相对于可执行文件的路径) // 解析资源路径(优先尝试 romfs:/ 前缀,然后
// sdmc:/,最后尝试相对于可执行文件的路径)
static std::string resolveResourcePath(const std::string &filepath) { static std::string resolveResourcePath(const std::string &filepath) {
// 如果已经是 romfs 或 sdmc 路径,直接返回 // 如果已经是 romfs 或 sdmc 路径,直接返回
if (isRomfsPath(filepath) || filepath.find("sdmc:/") == 0) { if (isRomfsPath(filepath) || filepath.find("sdmc:/") == 0) {
@ -81,9 +82,7 @@ static std::string resolveResourcePath(const std::string &filepath) {
ResourceManager::ResourceManager() = default; ResourceManager::ResourceManager() = default;
ResourceManager::~ResourceManager() { ResourceManager::~ResourceManager() { shutdownAsyncLoader(); }
shutdownAsyncLoader();
}
ResourceManager &ResourceManager::getInstance() { ResourceManager &ResourceManager::getInstance() {
static ResourceManager instance; static ResourceManager instance;
@ -98,9 +97,10 @@ void ResourceManager::initAsyncLoader() {
if (asyncRunning_) { if (asyncRunning_) {
return; return;
} }
asyncRunning_ = true; asyncRunning_ = true;
asyncThread_ = std::make_unique<std::thread>(&ResourceManager::asyncLoadLoop, this); asyncThread_ =
std::make_unique<std::thread>(&ResourceManager::asyncLoadLoop, this);
E2D_LOG_INFO("ResourceManager: async loader initialized"); E2D_LOG_INFO("ResourceManager: async loader initialized");
} }
@ -108,14 +108,14 @@ void ResourceManager::shutdownAsyncLoader() {
if (!asyncRunning_) { if (!asyncRunning_) {
return; return;
} }
asyncRunning_ = false; asyncRunning_ = false;
asyncCondition_.notify_all(); asyncCondition_.notify_all();
if (asyncThread_ && asyncThread_->joinable()) { if (asyncThread_ && asyncThread_->joinable()) {
asyncThread_->join(); asyncThread_->join();
} }
E2D_LOG_INFO("ResourceManager: async loader shutdown"); E2D_LOG_INFO("ResourceManager: async loader shutdown");
} }
@ -132,34 +132,35 @@ bool ResourceManager::hasPendingAsyncLoads() const {
void ResourceManager::asyncLoadLoop() { void ResourceManager::asyncLoadLoop() {
while (asyncRunning_) { while (asyncRunning_) {
AsyncLoadTask task; AsyncLoadTask task;
{ {
std::unique_lock<std::mutex> lock(asyncQueueMutex_); std::unique_lock<std::mutex> lock(asyncQueueMutex_);
asyncCondition_.wait(lock, [this] { return !asyncTaskQueue_.empty() || !asyncRunning_; }); asyncCondition_.wait(
lock, [this] { return !asyncTaskQueue_.empty() || !asyncRunning_; });
if (!asyncRunning_) { if (!asyncRunning_) {
break; break;
} }
if (asyncTaskQueue_.empty()) { if (asyncTaskQueue_.empty()) {
continue; continue;
} }
task = std::move(asyncTaskQueue_.front()); task = std::move(asyncTaskQueue_.front());
asyncTaskQueue_.pop(); asyncTaskQueue_.pop();
} }
// 执行加载 // 执行加载
auto texture = loadTextureInternal(task.filepath, task.format); auto texture = loadTextureInternal(task.filepath, task.format);
// 回调 // 回调
if (task.callback) { if (task.callback) {
task.callback(texture); task.callback(texture);
} }
// 设置 promise // 设置 promise
task.promise.set_value(texture); task.promise.set_value(texture);
pendingAsyncLoads_--; pendingAsyncLoads_--;
} }
} }
@ -172,25 +173,30 @@ Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath) {
return loadTexture(filepath, false, TextureFormat::Auto); return loadTexture(filepath, false, TextureFormat::Auto);
} }
Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath, bool async) { Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath,
bool async) {
return loadTexture(filepath, async, TextureFormat::Auto); return loadTexture(filepath, async, TextureFormat::Auto);
} }
Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath, bool async, TextureFormat format) { Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath,
bool async, TextureFormat format) {
if (async) { if (async) {
// 异步加载:返回空指针,实际纹理通过回调获取 // 异步加载:返回空指针,实际纹理通过回调获取
loadTextureAsync(filepath, format, nullptr); loadTextureAsync(filepath, format, nullptr);
return nullptr; return nullptr;
} }
return loadTextureInternal(filepath, format); return loadTextureInternal(filepath, format);
} }
void ResourceManager::loadTextureAsync(const std::string &filepath, TextureLoadCallback callback) { void ResourceManager::loadTextureAsync(const std::string &filepath,
TextureLoadCallback callback) {
loadTextureAsync(filepath, TextureFormat::Auto, callback); loadTextureAsync(filepath, TextureFormat::Auto, callback);
} }
void ResourceManager::loadTextureAsync(const std::string &filepath, TextureFormat format, TextureLoadCallback callback) { void ResourceManager::loadTextureAsync(const std::string &filepath,
TextureFormat format,
TextureLoadCallback callback) {
// 确保异步加载系统已启动 // 确保异步加载系统已启动
if (!asyncRunning_) { if (!asyncRunning_) {
initAsyncLoader(); initAsyncLoader();
@ -229,7 +235,8 @@ void ResourceManager::loadTextureAsync(const std::string &filepath, TextureForma
E2D_LOG_DEBUG("ResourceManager: queued async texture load: {}", filepath); E2D_LOG_DEBUG("ResourceManager: queued async texture load: {}", filepath);
} }
Ptr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath, TextureFormat format) { Ptr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath,
TextureFormat format) {
std::lock_guard<std::mutex> lock(textureMutex_); std::lock_guard<std::mutex> lock(textureMutex_);
// 检查缓存 // 检查缓存
@ -255,7 +262,7 @@ Ptr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath, T
// 创建新纹理 // 创建新纹理
try { try {
auto texture = makePtr<GLTexture>(fullPath); auto texture = shared<GLTexture>(fullPath);
if (!texture->isValid()) { if (!texture->isValid()) {
E2D_LOG_ERROR("ResourceManager: failed to load texture: {}", filepath); E2D_LOG_ERROR("ResourceManager: failed to load texture: {}", filepath);
return nullptr; return nullptr;
@ -273,7 +280,8 @@ Ptr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath, T
evictTexturesIfNeeded(); evictTexturesIfNeeded();
// 计算纹理大小 // 计算纹理大小
size_t textureSize = calculateTextureSize(texture->getWidth(), texture->getHeight(), texture->getFormat()); size_t textureSize = calculateTextureSize(
texture->getWidth(), texture->getHeight(), texture->getFormat());
// 分配LRU节点 // 分配LRU节点
uint32_t lruIndex = allocateLRUNode(filepath); uint32_t lruIndex = allocateLRUNode(filepath);
@ -292,7 +300,8 @@ Ptr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath, T
// 添加到LRU链表头部 // 添加到LRU链表头部
moveToFront(lruIndex); moveToFront(lruIndex);
E2D_LOG_DEBUG("ResourceManager: loaded texture: {} ({} KB)", filepath, textureSize / 1024); E2D_LOG_DEBUG("ResourceManager: loaded texture: {} ({} KB)", filepath,
textureSize / 1024);
return texture; return texture;
} catch (...) { } catch (...) {
E2D_LOG_ERROR("ResourceManager: exception loading texture: {}", filepath); E2D_LOG_ERROR("ResourceManager: exception loading texture: {}", filepath);
@ -304,24 +313,26 @@ TextureFormat ResourceManager::selectBestFormat(TextureFormat requested) const {
if (requested != TextureFormat::Auto) { if (requested != TextureFormat::Auto) {
return requested; return requested;
} }
// 自动选择最佳格式 // 自动选择最佳格式
// 检查支持的扩展 // 检查支持的扩展
// 这里简化处理,实际应该查询 OpenGL 扩展 // 这里简化处理,实际应该查询 OpenGL 扩展
// 桌面平台优先 DXT // 桌面平台优先 DXT
// 移动平台优先 ETC2 或 ASTC // 移动平台优先 ETC2 或 ASTC
// 默认返回 RGBA8 // 默认返回 RGBA8
return TextureFormat::RGBA8; return TextureFormat::RGBA8;
} }
std::vector<uint8_t> ResourceManager::compressTexture(const uint8_t* data, int width, int height, std::vector<uint8_t> ResourceManager::compressTexture(const uint8_t *data,
int channels, TextureFormat format) { int width, int height,
int channels,
TextureFormat format) {
// 纹理压缩实现 // 纹理压缩实现
// 这里需要根据格式使用相应的压缩库 // 这里需要根据格式使用相应的压缩库
// 如squish (DXT), etcpack (ETC2), astc-encoder (ASTC) // 如squish (DXT), etcpack (ETC2), astc-encoder (ASTC)
// 目前返回原始数据 // 目前返回原始数据
std::vector<uint8_t> result(data, data + width * height * channels); std::vector<uint8_t> result(data, data + width * height * channels);
return result; return result;
@ -383,9 +394,9 @@ Ptr<Texture> ResourceManager::getTexture(const std::string &key) const {
auto it = textureCache_.find(key); auto it = textureCache_.find(key);
if (it != textureCache_.end()) { if (it != textureCache_.end()) {
const_cast<ResourceManager*>(this)->touchTexture(key); const_cast<ResourceManager *>(this)->touchTexture(key);
const_cast<ResourceManager*>(this)->textureHitCount_++; const_cast<ResourceManager *>(this)->textureHitCount_++;
const_cast<uint32_t&>(it->second.accessCount)++; const_cast<uint32_t &>(it->second.accessCount)++;
return it->second.texture; return it->second.texture;
} }
return nullptr; return nullptr;
@ -402,8 +413,9 @@ void ResourceManager::unloadTexture(const std::string &key) {
auto it = textureCache_.find(key); auto it = textureCache_.find(key);
if (it != textureCache_.end()) { if (it != textureCache_.end()) {
// 从LRU链表中移除 // 从LRU链表中移除
auto nodeIt = std::find_if(lruNodes_.begin(), lruNodes_.end(), auto nodeIt = std::find_if(
[&key](const LRUNode &node) { return node.valid && node.key == key; }); lruNodes_.begin(), lruNodes_.end(),
[&key](const LRUNode &node) { return node.valid && node.key == key; });
if (nodeIt != lruNodes_.end()) { if (nodeIt != lruNodes_.end()) {
removeFromList(static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1); removeFromList(static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1);
freeLRUNode(static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1); freeLRUNode(static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1);
@ -453,7 +465,7 @@ Ptr<FontAtlas> ResourceManager::loadFont(const std::string &filepath,
// 创建新字体图集 // 创建新字体图集
try { try {
auto font = makePtr<GLFontAtlas>(fullPath, fontSize, useSDF); auto font = shared<GLFontAtlas>(fullPath, fontSize, useSDF);
if (!font->getTexture() || !font->getTexture()->isValid()) { if (!font->getTexture() || !font->getTexture()->isValid()) {
E2D_LOG_ERROR("ResourceManager: failed to load font: {}", filepath); E2D_LOG_ERROR("ResourceManager: failed to load font: {}", filepath);
return nullptr; return nullptr;
@ -648,7 +660,8 @@ size_t ResourceManager::getTextureCacheSize() const {
// LRU 缓存管理 // LRU 缓存管理
// ============================================================================ // ============================================================================
void ResourceManager::setTextureCache(size_t maxCacheSize, size_t maxTextureCount, void ResourceManager::setTextureCache(size_t maxCacheSize,
size_t maxTextureCount,
float unloadInterval) { float unloadInterval) {
std::lock_guard<std::mutex> lock(textureMutex_); std::lock_guard<std::mutex> lock(textureMutex_);
maxCacheSize_ = maxCacheSize; maxCacheSize_ = maxCacheSize;
@ -694,7 +707,8 @@ void ResourceManager::update(float dt) {
size_t targetSize = static_cast<size_t>(maxCacheSize_ * 0.5f); size_t targetSize = static_cast<size_t>(maxCacheSize_ * 0.5f);
while (totalTextureSize_ > targetSize && lruTail_ != 0) { while (totalTextureSize_ > targetSize && lruTail_ != 0) {
std::string key = evictLRU(); std::string key = evictLRU();
if (key.empty()) break; if (key.empty())
break;
auto it = textureCache_.find(key); auto it = textureCache_.find(key);
if (it != textureCache_.end()) { if (it != textureCache_.end()) {
@ -703,7 +717,8 @@ void ResourceManager::update(float dt) {
E2D_LOG_DEBUG("ResourceManager: auto-evicted texture: {}", key); E2D_LOG_DEBUG("ResourceManager: auto-evicted texture: {}", key);
} }
} }
E2D_LOG_INFO("ResourceManager: texture cache trimmed to {} MB", totalTextureSize_ / (1024 * 1024)); E2D_LOG_INFO("ResourceManager: texture cache trimmed to {} MB",
totalTextureSize_ / (1024 * 1024));
} }
} }
} }
@ -733,7 +748,8 @@ uint32_t ResourceManager::allocateLRUNode(const std::string &key) {
} }
void ResourceManager::freeLRUNode(uint32_t index) { void ResourceManager::freeLRUNode(uint32_t index) {
if (index == 0 || index > lruNodes_.size()) return; if (index == 0 || index > lruNodes_.size())
return;
LRUNode &node = lruNodes_[index - 1]; LRUNode &node = lruNodes_[index - 1];
node.valid = false; node.valid = false;
@ -744,7 +760,8 @@ void ResourceManager::freeLRUNode(uint32_t index) {
} }
void ResourceManager::moveToFront(uint32_t index) { void ResourceManager::moveToFront(uint32_t index) {
if (index == 0 || index > lruNodes_.size() || index == lruHead_) return; if (index == 0 || index > lruNodes_.size() || index == lruHead_)
return;
removeFromList(index); removeFromList(index);
@ -763,7 +780,8 @@ void ResourceManager::moveToFront(uint32_t index) {
} }
void ResourceManager::removeFromList(uint32_t index) { void ResourceManager::removeFromList(uint32_t index) {
if (index == 0 || index > lruNodes_.size()) return; if (index == 0 || index > lruNodes_.size())
return;
LRUNode &node = lruNodes_[index - 1]; LRUNode &node = lruNodes_[index - 1];
@ -781,7 +799,8 @@ void ResourceManager::removeFromList(uint32_t index) {
} }
std::string ResourceManager::evictLRU() { std::string ResourceManager::evictLRU() {
if (lruTail_ == 0) return ""; if (lruTail_ == 0)
return "";
uint32_t index = lruTail_; uint32_t index = lruTail_;
std::string key = lruNodes_[index - 1].key; std::string key = lruNodes_[index - 1].key;
@ -794,8 +813,9 @@ std::string ResourceManager::evictLRU() {
void ResourceManager::touchTexture(const std::string &key) { void ResourceManager::touchTexture(const std::string &key) {
// 查找对应的LRU节点 // 查找对应的LRU节点
auto nodeIt = std::find_if(lruNodes_.begin(), lruNodes_.end(), auto nodeIt = std::find_if(
[&key](const LRUNode &node) { return node.valid && node.key == key; }); lruNodes_.begin(), lruNodes_.end(),
[&key](const LRUNode &node) { return node.valid && node.key == key; });
if (nodeIt != lruNodes_.end()) { if (nodeIt != lruNodes_.end()) {
uint32_t index = static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1; uint32_t index = static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1;
moveToFront(index); moveToFront(index);
@ -813,7 +833,8 @@ void ResourceManager::evictTexturesIfNeeded() {
textureCache_.size() >= maxTextureCount_) && textureCache_.size() >= maxTextureCount_) &&
lruTail_ != 0) { lruTail_ != 0) {
std::string key = evictLRU(); std::string key = evictLRU();
if (key.empty()) break; if (key.empty())
break;
auto it = textureCache_.find(key); auto it = textureCache_.find(key);
if (it != textureCache_.end()) { if (it != textureCache_.end()) {
@ -824,24 +845,25 @@ void ResourceManager::evictTexturesIfNeeded() {
} }
} }
size_t ResourceManager::calculateTextureSize(int width, int height, PixelFormat format) const { size_t ResourceManager::calculateTextureSize(int width, int height,
PixelFormat format) const {
int bytesPerPixel = 4; int bytesPerPixel = 4;
switch (format) { switch (format) {
case PixelFormat::R8: case PixelFormat::R8:
bytesPerPixel = 1; bytesPerPixel = 1;
break; break;
case PixelFormat::RG8: case PixelFormat::RG8:
bytesPerPixel = 2; bytesPerPixel = 2;
break; break;
case PixelFormat::RGB8: case PixelFormat::RGB8:
bytesPerPixel = 3; bytesPerPixel = 3;
break; break;
case PixelFormat::RGBA8: case PixelFormat::RGBA8:
bytesPerPixel = 4; bytesPerPixel = 4;
break; break;
default: default:
bytesPerPixel = 4; bytesPerPixel = 4;
break; break;
} }
return static_cast<size_t>(width * height * bytesPerPixel); return static_cast<size_t>(width * height * bytesPerPixel);
} }
@ -864,7 +886,8 @@ std::string ResourceManager::loadTextFile(const std::string &filepath) {
return loadTextFile(filepath, "UTF-8"); return loadTextFile(filepath, "UTF-8");
} }
std::string ResourceManager::loadTextFile(const std::string &filepath, const std::string &encoding) { std::string ResourceManager::loadTextFile(const std::string &filepath,
const std::string &encoding) {
(void)encoding; // 目前只支持 UTF-8 (void)encoding; // 目前只支持 UTF-8
std::lock_guard<std::mutex> lock(textFileMutex_); std::lock_guard<std::mutex> lock(textFileMutex_);
@ -888,13 +911,15 @@ std::string ResourceManager::loadTextFile(const std::string &filepath, const std
#ifdef _WIN32 #ifdef _WIN32
errno_t err = fopen_s(&file, resolvedPath.c_str(), "rb"); errno_t err = fopen_s(&file, resolvedPath.c_str(), "rb");
if (err != 0 || !file) { if (err != 0 || !file) {
E2D_LOG_ERROR("ResourceManager: failed to open text file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to open text file: {}",
resolvedPath);
return ""; return "";
} }
#else #else
file = fopen(resolvedPath.c_str(), "rb"); file = fopen(resolvedPath.c_str(), "rb");
if (!file) { if (!file) {
E2D_LOG_ERROR("ResourceManager: failed to open text file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to open text file: {}",
resolvedPath);
return ""; return "";
} }
#endif #endif
@ -917,13 +942,15 @@ std::string ResourceManager::loadTextFile(const std::string &filepath, const std
fclose(file); fclose(file);
if (readSize != static_cast<size_t>(fileSize)) { if (readSize != static_cast<size_t>(fileSize)) {
E2D_LOG_ERROR("ResourceManager: failed to read text file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to read text file: {}",
resolvedPath);
return ""; return "";
} }
// 缓存内容 // 缓存内容
textFileCache_[filepath] = content; textFileCache_[filepath] = content;
E2D_LOG_DEBUG("ResourceManager: loaded text file: {} ({} bytes)", filepath, content.size()); E2D_LOG_DEBUG("ResourceManager: loaded text file: {} ({} bytes)", filepath,
content.size());
return content; return content;
} }
@ -989,13 +1016,15 @@ std::string ResourceManager::loadJsonFile(const std::string &filepath) {
#ifdef _WIN32 #ifdef _WIN32
errno_t err = fopen_s(&file, resolvedPath.c_str(), "rb"); errno_t err = fopen_s(&file, resolvedPath.c_str(), "rb");
if (err != 0 || !file) { if (err != 0 || !file) {
E2D_LOG_ERROR("ResourceManager: failed to open JSON file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to open JSON file: {}",
resolvedPath);
return ""; return "";
} }
#else #else
file = fopen(resolvedPath.c_str(), "rb"); file = fopen(resolvedPath.c_str(), "rb");
if (!file) { if (!file) {
E2D_LOG_ERROR("ResourceManager: failed to open JSON file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to open JSON file: {}",
resolvedPath);
return ""; return "";
} }
#endif #endif
@ -1018,7 +1047,8 @@ std::string ResourceManager::loadJsonFile(const std::string &filepath) {
fclose(file); fclose(file);
if (readSize != static_cast<size_t>(fileSize)) { if (readSize != static_cast<size_t>(fileSize)) {
E2D_LOG_ERROR("ResourceManager: failed to read JSON file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to read JSON file: {}",
resolvedPath);
return ""; return "";
} }
@ -1032,7 +1062,8 @@ std::string ResourceManager::loadJsonFile(const std::string &filepath) {
// 缓存内容 // 缓存内容
jsonFileCache_[filepath] = content; jsonFileCache_[filepath] = content;
E2D_LOG_DEBUG("ResourceManager: loaded JSON file: {} ({} bytes)", filepath, content.size()); E2D_LOG_DEBUG("ResourceManager: loaded JSON file: {} ({} bytes)", filepath,
content.size());
return content; return content;
} }

View File

@ -5,7 +5,7 @@
namespace extra2d { namespace extra2d {
Scene::Scene() { defaultCamera_ = makePtr<Camera>(); } Scene::Scene() { defaultCamera_ = shared<Camera>(); }
void Scene::setCamera(Ptr<Camera> camera) { camera_ = camera; } void Scene::setCamera(Ptr<Camera> camera) { camera_ = camera; }
@ -126,6 +126,6 @@ void Scene::collectRenderCommands(std::vector<RenderCommand> &commands,
Node::collectRenderCommands(commands, parentZOrder); Node::collectRenderCommands(commands, parentZOrder);
} }
Ptr<Scene> Scene::create() { return makePtr<Scene>(); } Ptr<Scene> Scene::create() { return shared<Scene>(); }
} // namespace extra2d } // namespace extra2d

View File

@ -9,10 +9,10 @@ namespace extra2d {
ShapeNode::ShapeNode() = default; ShapeNode::ShapeNode() = default;
Ptr<ShapeNode> ShapeNode::create() { return makePtr<ShapeNode>(); } Ptr<ShapeNode> ShapeNode::create() { return shared<ShapeNode>(); }
Ptr<ShapeNode> ShapeNode::createPoint(const Vec2 &pos, const Color &color) { Ptr<ShapeNode> ShapeNode::createPoint(const Vec2 &pos, const Color &color) {
auto node = makePtr<ShapeNode>(); auto node = shared<ShapeNode>();
node->shapeType_ = ShapeType::Point; node->shapeType_ = ShapeType::Point;
node->color_ = color; node->color_ = color;
node->points_ = {pos}; node->points_ = {pos};
@ -21,7 +21,7 @@ Ptr<ShapeNode> ShapeNode::createPoint(const Vec2 &pos, const Color &color) {
Ptr<ShapeNode> ShapeNode::createLine(const Vec2 &start, const Vec2 &end, Ptr<ShapeNode> ShapeNode::createLine(const Vec2 &start, const Vec2 &end,
const Color &color, float width) { const Color &color, float width) {
auto node = makePtr<ShapeNode>(); auto node = shared<ShapeNode>();
node->shapeType_ = ShapeType::Line; node->shapeType_ = ShapeType::Line;
node->color_ = color; node->color_ = color;
node->lineWidth_ = width; node->lineWidth_ = width;
@ -31,7 +31,7 @@ Ptr<ShapeNode> ShapeNode::createLine(const Vec2 &start, const Vec2 &end,
Ptr<ShapeNode> ShapeNode::createRect(const Rect &rect, const Color &color, Ptr<ShapeNode> ShapeNode::createRect(const Rect &rect, const Color &color,
float width) { float width) {
auto node = makePtr<ShapeNode>(); auto node = shared<ShapeNode>();
node->shapeType_ = ShapeType::Rect; node->shapeType_ = ShapeType::Rect;
node->color_ = color; node->color_ = color;
node->lineWidth_ = width; node->lineWidth_ = width;
@ -52,7 +52,7 @@ Ptr<ShapeNode> ShapeNode::createFilledRect(const Rect &rect,
Ptr<ShapeNode> ShapeNode::createCircle(const Vec2 &center, float radius, Ptr<ShapeNode> ShapeNode::createCircle(const Vec2 &center, float radius,
const Color &color, int segments, const Color &color, int segments,
float width) { float width) {
auto node = makePtr<ShapeNode>(); auto node = shared<ShapeNode>();
node->shapeType_ = ShapeType::Circle; node->shapeType_ = ShapeType::Circle;
node->color_ = color; node->color_ = color;
node->lineWidth_ = width; node->lineWidth_ = width;
@ -74,7 +74,7 @@ Ptr<ShapeNode> ShapeNode::createFilledCircle(const Vec2 &center, float radius,
Ptr<ShapeNode> ShapeNode::createTriangle(const Vec2 &p1, const Vec2 &p2, Ptr<ShapeNode> ShapeNode::createTriangle(const Vec2 &p1, const Vec2 &p2,
const Vec2 &p3, const Color &color, const Vec2 &p3, const Color &color,
float width) { float width) {
auto node = makePtr<ShapeNode>(); auto node = shared<ShapeNode>();
node->shapeType_ = ShapeType::Triangle; node->shapeType_ = ShapeType::Triangle;
node->color_ = color; node->color_ = color;
node->lineWidth_ = width; node->lineWidth_ = width;
@ -93,7 +93,7 @@ Ptr<ShapeNode> ShapeNode::createFilledTriangle(const Vec2 &p1, const Vec2 &p2,
Ptr<ShapeNode> ShapeNode::createPolygon(const std::vector<Vec2> &points, Ptr<ShapeNode> ShapeNode::createPolygon(const std::vector<Vec2> &points,
const Color &color, float width) { const Color &color, float width) {
auto node = makePtr<ShapeNode>(); auto node = shared<ShapeNode>();
node->shapeType_ = ShapeType::Polygon; node->shapeType_ = ShapeType::Polygon;
node->color_ = color; node->color_ = color;
node->lineWidth_ = width; node->lineWidth_ = width;
@ -262,16 +262,16 @@ void ShapeNode::generateRenderCommand(std::vector<RenderCommand> &commands,
case ShapeType::Point: case ShapeType::Point:
if (!points_.empty()) { if (!points_.empty()) {
cmd.type = RenderCommandType::FilledCircle; cmd.type = RenderCommandType::FilledCircle;
cmd.data = cmd.data = CircleCommandData{
CircleCommandData{points_[0] + offset, lineWidth_ * 0.5f, color_, 8, 0.0f, true}; points_[0] + offset, lineWidth_ * 0.5f, color_, 8, 0.0f, true};
} }
break; break;
case ShapeType::Line: case ShapeType::Line:
if (points_.size() >= 2) { if (points_.size() >= 2) {
cmd.type = RenderCommandType::Line; cmd.type = RenderCommandType::Line;
cmd.data = LineCommandData{points_[0] + offset, points_[1] + offset, color_, cmd.data = LineCommandData{points_[0] + offset, points_[1] + offset,
lineWidth_}; color_, lineWidth_};
} }
break; break;
@ -281,14 +281,14 @@ void ShapeNode::generateRenderCommand(std::vector<RenderCommand> &commands,
cmd.type = RenderCommandType::FilledRect; cmd.type = RenderCommandType::FilledRect;
Rect rect(points_[0].x, points_[0].y, points_[2].x - points_[0].x, Rect rect(points_[0].x, points_[0].y, points_[2].x - points_[0].x,
points_[2].y - points_[0].y); points_[2].y - points_[0].y);
cmd.data = cmd.data = RectCommandData{Rect(rect.origin + offset, rect.size),
RectCommandData{Rect(rect.origin + offset, rect.size), color_, 0.0f, true}; color_, 0.0f, true};
} else { } else {
cmd.type = RenderCommandType::Rect; cmd.type = RenderCommandType::Rect;
Rect rect(points_[0].x, points_[0].y, points_[2].x - points_[0].x, Rect rect(points_[0].x, points_[0].y, points_[2].x - points_[0].x,
points_[2].y - points_[0].y); points_[2].y - points_[0].y);
cmd.data = cmd.data = RectCommandData{Rect(rect.origin + offset, rect.size),
RectCommandData{Rect(rect.origin + offset, rect.size), color_, lineWidth_, false}; color_, lineWidth_, false};
} }
} }
break; break;
@ -298,12 +298,12 @@ void ShapeNode::generateRenderCommand(std::vector<RenderCommand> &commands,
float radius = points_[1].x; float radius = points_[1].x;
if (filled_) { if (filled_) {
cmd.type = RenderCommandType::FilledCircle; cmd.type = RenderCommandType::FilledCircle;
cmd.data = cmd.data = CircleCommandData{points_[0] + offset, radius, color_,
CircleCommandData{points_[0] + offset, radius, color_, segments_, 0.0f, true}; segments_, 0.0f, true};
} else { } else {
cmd.type = RenderCommandType::Circle; cmd.type = RenderCommandType::Circle;
cmd.data = CircleCommandData{points_[0] + offset, radius, color_, segments_, cmd.data = CircleCommandData{points_[0] + offset, radius, color_,
lineWidth_, false}; segments_, lineWidth_, false};
} }
} }
break; break;
@ -336,7 +336,8 @@ void ShapeNode::generateRenderCommand(std::vector<RenderCommand> &commands,
cmd.data = PolygonCommandData{transformedPoints, color_, 0.0f, true}; cmd.data = PolygonCommandData{transformedPoints, color_, 0.0f, true};
} else { } else {
cmd.type = RenderCommandType::Polygon; cmd.type = RenderCommandType::Polygon;
cmd.data = PolygonCommandData{transformedPoints, color_, lineWidth_, false}; cmd.data =
PolygonCommandData{transformedPoints, color_, lineWidth_, false};
} }
} }
break; break;

View File

@ -31,14 +31,14 @@ void Sprite::setFlipX(bool flip) { flipX_ = flip; }
void Sprite::setFlipY(bool flip) { flipY_ = flip; } void Sprite::setFlipY(bool flip) { flipY_ = flip; }
Ptr<Sprite> Sprite::create() { return makePtr<Sprite>(); } Ptr<Sprite> Sprite::create() { return shared<Sprite>(); }
Ptr<Sprite> Sprite::create(Ptr<Texture> texture) { Ptr<Sprite> Sprite::create(Ptr<Texture> texture) {
return makePtr<Sprite>(texture); return shared<Sprite>(texture);
} }
Ptr<Sprite> Sprite::create(Ptr<Texture> texture, const Rect &rect) { Ptr<Sprite> Sprite::create(Ptr<Texture> texture, const Rect &rect) {
auto sprite = makePtr<Sprite>(texture); auto sprite = shared<Sprite>(texture);
sprite->setTextureRect(rect); sprite->setTextureRect(rect);
return sprite; return sprite;
} }

View File

@ -15,7 +15,7 @@ public:
CSimpleIniA ini; CSimpleIniA ini;
}; };
DataStore::DataStore() : impl_(makeUnique<Impl>()) {} DataStore::DataStore() : impl_(unique<Impl>()) {}
DataStore::~DataStore() { DataStore::~DataStore() {
// 如果在事务中,尝试提交 // 如果在事务中,尝试提交
@ -203,9 +203,7 @@ std::string DataStore::getSaveDataPath(const std::string &path) const {
return path; return path;
} }
UserId DataStore::getCurrentUserId() { UserId DataStore::getCurrentUserId() { return UserId(); }
return UserId();
}
#endif #endif
@ -402,7 +400,8 @@ std::vector<std::string> DataStore::getAllSections() const {
return sections; return sections;
} }
std::vector<std::string> DataStore::getAllKeys(const std::string &section) const { std::vector<std::string>
DataStore::getAllKeys(const std::string &section) const {
std::vector<std::string> keys; std::vector<std::string> keys;
CSimpleIniA::TNamesDepend keyList; CSimpleIniA::TNamesDepend keyList;
impl_->ini.GetAllKeys(section.c_str(), keyList); impl_->ini.GetAllKeys(section.c_str(), keyList);

View File

@ -1,6 +1,7 @@
#include <extra2d/window/window.h>
#include <extra2d/platform/input.h> #include <extra2d/platform/input.h>
#include <extra2d/utils/logger.h> #include <extra2d/utils/logger.h>
#include <extra2d/window/window.h>
#include <SDL.h> #include <SDL.h>
#include <glad/glad.h> #include <glad/glad.h>
@ -8,10 +9,8 @@
namespace extra2d { namespace extra2d {
Window::Window() Window::Window()
: sdlWindow_(nullptr), glContext_(nullptr), : sdlWindow_(nullptr), glContext_(nullptr), width_(1280), height_(720),
width_(1280), height_(720), vsync_(true), shouldClose_(false), vsync_(true), shouldClose_(false), fullscreen_(true) {}
fullscreen_(true) {
}
Window::~Window() { destroy(); } Window::~Window() { destroy(); }
@ -31,7 +30,7 @@ bool Window::create(const WindowConfig &config) {
return false; return false;
} }
input_ = makeUnique<Input>(); input_ = unique<Input>();
input_->init(); input_->init();
E2D_LOG_INFO("Window created: {}x{}", width_, height_); E2D_LOG_INFO("Window created: {}x{}", width_, height_);
@ -57,7 +56,7 @@ bool Window::initSDL(const WindowConfig &config) {
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
Uint32 windowFlags = SDL_WINDOW_OPENGL; Uint32 windowFlags = SDL_WINDOW_OPENGL;
if (config.fullscreen) { if (config.fullscreen) {
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
} else { } else {
@ -71,7 +70,7 @@ bool Window::initSDL(const WindowConfig &config) {
config.centerWindow ? SDL_WINDOWPOS_CENTERED : SDL_WINDOWPOS_UNDEFINED, config.centerWindow ? SDL_WINDOWPOS_CENTERED : SDL_WINDOWPOS_UNDEFINED,
config.centerWindow ? SDL_WINDOWPOS_CENTERED : SDL_WINDOWPOS_UNDEFINED, config.centerWindow ? SDL_WINDOWPOS_CENTERED : SDL_WINDOWPOS_UNDEFINED,
width_, height_, windowFlags); width_, height_, windowFlags);
if (!sdlWindow_) { if (!sdlWindow_) {
E2D_LOG_ERROR("SDL_CreateWindow failed: {}", SDL_GetError()); E2D_LOG_ERROR("SDL_CreateWindow failed: {}", SDL_GetError());
SDL_Quit(); SDL_Quit();
@ -97,7 +96,8 @@ bool Window::initSDL(const WindowConfig &config) {
return false; return false;
} }
if (gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress)) == 0) { if (gladLoadGLES2Loader(
reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress)) == 0) {
E2D_LOG_ERROR("gladLoadGLES2Loader failed"); E2D_LOG_ERROR("gladLoadGLES2Loader failed");
SDL_GL_DeleteContext(glContext_); SDL_GL_DeleteContext(glContext_);
glContext_ = nullptr; glContext_ = nullptr;
@ -110,8 +110,10 @@ bool Window::initSDL(const WindowConfig &config) {
SDL_GL_SetSwapInterval(vsync_ ? 1 : 0); SDL_GL_SetSwapInterval(vsync_ ? 1 : 0);
E2D_LOG_INFO("SDL2 + OpenGL ES 3.0 initialized successfully"); E2D_LOG_INFO("SDL2 + OpenGL ES 3.0 initialized successfully");
E2D_LOG_INFO("OpenGL Version: {}", reinterpret_cast<const char*>(glGetString(GL_VERSION))); E2D_LOG_INFO("OpenGL Version: {}",
E2D_LOG_INFO("OpenGL Renderer: {}", reinterpret_cast<const char*>(glGetString(GL_RENDERER))); reinterpret_cast<const char *>(glGetString(GL_VERSION)));
E2D_LOG_INFO("OpenGL Renderer: {}",
reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
return true; return true;
} }

View File

@ -105,7 +105,7 @@ int main(int argc, char **argv)
} }
// 进入 Hello World 场景 // 进入 Hello World 场景
app.enterScene(makePtr<HelloWorldScene>()); app.enterScene(shared<HelloWorldScene>());
// 运行应用 // 运行应用
app.run(); app.run();

View File

@ -96,7 +96,7 @@ void BaseScene::updateViewport() {
setViewportSize(GAME_WIDTH, GAME_HEIGHT); setViewportSize(GAME_WIDTH, GAME_HEIGHT);
// 创建并设置相机 // 创建并设置相机
auto camera = extra2d::makePtr<extra2d::Camera>(); auto camera = extra2d::shared<extra2d::Camera>();
camera->setViewport(0.0f, GAME_WIDTH, GAME_HEIGHT, 0.0f); camera->setViewport(0.0f, GAME_WIDTH, GAME_HEIGHT, 0.0f);
setCamera(camera); setCamera(camera);
} }
@ -146,7 +146,7 @@ void GameScene::onEnter() {
float screenHeight = GAME_HEIGHT; // 512.0f float screenHeight = GAME_HEIGHT; // 512.0f
// 所有坐标都基于逻辑分辨率 // 所有坐标都基于逻辑分辨率
auto bird = extra2d::makePtr<Bird>(); auto bird = extra2d::shared<Bird>();
bird->setPosition(extra2d::Vec2(screenWidth / 2.0f - 50.0f, screenHeight / 2.0f)); bird->setPosition(extra2d::Vec2(screenWidth / 2.0f - 50.0f, screenHeight / 2.0f));
addChild(bird); addChild(bird);
} }
@ -246,17 +246,17 @@ public:
auto& scenes = app.scenes(); auto& scenes = app.scenes();
// 运行第一个场景 // 运行第一个场景
scenes.runWithScene(makePtr<GameScene>()); scenes.runWithScene(shared<GameScene>());
// 替换当前场景(无过渡) // 替换当前场景(无过渡)
scenes.replaceScene(makePtr<GameScene>()); scenes.replaceScene(shared<GameScene>());
// 替换当前场景(有过渡效果) // 替换当前场景(有过渡效果)
scenes.replaceScene(makePtr<GameScene>(), TransitionType::Fade, 0.5f); scenes.replaceScene(shared<GameScene>(), TransitionType::Fade, 0.5f);
// 推入场景(保留当前场景) // 推入场景(保留当前场景)
scenes.pushScene(makePtr<NewScene>()); scenes.pushScene(shared<NewScene>());
scenes.pushScene(makePtr<NewScene>(), TransitionType::SlideLeft, 0.5f); scenes.pushScene(shared<NewScene>(), TransitionType::SlideLeft, 0.5f);
// 弹出场景(返回上一个场景) // 弹出场景(返回上一个场景)
scenes.popScene(); scenes.popScene();
@ -319,7 +319,7 @@ scenes.end();
## 场景生命周期 ## 场景生命周期
``` ```
创建场景 (makePtr<Scene>) 创建场景 (shared<Scene>)
进入场景 (runWithScene/replaceScene/pushScene) 进入场景 (runWithScene/replaceScene/pushScene)
@ -452,7 +452,7 @@ private:
switch (selectedIndex_) { switch (selectedIndex_) {
case 0: case 0:
scenes.replaceScene(makePtr<GameScene>(), scenes.replaceScene(shared<GameScene>(),
TransitionType::Fade, 0.25f); TransitionType::Fade, 0.25f);
break; break;
case 1: case 1:

View File

@ -170,7 +170,7 @@ panel->setPosition(Vec2(0, 256)); // 相对于父节点的中心
addChild(panel); addChild(panel);
// 添加子节点到 panel // 添加子节点到 panel
auto scoreNumber = makePtr<Number>(); auto scoreNumber = shared<Number>();
scoreNumber->setPosition(Vec2(95.0f, 10.0f)); // 相对于 panel 中心 scoreNumber->setPosition(Vec2(95.0f, 10.0f)); // 相对于 panel 中心
panel->addChild(scoreNumber); panel->addChild(scoreNumber);
@ -384,7 +384,7 @@ parent->reorderChild(child, newZOrder);
class Player : public Node { class Player : public Node {
public: public:
static Ptr<Player> create(Ptr<Texture> texture) { static Ptr<Player> create(Ptr<Texture> texture) {
auto player = makePtr<Player>(); auto player = shared<Player>();
if (player->init(texture)) { if (player->init(texture)) {
return player; return player;
} }
@ -454,7 +454,7 @@ void GameOverLayer::onEnter() {
initButtons(); initButtons();
// 创建向上移动的动画 // 创建向上移动的动画
auto moveAction = extra2d::makePtr<extra2d::MoveBy>( auto moveAction = extra2d::shared<extra2d::MoveBy>(
1.0f, extra2d::Vec2(0.0f, -screenHeight) 1.0f, extra2d::Vec2(0.0f, -screenHeight)
); );
runAction(moveAction); runAction(moveAction);
@ -474,7 +474,7 @@ void GameOverLayer::initPanel(int score, float screenHeight) {
addChild(panel); addChild(panel);
// 显示本局得分(相对于 panel 的本地坐标) // 显示本局得分(相对于 panel 的本地坐标)
auto scoreNumber = extra2d::makePtr<Number>(); auto scoreNumber = extra2d::shared<Number>();
scoreNumber->setLittleNumber(score); scoreNumber->setLittleNumber(score);
scoreNumber->setPosition(extra2d::Vec2(95.0f, 10.0f)); scoreNumber->setPosition(extra2d::Vec2(95.0f, 10.0f));
panel->addChild(scoreNumber); panel->addChild(scoreNumber);
@ -483,7 +483,7 @@ void GameOverLayer::initPanel(int score, float screenHeight) {
static int bestScore = 0; static int bestScore = 0;
if (score > bestScore) bestScore = score; if (score > bestScore) bestScore = score;
auto bestNumber = extra2d::makePtr<Number>(); auto bestNumber = extra2d::shared<Number>();
bestNumber->setLittleNumber(bestScore); bestNumber->setLittleNumber(bestScore);
bestNumber->setPosition(extra2d::Vec2(95.0f, 50.0f)); bestNumber->setPosition(extra2d::Vec2(95.0f, 50.0f));
panel->addChild(bestNumber); panel->addChild(bestNumber);
@ -591,16 +591,16 @@ Extra2D 提供了丰富的动作类:
```cpp ```cpp
// 移动动画 // 移动动画
auto moveAction = makePtr<MoveBy>(1.0f, Vec2(0.0f, -100.0f)); auto moveAction = shared<MoveBy>(1.0f, Vec2(0.0f, -100.0f));
node->runAction(moveAction); node->runAction(moveAction);
// 缩放动画 // 缩放动画
auto scaleAction = makePtr<ScaleTo>(0.5f, 2.0f); auto scaleAction = shared<ScaleTo>(0.5f, 2.0f);
node->runAction(scaleAction); node->runAction(scaleAction);
// 淡入淡出 // 淡入淡出
auto fadeOut = makePtr<FadeOut>(0.3f); auto fadeOut = shared<FadeOut>(0.3f);
auto fadeIn = makePtr<FadeIn>(0.3f); auto fadeIn = shared<FadeIn>(0.3f);
node->runAction(fadeOut); node->runAction(fadeOut);
``` ```
@ -614,7 +614,7 @@ void GameOverLayer::onEnter() {
Node::onEnter(); Node::onEnter();
// 创建向上移动的动画 // 创建向上移动的动画
auto moveAction = extra2d::makePtr<extra2d::MoveBy>( auto moveAction = extra2d::shared<extra2d::MoveBy>(
1.0f, extra2d::Vec2(0.0f, -screenHeight)); 1.0f, extra2d::Vec2(0.0f, -screenHeight));
// 设置动画完成回调 // 设置动画完成回调
@ -636,7 +636,7 @@ void GameOverLayer::onEnter() {
```cpp ```cpp
// 顺序执行:先移动,再缩放,最后淡出 // 顺序执行:先移动,再缩放,最后淡出
auto sequence = makePtr<Sequence>({ auto sequence = shared<Sequence>({
new MoveTo(1.0f, Vec2(100, 100)), new MoveTo(1.0f, Vec2(100, 100)),
new ScaleTo(0.5f, 2.0f), new ScaleTo(0.5f, 2.0f),
new FadeOut(0.3f) new FadeOut(0.3f)
@ -644,21 +644,21 @@ auto sequence = makePtr<Sequence>({
node->runAction(sequence); node->runAction(sequence);
// 并行执行:同时移动和旋转 // 并行执行:同时移动和旋转
auto spawn = makePtr<Spawn>({ auto spawn = shared<Spawn>({
new MoveTo(1.0f, Vec2(100, 100)), new MoveTo(1.0f, Vec2(100, 100)),
new RotateBy(1.0f, 360.0f) new RotateBy(1.0f, 360.0f)
}); });
node->runAction(spawn); node->runAction(spawn);
// 循环执行 // 循环执行
auto loop = makePtr<Loop(new RotateBy(1.0f, 360.0f), 5); // 旋转5次 auto loop = shared<Loop(new RotateBy(1.0f, 360.0f), 5); // 旋转5次
node->runAction(loop); node->runAction(loop);
``` ```
### 动画进度回调 ### 动画进度回调
```cpp ```cpp
auto action = makePtr<MoveTo>(2.0f, Vec2(100, 100)); auto action = shared<MoveTo>(2.0f, Vec2(100, 100));
action->setProgressCallback([](float progress) { action->setProgressCallback([](float progress) {
// progress: 0.0 - 1.0 // progress: 0.0 - 1.0
E2D_LOG_INFO("动画进度: {}%", progress * 100); E2D_LOG_INFO("动画进度: {}%", progress * 100);

View File

@ -332,7 +332,7 @@ ResLoader::getKeyFrame(const std::string &name) {
} }
const ImageInfo &info = it->second; const ImageInfo &info = it->second;
return extra2d::makePtr<extra2d::SpriteFrame>( return extra2d::shared<extra2d::SpriteFrame>(
atlasTexture_, extra2d::Rect(info.x, info.y, info.width, info.height)); atlasTexture_, extra2d::Rect(info.x, info.y, info.width, info.height));
} }

View File

@ -165,7 +165,7 @@ void GameOverLayer::onUpdate(float dt) {
if (input.isButtonPressed(extra2d::GamepadButton::A)) { if (input.isButtonPressed(extra2d::GamepadButton::A)) {
ResLoader::playMusic(MusicType::Click); ResLoader::playMusic(MusicType::Click);
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
app.scenes().replaceScene(extra2d::makePtr<GameScene>(), app.scenes().replaceScene(extra2d::shared<GameScene>(),
extra2d::TransitionType::Fade, 0.5f); extra2d::TransitionType::Fade, 0.5f);
} }
@ -173,7 +173,7 @@ void GameOverLayer::onUpdate(float dt) {
if (input.isButtonPressed(extra2d::GamepadButton::B)) { if (input.isButtonPressed(extra2d::GamepadButton::B)) {
ResLoader::playMusic(MusicType::Click); ResLoader::playMusic(MusicType::Click);
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
app.scenes().replaceScene(extra2d::makePtr<StartScene>(), app.scenes().replaceScene(extra2d::shared<StartScene>(),
extra2d::TransitionType::Fade, 0.5f); extra2d::TransitionType::Fade, 0.5f);
} }
} }
@ -221,7 +221,7 @@ void GameOverLayer::onUpdate(float dt) {
if (input.isButtonPressed(extra2d::GamepadButton::A)) { if (input.isButtonPressed(extra2d::GamepadButton::A)) {
ResLoader::playMusic(MusicType::Click); ResLoader::playMusic(MusicType::Click);
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
app.scenes().replaceScene(extra2d::makePtr<GameScene>(), app.scenes().replaceScene(extra2d::shared<GameScene>(),
extra2d::TransitionType::Fade, 0.5f); extra2d::TransitionType::Fade, 0.5f);
} }
@ -229,7 +229,7 @@ void GameOverLayer::onUpdate(float dt) {
if (input.isButtonPressed(extra2d::GamepadButton::B)) { if (input.isButtonPressed(extra2d::GamepadButton::B)) {
ResLoader::playMusic(MusicType::Click); ResLoader::playMusic(MusicType::Click);
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
app.scenes().replaceScene(extra2d::makePtr<StartScene>(), app.scenes().replaceScene(extra2d::shared<StartScene>(),
extra2d::TransitionType::Fade, 0.5f); extra2d::TransitionType::Fade, 0.5f);
} }
} }

View File

@ -85,7 +85,7 @@ public:
} }
void createBox(float x, float y) { void createBox(float x, float y) {
auto box = makePtr<CollidableBox>(50.0f, 50.0f, Color(0.3f, 0.7f, 1.0f, 0.8f)); auto box = shared<CollidableBox>(50.0f, 50.0f, Color(0.3f, 0.7f, 1.0f, 0.8f));
box->setPosition(Vec2(x, y)); box->setPosition(Vec2(x, y));
addChild(box); // 通过 addChild 管理节点生命周期 addChild(box); // 通过 addChild 管理节点生命周期
} }

View File

@ -231,7 +231,7 @@ void GameOverLayer::onEnter() {
initButtons(); initButtons();
// 创建动画 // 创建动画
auto moveAction = extra2d::makePtr<extra2d::MoveBy>( auto moveAction = extra2d::shared<extra2d::MoveBy>(
1.0f, extra2d::Vec2(0.0f, -screenHeight)); 1.0f, extra2d::Vec2(0.0f, -screenHeight));
// 动画完成后启用按钮 // 动画完成后启用按钮

View File

@ -173,7 +173,7 @@ void Bird::jump() {
restartBtn_->setOnClick([]() { restartBtn_->setOnClick([]() {
ResLoader::playMusic(MusicType::Click); // 播放点击音效 ResLoader::playMusic(MusicType::Click); // 播放点击音效
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
app.scenes().replaceScene(extra2d::makePtr<GameScene>(), app.scenes().replaceScene(extra2d::shared<GameScene>(),
extra2d::TransitionType::Fade, 0.5f); extra2d::TransitionType::Fade, 0.5f);
}); });
``` ```

View File

@ -67,7 +67,7 @@ public:
// 创建移动的中心方块 // 创建移动的中心方块
centerBox_ = centerBox_ =
makePtr<CollisionBox>(80.0f, 80.0f, Color(0.2f, 0.6f, 1.0f, 0.8f)); shared<CollisionBox>(80.0f, 80.0f, Color(0.2f, 0.6f, 1.0f, 0.8f));
centerBox_->setPosition(Vec2(centerX, centerY)); centerBox_->setPosition(Vec2(centerX, centerY));
addChild(centerBox_); addChild(centerBox_);
@ -149,7 +149,8 @@ private:
addChild(fpsText_); addChild(fpsText_);
// 创建退出提示文本 // 创建退出提示文本
float screenHeight = static_cast<float>(Application::instance().getConfig().height); float screenHeight =
static_cast<float>(Application::instance().getConfig().height);
exitHintText_ = Text::create("按 + 键退出", infoFont_); exitHintText_ = Text::create("按 + 键退出", infoFont_);
exitHintText_->setPosition(50.0f, screenHeight - 50.0f); exitHintText_->setPosition(50.0f, screenHeight - 50.0f);
exitHintText_->setTextColor(Color(0.8f, 0.8f, 0.8f, 1.0f)); exitHintText_->setTextColor(Color(0.8f, 0.8f, 0.8f, 1.0f));
@ -182,7 +183,7 @@ private:
}; };
for (const auto &[pos, color] : positions) { for (const auto &[pos, color] : positions) {
auto box = makePtr<CollisionBox>(70.0f, 70.0f, color); auto box = shared<CollisionBox>(70.0f, 70.0f, color);
box->setPosition(pos); box->setPosition(pos);
addChild(box); addChild(box);
boxes_.push_back(box); boxes_.push_back(box);
@ -238,8 +239,7 @@ private:
// 程序入口 // 程序入口
// ============================================================================ // ============================================================================
int main(int argc, char **argv) int main(int argc, char **argv) {
{
// 初始化日志系统 // 初始化日志系统
Logger::init(); Logger::init();
Logger::setLevel(LogLevel::Debug); Logger::setLevel(LogLevel::Debug);
@ -266,7 +266,7 @@ int main(int argc, char **argv)
} }
// 进入场景 // 进入场景
app.enterScene(makePtr<CollisionDemoScene>()); app.enterScene(shared<CollisionDemoScene>());
E2D_LOG_INFO("开始主循环..."); E2D_LOG_INFO("开始主循环...");

View File

@ -115,7 +115,7 @@ int main(int argc, char **argv) {
} }
// 进入 Hello World 场景 // 进入 Hello World 场景
app.enterScene(makePtr<HelloWorldScene>()); app.enterScene(shared<HelloWorldScene>());
E2D_LOG_INFO("开始主循环..."); E2D_LOG_INFO("开始主循环...");

View File

@ -321,7 +321,7 @@ int main(int argc, char **argv) {{
}} }}
// 进入主场景 // 进入主场景
app.enterScene(makePtr<MainScene>()); app.enterScene(shared<MainScene>());
E2D_LOG_INFO("开始主循环..."); E2D_LOG_INFO("开始主循环...");