refactor: 将 makePtr 和 makeUnique 重命名为 shared 和 unique
统一智能指针创建函数的命名风格,使用更直观的 shared 和 unique 替代 makePtr 和 makeUnique。 修改涉及核心类型定义、场景系统、资源管理、图形渲染等多个模块,确保代码风格一致性。 同时更新了相关文档和示例代码中的调用方式。
This commit is contained in:
parent
6fbebafef3
commit
c61edbb9dd
|
|
@ -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)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ¢er, float radius,
|
Ptr<ShapeNode> ShapeNode::createCircle(const Vec2 ¢er, 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 ¢er, 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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 §ion) const {
|
std::vector<std::string>
|
||||||
|
DataStore::getAllKeys(const std::string §ion) 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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 管理节点生命周期
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
||||||
// 动画完成后启用按钮
|
// 动画完成后启用按钮
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -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("开始主循环...");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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("开始主循环...");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -321,7 +321,7 @@ int main(int argc, char **argv) {{
|
||||||
}}
|
}}
|
||||||
|
|
||||||
// 进入主场景
|
// 进入主场景
|
||||||
app.enterScene(makePtr<MainScene>());
|
app.enterScene(shared<MainScene>());
|
||||||
|
|
||||||
E2D_LOG_INFO("开始主循环...");
|
E2D_LOG_INFO("开始主循环...");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue