Updated game structure
Some checks failed
Build and Package Tetris / build-windows (push) Has been cancelled
Build and Package Tetris / build-linux (push) Has been cancelled

This commit is contained in:
2025-08-16 12:10:19 +02:00
parent 71648fbaeb
commit 2afaea7fd3
36 changed files with 665 additions and 382 deletions

View File

@ -14,19 +14,20 @@
#include <cstdlib>
#include <memory>
#include "Audio.h"
#include "SoundEffect.h"
#include "audio/Audio.h"
#include "audio/SoundEffect.h"
#include "Game.h"
#include "Scores.h"
#include "Starfield.h"
#include "gameplay/Game.h"
#include "persistence/Scores.h"
#include "graphics/Starfield.h"
#include "Starfield3D.h"
#include "Font.h"
#include "LineEffect.h"
#include "graphics/Font.h"
#include "gameplay/LineEffect.h"
#include "states/State.h"
#include "states/LoadingState.h"
#include "states/MenuState.h"
#include "states/PlayingState.h"
#include "audio/MenuWrappers.h"
// Debug logging removed: no-op in this build (previously LOG_DEBUG)
@ -331,7 +332,7 @@ static void drawSettingsPopup(SDL_Renderer* renderer, FontAtlas& font, bool musi
// Starfield now managed by Starfield class
// State manager integration (scaffolded in StateManager.h)
#include "StateManager.h"
#include "core/StateManager.h"
// -----------------------------------------------------------------------------
// Intro/Menu state variables
@ -341,8 +342,6 @@ static bool showLevelPopup = false;
static bool showSettingsPopup = false;
static bool musicEnabled = true;
static int hoveredButton = -1; // -1 = none, 0 = play, 1 = level, 2 = settings
// Shared texture for fireworks particles (uses the blocks sheet)
static SDL_Texture* fireworksBlocksTex = nullptr;
// -----------------------------------------------------------------------------
// Tetris Block Fireworks for intro animation (block particles)
@ -389,44 +388,7 @@ struct TetrisFirework {
}
return !particles.empty();
}
void draw(SDL_Renderer* renderer) {
for (auto &p : particles) {
if (fireworksBlocksTex) {
// Apply per-particle alpha and color variants by modulating the blocks texture
// Save previous mods (assume single-threaded rendering)
Uint8 prevA = 255;
SDL_GetTextureAlphaMod(fireworksBlocksTex, &prevA);
Uint8 setA = Uint8(std::max(0.0f, std::min(1.0f, p.alpha)) * 255.0f);
SDL_SetTextureAlphaMod(fireworksBlocksTex, setA);
// Color modes: tint the texture where appropriate
if (mode == 1) {
// red
SDL_SetTextureColorMod(fireworksBlocksTex, 220, 60, 60);
} else if (mode == 2) {
// green
SDL_SetTextureColorMod(fireworksBlocksTex, 80, 200, 80);
} else if (mode == 3) {
// tint to the particle's block color
SDL_Color c = COLORS[p.blockType + 1];
SDL_SetTextureColorMod(fireworksBlocksTex, c.r, c.g, c.b);
} else {
// random: no tint (use texture colors directly)
SDL_SetTextureColorMod(fireworksBlocksTex, 255, 255, 255);
}
drawBlockTexture(renderer, fireworksBlocksTex, p.x - p.size * 0.5f, p.y - p.size * 0.5f, p.size, p.blockType);
// Restore alpha and color modulation
SDL_SetTextureAlphaMod(fireworksBlocksTex, prevA);
SDL_SetTextureColorMod(fireworksBlocksTex, 255, 255, 255);
} else {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, Uint8(p.alpha * 255));
SDL_FRect rect{p.x - p.size/2, p.y - p.size/2, p.size, p.size};
SDL_RenderFillRect(renderer, &rect);
}
}
}
// Drawing is handled by drawFireworks_impl which accepts the texture to use.
};
static std::vector<TetrisFirework> fireworks;
@ -455,13 +417,41 @@ static void updateFireworks(double frameMs) {
}
}
static void drawFireworks(SDL_Renderer* renderer) {
for (auto& f : fireworks) f.draw(renderer);
// Primary implementation that accepts a texture pointer
static void drawFireworks_impl(SDL_Renderer* renderer, SDL_Texture* blocksTexture) {
for (auto& f : fireworks) {
// Particle draw uses the texture pointer passed into drawBlockTexture calls from f.draw
// We'll set a thread-local-ish variable by passing the texture as an argument to draw
// routines or using the provided texture in the particle's draw path.
// For simplicity, the particle draw function below will reference a global symbol
// via an argument — we adapt by providing the texture when calling drawBlockTexture.
// Implementation: call a small lambda that temporarily binds the texture for drawBlockTexture.
struct Drawer { SDL_Renderer* r; SDL_Texture* tex; void drawParticle(struct BlockParticle& p) {
if (tex) {
Uint8 prevA = 255;
SDL_GetTextureAlphaMod(tex, &prevA);
Uint8 setA = Uint8(std::max(0.0f, std::min(1.0f, p.alpha)) * 255.0f);
SDL_SetTextureAlphaMod(tex, setA);
// Note: color modulation will be applied by callers of drawBlockTexture where needed
// but we mimic behavior from previous implementation by leaving color mod as default.
drawBlockTexture(r, tex, p.x - p.size * 0.5f, p.y - p.size * 0.5f, p.size, p.blockType);
SDL_SetTextureAlphaMod(tex, prevA);
SDL_SetTextureColorMod(tex, 255, 255, 255);
} else {
SDL_SetRenderDrawColor(r, 255, 255, 255, Uint8(p.alpha * 255));
SDL_FRect rect{p.x - p.size/2, p.y - p.size/2, p.size, p.size};
SDL_RenderFillRect(r, &rect);
}
}
} drawer{renderer, blocksTexture};
for (auto &p : f.particles) {
drawer.drawParticle(p);
}
}
}
// External wrappers for use by other translation units (MenuState)
// These call the internal helpers above so we don't change existing static linkage.
void menu_drawFireworks(SDL_Renderer* renderer) { drawFireworks(renderer); }
// Expect callers to pass the blocks texture via StateContext so we avoid globals.
void menu_drawFireworks(SDL_Renderer* renderer, SDL_Texture* blocksTex) { drawFireworks_impl(renderer, blocksTex); }
void menu_updateFireworks(double frameMs) { updateFireworks(frameMs); }
double menu_getLogoAnimCounter() { return logoAnimCounter; }
int menu_getHoveredButton() { return hoveredButton; }
@ -474,20 +464,20 @@ int main(int, char **)
int sdlInitRes = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
if (sdlInitRes < 0)
{
std::fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Init failed: %s", SDL_GetError());
return 1;
}
int ttfInitRes = TTF_Init();
if (ttfInitRes < 0)
{
std::fprintf(stderr, "TTF_Init failed\n");
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "TTF_Init failed");
SDL_Quit();
return 1;
}
SDL_Window *window = SDL_CreateWindow("Tetris (SDL3)", LOGICAL_W, LOGICAL_H, SDL_WINDOW_RESIZABLE);
if (!window)
{
std::fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateWindow failed: %s", SDL_GetError());
TTF_Quit();
SDL_Quit();
return 1;
@ -495,7 +485,7 @@ int main(int, char **)
SDL_Renderer *renderer = SDL_CreateRenderer(window, nullptr);
if (!renderer)
{
std::fprintf(stderr, "SDL_CreateRenderer failed: %s\n", SDL_GetError());
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateRenderer failed: %s", SDL_GetError());
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
@ -556,6 +546,9 @@ int main(int, char **)
} else {
(void)0;
}
// Note: `backgroundTex` is owned by main and passed into `StateContext::backgroundTex` below.
// States should render using `ctx.backgroundTex` rather than accessing globals.
// Level background caching system
SDL_Texture *levelBackgroundTex = nullptr;
@ -575,6 +568,7 @@ int main(int, char **)
} else {
(void)0;
}
// No global exposure of blocksTex; states receive textures via StateContext.
if (!blocksTex) {
(void)0;
@ -613,8 +607,7 @@ int main(int, char **)
(void)0;
}
// Provide the blocks sheet to the fireworks system (for block particles)
fireworksBlocksTex = blocksTex;
// Provide the blocks sheet to the fireworks system through StateContext (no globals).
// Default start level selection: 0
int startLevelSelection = 0;
@ -656,7 +649,7 @@ int main(int, char **)
}
}
std::fprintf(stderr, "Failed to load sound: %s (tried both WAV and MP3)\n", id.c_str());
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to load sound: %s (tried both WAV and MP3)", id.c_str());
};
loadSoundWithFallback("nice_combo", "nice_combo");