// // Created by bruno on 11.6.2025. // #include "button.h" #include "gamestate.h" void onStart() { genInitMap(); screenType = SCREEN_GAME; } void onContinue() { if (loadGameState(autosaveName, &mainPlayer)) { genInitMap(); } screenType = SCREEN_GAME; } void onCredits() { screenType = SCREEN_CREDITS; } void onNext() { if (!waveInfo.waveRunning && waveInfo.waveTimer > 60 * 5) { waveInfo.waveTimer = 60 * 5; } } void onQuit() { running = false; } void onBack() { screenType = SCREEN_MENU; } void onAtlas() { screenType = SCREEN_ATLAS; } void onFont() { screenType = SCREEN_FONTS; } Button buttons[5][BUTTON_COUNT]; void initButtons(void) { buttons[0][0] = (Button){ .label = "New", .rect = {110, DISPLAY_HEIGHT / 2, 125, 40}, .color = {100, 100, 0, 255}, .callback = onStart, .font = &fonts[1] }; buttons[0][1] = (Button){ .label = "Continue", .rect = {100, DISPLAY_HEIGHT / 2 + 45, 150, 40}, .color = {0, 100, 0, 255}, .callback = onContinue, .font = &fonts[1] }; buttons[0][2] = (Button){ .label = "Credits", .rect = {DISPLAY_WIDTH - 200, DISPLAY_HEIGHT - 120, 150, 40}, .color = {0, 50, 50, 255}, .callback = onCredits, .font = &fonts[1] }; buttons[0][3] = (Button){ .label = "Exit", .rect = {DISPLAY_WIDTH - 200, DISPLAY_HEIGHT - 40, 100, 40}, .color = {100, 0, 0, 255}, .callback = onQuit, .font = &fonts[1] }; buttons[1][0] = (Button){ .label = "Back", .rect = {DISPLAY_WIDTH / 2 - (100 / 2), DISPLAY_HEIGHT - 40, 100, 40}, .color = {100, 0, 0, 255}, .callback = onBack, .font = &fonts[1] }; buttons[1][1] = (Button){ .label = "Font atlas", .rect = {DISPLAY_WIDTH - 900, DISPLAY_HEIGHT - 40, 200, 40}, .color = {100, 0, 0, 255}, .callback = onFont, .font = &fonts[1] }; buttons[1][2] = (Button){ .label = "Texture atlas", .rect = {DISPLAY_WIDTH - 300, DISPLAY_HEIGHT - 40, 250, 40}, .color = {100, 0, 0, 255}, .callback = onAtlas, .font = &fonts[1] }; buttons[2][0] = (Button){ .label = "Next", .rect = {395, 0, 55, 80}, .color = {64, 64, 64, 64}, .callback = onNext, .font = &fonts[2] }; buttons[3][0] = (Button){ .label = "Back", .rect = {DISPLAY_WIDTH / 2 - (400 / 2), DISPLAY_HEIGHT - 40, 100, 40}, .color = {100, 0, 0, 255}, .callback = onCredits, .font = &fonts[1] }; buttons[4][0] = (Button){ .label = "Back", .rect = {DISPLAY_WIDTH / 2 - (400 / 2), DISPLAY_HEIGHT - 40, 100, 40}, .color = {100, 0, 0, 255}, .callback = onCredits, .font = &fonts[1] }; } void renderButtons(SDL_Renderer *renderer, Player player) { for (int i = 0; i < BUTTON_COUNT; i++) { renderButton(renderer, buttons[screenType][i], player); } } void renderButton(SDL_Renderer *renderer, Button btn, Player player) { if (btn.font == NULL || btn.label == NULL || strlen(btn.label) == 0) { return; } // Check for hover/click bool hovered = (player.cursor.windowX >= btn.rect.x && player.cursor.windowX <= btn.rect.x + btn.rect.w && player.cursor.windowY >= btn.rect.y && player.cursor.windowY <= btn.rect.y + btn.rect.h); // Set color and draw background SDL_Color bgColor = btn.color; if (hovered) { bgColor.a = btn.color.a / 2; } SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, bgColor.a); SDL_RenderFillRect(renderer, &btn.rect); // Split label into lines const char *label = btn.label; const int maxLines = 10; // Hard cap for sanity const char *lines[maxLines]; int lineCount = 0; lines[lineCount++] = label; for (const char *p = label; *p && lineCount < maxLines; p++) { if (*p == '\n') { lines[lineCount++] = p + 1; } } // Get length of each line and find max width (for centering) int maxLineWidth = 0; int lineWidths[maxLines]; int fontSize = btn.font->size; for (int i = 0; i < lineCount; i++) { const char *lineStart = lines[i]; const char *lineEnd = strchr(lineStart, '\n'); int lineLen = lineEnd ? (lineEnd - lineStart) : strlen(lineStart); int lineWidth = lineLen * fontSize; lineWidths[i] = lineWidth; if (lineWidth > maxLineWidth) { maxLineWidth = lineWidth; } } // Calculate starting Y to vertically center all lines int totalHeight = lineCount * fontSize; int startY = btn.rect.y + (btn.rect.h - totalHeight) / 2; // Render each line centered horizontally for (int i = 0; i < lineCount; i++) { const char *lineStart = lines[i]; const char *lineEnd = strchr(lineStart, '\n'); int lineLen = lineEnd ? (lineEnd - lineStart) : strlen(lineStart); char buffer[256]; strncpy(buffer, lineStart, lineLen); buffer[lineLen] = '\0'; int x = btn.rect.x + (btn.rect.w - lineWidths[i]) / 2; int y = startY + i * fontSize; renderText(renderer, *btn.font, buffer, x, y); } // Trigger callback if clicked if (hovered && (player.mouseButtons & SDL_BUTTON_LMASK)) { if (btn.callback) { btn.callback(); } } }