feat: add BadAppleScene

This commit is contained in:
2026-02-09 10:05:41 +08:00
parent e23edaa2e7
commit bdcaa8547d
12 changed files with 151395 additions and 3 deletions

View File

@@ -52,6 +52,7 @@ set(SOURCE_FILES
src/network/server/GameServer.cpp src/network/server/GameServer.cpp
src/network/NetworkManager.cpp src/network/NetworkManager.cpp
src/graphics/texture/TextureManager.cpp src/graphics/texture/TextureManager.cpp
src/scenes/other/BadAppleScene.cpp
) )

151179
assets/BadApple.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -116,4 +116,5 @@ void GameApplication::run() {
void GameApplication::cleanup() { void GameApplication::cleanup() {
m_sceneManager->destoryQuitedScene(); m_sceneManager->destoryQuitedScene();
m_inputManager->clearInput();
} }

View File

@@ -3,14 +3,16 @@
#include "core/Time.h" #include "core/Time.h"
#include "utils/Tools.h" #include "utils/Tools.h"
#include <iostream> #include <iostream>
BoardRenderer::BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer, TextureManager* textureManager) : BoardRenderer::BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer, TextureManager* textureManager) :
m_Width(WIDTH), m_Width(WIDTH),
m_Height(HEIGHT), m_Height(HEIGHT),
m_renderer(renderer), m_renderer(renderer),
m_textureManager(textureManager) m_textureManager(textureManager)
{ {
m_cellSize = HEIGHT / m_boardRow;
m_cellSize = std::min(WIDTH, HEIGHT) / std::min(m_boardRow, m_boardCOL);
m_area = getBoardArea(); m_area = getBoardArea();
} }

View File

@@ -72,6 +72,11 @@ SDL_AppResult InputManager::handleInputEvent(const SDL_Event* event) {
m_badapple.clear(); m_badapple.clear();
} }
break; break;
case SDLK_Q:
m_currentInputState.isQ = true;
break;
case SDLK_R:
m_currentInputState.isR = true;
} }
break; break;
@@ -82,3 +87,8 @@ SDL_AppResult InputManager::handleInputEvent(const SDL_Event* event) {
InputState InputManager::GetInputState() const { InputState InputManager::GetInputState() const {
return m_currentInputState; return m_currentInputState;
} }
void InputManager::clearInput() {
m_currentInputState.isQ = false;
m_currentInputState.isR = false;
}

View File

@@ -9,6 +9,8 @@ public:
SDL_AppResult handleInputEvent(const SDL_Event* event); SDL_AppResult handleInputEvent(const SDL_Event* event);
InputState GetInputState() const; InputState GetInputState() const;
void clearInput();
private: private:
InputState& m_currentInputState; InputState& m_currentInputState;
CoreData& m_coreData; CoreData& m_coreData;

View File

@@ -10,4 +10,6 @@ struct InputState
glm::ivec2 mouseCurrentLogicalPosition; glm::ivec2 mouseCurrentLogicalPosition;
bool isFullscreen = false; bool isFullscreen = false;
bool isBadApplePress = false; bool isBadApplePress = false;
bool isQ = false;
bool isR = false;
}; };

View File

@@ -21,7 +21,8 @@ enum class SceneType {
MainMenuScene, MainMenuScene,
GameScene, GameScene,
OnlineGameScene OnlineGameScene,
BadAppleScene
}; };
// 自定义哈希器 // 自定义哈希器

View File

