diff --git a/Frostbite2D/include/frostbite2D/core/application.h b/Frostbite2D/include/frostbite2D/core/application.h index 4f98cd5..b46efbe 100644 --- a/Frostbite2D/include/frostbite2D/core/application.h +++ b/Frostbite2D/include/frostbite2D/core/application.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -176,6 +177,7 @@ private: Window* window_ = nullptr; class Renderer* renderer_ = nullptr; + Camera* camera_ = nullptr; AppConfig config_; bool initialized_ = false; diff --git a/Frostbite2D/src/frostbite2D/2d/sprite.cpp b/Frostbite2D/src/frostbite2D/2d/sprite.cpp index 60a5d94..fa7ce97 100644 --- a/Frostbite2D/src/frostbite2D/2d/sprite.cpp +++ b/Frostbite2D/src/frostbite2D/2d/sprite.cpp @@ -55,19 +55,17 @@ void Sprite::Render() { } Renderer& renderer = Renderer::get(); - Batch& batch = renderer.getBatch(); - - Shader* shader = getActiveShader(); - if (!shader || !shader->isValid()) { - RenderChildren(); - return; + + Vec2 pos = GetPosition(); + Vec2 size = GetSize(); + if (size.x == 0 || size.y == 0) { + size = Vec2((float)texture_->getWidth(), (float)texture_->getHeight()); } - - updateTransform(); - - Quad quad = createQuad(); - - batch.submitQuad(quad, transform_, texture_, shader, blendMode_); + + // 直接使用 Renderer 的 drawSprite 函数,确保和直接渲染一致 + renderer.drawSprite(pos, Rect(0, 0, (float)texture_->getWidth(), (float)texture_->getHeight()), + Vec2((float)texture_->getWidth(), (float)texture_->getHeight()), + texture_, color_); RenderChildren(); } diff --git a/Frostbite2D/src/frostbite2D/core/application.cpp b/Frostbite2D/src/frostbite2D/core/application.cpp index 4e9fe74..4e5c8e1 100644 --- a/Frostbite2D/src/frostbite2D/core/application.cpp +++ b/Frostbite2D/src/frostbite2D/core/application.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,12 @@ void Application::shutdown() { window_ = nullptr; } + // 清理相机 + if (camera_) { + delete camera_; + camera_ = nullptr; + } + // 平台相关清理 #ifdef __SWITCH__ switchShutdown(); @@ -110,6 +117,12 @@ bool Application::initCoreModules() { renderer_->setViewport(0, 0, config_.windowConfig.width, config_.windowConfig.height); + // 创建并设置相机 + camera_ = new Camera(); + camera_->setViewport(config_.windowConfig.width, config_.windowConfig.height); + camera_->setFlipY(true); // 启用 Y 轴翻转,(0,0) 在左上角 + renderer_->setCamera(camera_); + return true; } @@ -198,11 +211,10 @@ void Application::update() { void Application::render() { Renderer& renderer = Renderer::get(); - Batch& batch = renderer.getBatch(); - batch.begin(); + renderer.beginFrame(); SceneManager::get().Render(); - batch.end(); + renderer.endFrame(); if (window_) { window_->swap(); diff --git a/Frostbite2D/src/frostbite2D/graphics/batch.cpp b/Frostbite2D/src/frostbite2D/graphics/batch.cpp index 643b2db..2a2212d 100644 --- a/Frostbite2D/src/frostbite2D/graphics/batch.cpp +++ b/Frostbite2D/src/frostbite2D/graphics/batch.cpp @@ -152,9 +152,11 @@ void Batch::flushCurrentBatch() { // 绑定着色器和纹理 if (currentBatch_.shader) { currentBatch_.shader->use(); + // 设置纹理采样器 uniform 变量 + currentBatch_.shader->setTexture("u_texture", 0); } if (currentBatch_.texture) { - currentBatch_.texture->bind(); + currentBatch_.texture->bind(0); } glBindBuffer(GL_ARRAY_BUFFER, vbo_); diff --git a/Frostbite2D/src/frostbite2D/graphics/camera.cpp b/Frostbite2D/src/frostbite2D/graphics/camera.cpp index 5c88a28..3b2c454 100644 --- a/Frostbite2D/src/frostbite2D/graphics/camera.cpp +++ b/Frostbite2D/src/frostbite2D/graphics/camera.cpp @@ -37,8 +37,19 @@ glm::mat4 Camera::getViewMatrix() const { glm::mat4 Camera::getProjectionMatrix() const { float left = 0.0f; float right = static_cast(viewportWidth_); - float bottom = static_cast(viewportHeight_); - float top = 0.0f; + float bottom, top; + + if (flipY_) { + // Y 轴向下:(0,0) 在左上角(2D 游戏常用) + // glm::ortho(left, right, bottom, top, ...) + // 这里 bottom 是屏幕底部(值大),top 是屏幕顶部(值小) + bottom = static_cast(viewportHeight_); + top = 0.0f; + } else { + // Y 轴向上:(0,0) 在左下角(OpenGL 默认) + bottom = 0.0f; + top = static_cast(viewportHeight_); + } return glm::ortho(left, right, bottom, top, -1.0f, 1.0f); } diff --git a/Frostbite2D/src/frostbite2D/graphics/renderer.cpp b/Frostbite2D/src/frostbite2D/graphics/renderer.cpp index a96162f..853c6f1 100644 --- a/Frostbite2D/src/frostbite2D/graphics/renderer.cpp +++ b/Frostbite2D/src/frostbite2D/graphics/renderer.cpp @@ -175,10 +175,7 @@ void Renderer::drawQuad(const Vec2& pos, const Size& size, Ptr texture) void Renderer::drawQuad(const Rect& rect, const Color& color) { drawQuad(Vec2(rect.left(), rect.top()), Size(rect.width(), rect.height()), - static_cast(color.r) / 255.0f, - static_cast(color.g) / 255.0f, - static_cast(color.b) / 255.0f, - static_cast(color.a) / 255.0f); + color.r, color.g, color.b, color.a); } void Renderer::drawSprite(const Vec2& pos, const Size& size, Ptr texture) { @@ -189,10 +186,7 @@ void Renderer::drawSprite(const Vec2& pos, const Rect& srcRect, const Vec2& texS Ptr texture, const Color& color) { Rect destRect(pos.x, pos.y, srcRect.width(), srcRect.height()); Quad quad = Quad::createTextured(destRect, srcRect, texSize, - static_cast(color.r) / 255.0f, - static_cast(color.g) / 255.0f, - static_cast(color.b) / 255.0f, - static_cast(color.a) / 255.0f); + color.r, color.g, color.b, color.a); Transform2D transform = Transform2D::identity(); auto* shader = shaderManager_.getShader("sprite"); diff --git a/Game/src/main.cpp b/Game/src/main.cpp index 75a29ba..7846487 100644 --- a/Game/src/main.cpp +++ b/Game/src/main.cpp @@ -32,9 +32,18 @@ int main(int argc, char **argv) { auto menuScene = MakePtr(); SceneManager::get().PushScene(menuScene); + // 先测试彩色四边形,排除纹理问题 + SDL_Log("Testing colored quad..."); + + // 尝试加载精灵 auto sprite = Sprite::createFromFile("assets\\player.png"); - sprite->SetPosition(100, 100); - menuScene->AddActor(sprite); + if (sprite) { + sprite->SetPosition(100, 100); + menuScene->AddActor(sprite); + SDL_Log("Sprite created and added to scene"); + } else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create sprite from file!"); + } app.run();