latest state

This commit is contained in:
2025-12-06 09:43:33 +01:00
parent 294e935344
commit b44de25113
19 changed files with 2451 additions and 524 deletions

View File

@ -311,189 +311,7 @@ static void resetLevelBackgrounds(LevelBackgroundFader& fader) {
// ...existing code...
// -----------------------------------------------------------------------------
// Enhanced Button Drawing
// -----------------------------------------------------------------------------
static void drawEnhancedButton(SDL_Renderer* renderer, FontAtlas& font, float cx, float cy, float w, float h,
const std::string& label, bool isHovered, bool isSelected = false) {
SDL_Color bgColor = isHovered ? SDL_Color{120, 150, 240, 255} : SDL_Color{80, 110, 200, 255};
if (isSelected) bgColor = {160, 190, 255, 255};
float x = cx - w/2;
float y = cy - h/2;
// Draw button background with border
drawRect(renderer, x-2, y-2, w+4, h+4, {60, 80, 140, 255}); // Border
drawRect(renderer, x, y, w, h, bgColor); // Background
// Draw button text centered
float textScale = 1.5f;
float textX = x + (w - label.length() * 12 * textScale) / 2;
float textY = y + (h - 20 * textScale) / 2;
font.draw(renderer, textX, textY, label, textScale, {255, 255, 255, 255});
}
// External wrapper for enhanced button so other translation units can call it.
void menu_drawEnhancedButton(SDL_Renderer* renderer, FontAtlas& font, float cx, float cy, float w, float h,
const std::string& label, bool isHovered, bool isSelected) {
drawEnhancedButton(renderer, font, cx, cy, w, h, label, isHovered, isSelected);
}
// Popup wrappers
// Forward declarations for popup functions defined later in this file
static void drawSettingsPopup(SDL_Renderer* renderer, FontAtlas& font, bool musicEnabled);
void menu_drawSettingsPopup(SDL_Renderer* renderer, FontAtlas& font, bool musicEnabled) {
drawSettingsPopup(renderer, font, musicEnabled);
}
// Simple rounded menu button drawer used by MenuState (keeps visual parity with JS)
void menu_drawMenuButton(SDL_Renderer* renderer, FontAtlas& font, float cx, float cy, float w, float h,
const std::string& label, SDL_Color bgColor, SDL_Color borderColor) {
float x = cx - w/2;
float y = cy - h/2;
drawRect(renderer, x-6, y-6, w+12, h+12, borderColor);
drawRect(renderer, x-4, y-4, w+8, h+8, {255,255,255,255});
drawRect(renderer, x, y, w, h, bgColor);
float textScale = 1.6f;
float approxCharW = 12.0f * textScale;
float textW = label.length() * approxCharW;
float tx = x + (w - textW) / 2.0f;
float ty = y + (h - 20.0f * textScale) / 2.0f;
font.draw(renderer, tx+2, ty+2, label, textScale, {0,0,0,180});
font.draw(renderer, tx, ty, label, textScale, {255,255,255,255});
}
// -----------------------------------------------------------------------------
// Block Drawing Functions
// -----------------------------------------------------------------------------
static void drawBlockTexture(SDL_Renderer* renderer, SDL_Texture* blocksTex, float x, float y, float size, int blockType) {
if (!blocksTex || blockType < 0 || blockType >= PIECE_COUNT) {
// Debug: print why we're falling back
if (!blocksTex) {
static bool printed = false;
if (!printed) {
(void)0;
printed = true;
}
}
// Fallback to colored rectangle if texture isn't available
SDL_Color color = (blockType >= 0 && blockType < PIECE_COUNT) ? COLORS[blockType + 1] : SDL_Color{128, 128, 128, 255};
drawRect(renderer, x, y, size-1, size-1, color);
return;
}
// JavaScript uses: sx = type * spriteSize, sy = 0, with 2px padding
// Each sprite is 90px wide in the horizontal sprite sheet
const int SPRITE_SIZE = 90;
float srcX = blockType * SPRITE_SIZE + 2; // Add 2px padding like JS
float srcY = 2; // Add 2px padding from top like JS
float srcW = SPRITE_SIZE - 4; // Subtract 4px total padding like JS
float srcH = SPRITE_SIZE - 4; // Subtract 4px total padding like JS
SDL_FRect srcRect = {srcX, srcY, srcW, srcH};
SDL_FRect dstRect = {x, y, size, size};
SDL_RenderTexture(renderer, blocksTex, &srcRect, &dstRect);
}
static void drawPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, const Game::Piece& piece, float ox, float oy, float tileSize, bool isGhost = false) {
if (piece.type >= PIECE_COUNT) return;
for (int cy = 0; cy < 4; ++cy) {
for (int cx = 0; cx < 4; ++cx) {
if (Game::cellFilled(piece, cx, cy)) {
float px = ox + (piece.x + cx) * tileSize;
float py = oy + (piece.y + cy) * tileSize;
if (isGhost) {
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
// Draw ghost piece as barely visible gray outline
SDL_SetRenderDrawColor(renderer, 180, 180, 180, 20); // Very faint gray
SDL_FRect rect = {px + 2, py + 2, tileSize - 4, tileSize - 4};
SDL_RenderFillRect(renderer, &rect);
// Draw thin gray border
SDL_SetRenderDrawColor(renderer, 180, 180, 180, 30);
SDL_FRect border = {px + 1, py + 1, tileSize - 2, tileSize - 2};
SDL_RenderRect(renderer, &border);
} else {
drawBlockTexture(renderer, blocksTex, px, py, tileSize, piece.type);
}
}
}
}
}
static void drawSmallPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, PieceType pieceType, float x, float y, float tileSize) {
if (pieceType >= PIECE_COUNT) return;
// Use the first rotation (index 0) for preview
Game::Piece previewPiece;
previewPiece.type = pieceType;
previewPiece.rot = 0;
previewPiece.x = 0;
previewPiece.y = 0;
// Center the piece in the preview area
float offsetX = 0, offsetY = 0;
if (pieceType == I) { offsetX = tileSize * 0.5f; } // I-piece centering
else if (pieceType == O) { offsetX = tileSize * 0.5f; } // O-piece centering
// Use semi-transparent alpha for preview blocks
Uint8 previewAlpha = 180; // Change this value for more/less transparency
SDL_SetTextureAlphaMod(blocksTex, previewAlpha);
for (int cy = 0; cy < 4; ++cy) {
for (int cx = 0; cx < 4; ++cx) {
if (Game::cellFilled(previewPiece, cx, cy)) {
float px = x + offsetX + cx * tileSize;
float py = y + offsetY + cy * tileSize;
drawBlockTexture(renderer, blocksTex, px, py, tileSize, pieceType);
}
}
}
SDL_SetTextureAlphaMod(blocksTex, 255); // Reset alpha after drawing
}
// -----------------------------------------------------------------------------
// Popup Drawing Functions
// -----------------------------------------------------------------------------
static void drawSettingsPopup(SDL_Renderer* renderer, FontAtlas& font, bool musicEnabled) {
float popupW = 350, popupH = 260;
float popupX = (LOGICAL_W - popupW) / 2;
float popupY = (LOGICAL_H - popupH) / 2;
// Semi-transparent overlay
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 128);
SDL_FRect overlay{0, 0, LOGICAL_W, LOGICAL_H};
SDL_RenderFillRect(renderer, &overlay);
// Popup background
drawRect(renderer, popupX-4, popupY-4, popupW+8, popupH+8, {100, 120, 160, 255}); // Border
drawRect(renderer, popupX, popupY, popupW, popupH, {40, 50, 70, 255}); // Background
// Title
font.draw(renderer, popupX + 20, popupY + 20, "SETTINGS", 2.0f, {255, 220, 0, 255});
// Music toggle
font.draw(renderer, popupX + 20, popupY + 70, "MUSIC:", 1.5f, {255, 255, 255, 255});
const char* musicStatus = musicEnabled ? "ON" : "OFF";
SDL_Color musicColor = musicEnabled ? SDL_Color{0, 255, 0, 255} : SDL_Color{255, 0, 0, 255};
font.draw(renderer, popupX + 120, popupY + 70, musicStatus, 1.5f, musicColor);
// Sound effects toggle
font.draw(renderer, popupX + 20, popupY + 100, "SOUND FX:", 1.5f, {255, 255, 255, 255});
const char* soundStatus = SoundEffectManager::instance().isEnabled() ? "ON" : "OFF";
SDL_Color soundColor = SoundEffectManager::instance().isEnabled() ? SDL_Color{0, 255, 0, 255} : SDL_Color{255, 0, 0, 255};
font.draw(renderer, popupX + 140, popupY + 100, soundStatus, 1.5f, soundColor);
// Instructions
font.draw(renderer, popupX + 20, popupY + 150, "M = TOGGLE MUSIC", 1.0f, {200, 200, 220, 255});
font.draw(renderer, popupX + 20, popupY + 170, "S = TOGGLE SOUND FX", 1.0f, {200, 200, 220, 255});
font.draw(renderer, popupX + 20, popupY + 190, "ESC = CLOSE", 1.0f, {200, 200, 220, 255});
}
// Legacy rendering functions removed (moved to UIRenderer / GameRenderer)
// -----------------------------------------------------------------------------
@ -521,7 +339,9 @@ static bool helpOverlayPausedGame = false;
// -----------------------------------------------------------------------------
// Tetris Block Fireworks for intro animation (block particles)
// Forward declare block render helper used by particles
static void drawBlockTexture(SDL_Renderer* renderer, SDL_Texture* blocksTex, float x, float y, float size, int blockType);
// Forward declare block render helper used by particles
// (Note: drawBlockTexture implementation was removed, so this is likely dead code unless particles use it.
// However, particles use drawFireworks_impl which uses SDL_RenderGeometry, so this is unused.)
// -----------------------------------------------------------------------------
struct BlockParticle {
float x{}, y{};
@ -791,11 +611,11 @@ int main(int, char **)
lineEffect.init(renderer);
// Load logo assets via SDL_image so we can use compressed formats
SDL_Texture* logoTex = loadTextureFromImage(renderer, "assets/images/logo.bmp");
SDL_Texture* logoTex = loadTextureFromImage(renderer, "assets/images/spacetris.png");
// Load small logo (used by Menu to show whole logo)
int logoSmallW = 0, logoSmallH = 0;
SDL_Texture* logoSmallTex = loadTextureFromImage(renderer, "assets/images/logo_small.bmp", &logoSmallW, &logoSmallH);
SDL_Texture* logoSmallTex = loadTextureFromImage(renderer, "assets/images/spacetris.png", &logoSmallW, &logoSmallH);
// Load menu background using SDL_image (prefers JPEG)
SDL_Texture* backgroundTex = loadTextureFromImage(renderer, "assets/images/main_background.bmp");