@@ -43,6 +43,9 @@ void SceneManager::registerAllScene() {
registerSceneFactory(SceneType::OnlineGameScene, []() -> std::shared_ptr<Scene> { registerSceneFactory(SceneType::OnlineGameScene, []() -> std::shared_ptr<Scene> {
return std::make_shared<OnlineGameScene>(); return std::make_shared<OnlineGameScene>();
}); });
registerSceneFactory(SceneType::BadAppleScene, []() -> std::shared_ptr<Scene> {
return std::make_shared<BadAppleScene>();
});
} }
std::shared_ptr<Scene> SceneManager::createScene(SceneType sceneType) { std::shared_ptr<Scene> SceneManager::createScene(SceneType sceneType) {
@@ -178,6 +181,7 @@ void SceneManager::updateCurrent() {
if (m_coreData.inputState.isBadApplePress) { if (m_coreData.inputState.isBadApplePress) {
m_coreData.inputState.isBadApplePress = false; m_coreData.inputState.isBadApplePress = false;
std::cout << "SceneManager: badapple pressed\n"; std::cout << "SceneManager: badapple pressed\n";
changeScene(SceneType::BadAppleScene);
} }
} }

View File

@@ -10,6 +10,7 @@
#include "scenes/gameplay/GameScene.h" #include "scenes/gameplay/GameScene.h"
#include "scenes/menu/MainMenuScene.h" #include "scenes/menu/MainMenuScene.h"
#include "scenes/gameplay/OnlineGameScene.h" #include "scenes/gameplay/OnlineGameScene.h"
#include "scenes/other/BadAppleScene.h"
#include "core/CoreData.h" #include "core/CoreData.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <string> #include <string>

View File

@@ -0,0 +1,157 @@
#include "BadAppleScene.h"
#include "core/Time.h"
#include <iostream>
static constexpr int ROW = 22;
static constexpr int COL = 30;
static constexpr int FPS = 30;
static constexpr float FrameTime = 1 / static_cast<float>(FPS);
BadAppleScene::BadAppleScene() {
}
BadAppleScene::~BadAppleScene() {
}
void BadAppleScene::onEnter(SDL_Renderer* renderer, int WIDTH, int HEIGHT, UIRenderer* uiRenderer, TextureManager* textureManager, CoreData* coreData) {
m_renderer = renderer;
m_uiRenderer = uiRenderer;
m_coreData = coreData;
m_Width = WIDTH;
m_Height = HEIGHT;
m_cellSize = std::min(WIDTH, HEIGHT) / std::min(ROW, COL);
m_area = {
(m_Width - m_cellSize * COL) / 2,
(m_Height - m_cellSize * ROW) / 2,
m_cellSize,
ROW,
COL
};
m_file.open("assets/BadApple.txt");
if (!m_file.is_open()) {
std::cerr << "BadAppleScene: fail to open BadApple.txt\n";
}
}
void BadAppleScene::update() {
if (m_coreData->inputState.isQ) {
m_coreData->inputState.isQ = false;
m_eventCallback({SceneEventType::ChangeScene, SceneType::MainMenuScene});
}
if (m_coreData->inputState.isR) {
m_coreData->inputState.isR = false;
if (!m_file.is_open()) {
m_file.open("assets/BadApple.txt");
if (!m_file.is_open()) {
std::cerr << "BadAppleScene: fail to open BadApple.txt\n";
return;
}
}
m_file.clear();
m_file.seekg(0);
}
if (!m_file.is_open() || m_file.eof()) {
return;
}
m_currentTime += Time::deltaTime();
if (m_currentTime >= FrameTime) {
m_currentTime = 0;
updateFrame();
}
}
void BadAppleScene::updateFrame() {
if (!readFrame()) {
std::cerr << "BadAppleScene: fail to read frame\n";
return;
}
if (m_file.eof()) {
return;
}
}
bool BadAppleScene::readFrame() {
m_frame.clear();
for (int i = 0; i <= ROW; i++) {
std::string line;
if(!std::getline(m_file, line)) {
if (m_file.eof()) {
std::cout << "BadAppleScene: read all frame successfully\n";
return true;
} else {
std::cerr << "BadAppleScene: unknown error while readiing frame\n";
m_file.close();
return false;
}
}
if (i == 0) {
continue;
}
if (line.length() != COL) {
std::cerr << "BadAppleScene: file is corrupted\n";
m_file.close();
return false;
}
m_frame.push_back(line);
}
return true;
}
void BadAppleScene::renderWorld() {
if (m_frame.empty()) {
return;
}
// 绘制格子
SDL_SetRenderDrawColor(m_renderer, 80, 80, 80, 255); // 浅灰边框
for (int row = 0; row < m_area.rows; ++row) {
for (int col = 0; col < m_area.cols; ++col) {
// 使用 SDL_FRect浮点数
SDL_FRect rect{
static_cast<float>(m_area.x + col * m_area.cellSize),
static_cast<float>(m_area.y + row * m_area.cellSize),
static_cast<float>(m_area.cellSize),
static_cast<float>(m_area.cellSize)
};
// SDL3: RenderFillRect 接受 const SDL_FRect*
SDL_RenderRect(m_renderer, &rect);
}
}
// 绘制棋子
SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, 255); // 纯黑填充
for (int row = 0; row < m_area.rows; ++row) {
for (int col = 0; col < m_area.cols; ++col) {
if (m_frame[row][col] == ' ') {
SDL_FRect rect{
static_cast<float>(m_area.x + col * m_area.cellSize),
static_cast<float>(m_area.y + row * m_area.cellSize),
static_cast<float>(m_area.cellSize),
static_cast<float>(m_area.cellSize)
};
SDL_RenderFillRect(m_renderer, &rect);
}
}
}
}
void BadAppleScene::renderUI() {
}
void BadAppleScene::handleClick(int logicalX, int logicalYY) {
}

View File

@@ -0,0 +1,32 @@
#include "scenes/base/Scene.h"
#include "utils/Config.h"
#include <fstream>
class BadAppleScene : public Scene {
public:
BadAppleScene();
~BadAppleScene();
void onEnter(SDL_Renderer* renderer, int WIDTH, int HEIGHT, UIRenderer* uiRenderer, TextureManager* textureManager, CoreData* coreData) override;
void handleClick(int logicalX, int logicalYY) override;
void update() override;
void renderWorld() override; // 逻辑世界
void renderUI() override; // 屏幕 UI
private:
int m_Width;
int m_Height;
int m_cellSize;
BoardArea m_area;
std::ifstream m_file;
float m_currentTime = 0.0f;
std::vector<std::string> m_frame;
void updateFrame();
bool readFrame();
};