diff --git a/.gitignore b/.gitignore index 2004c3c..6b19a9b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ sdlmine/config.h.in~ imgui/.deps/ imgui/.dirstamp + +spidersol/configure~ diff --git a/sdlmine/minesweeper.cpp b/sdlmine/minesweeper.cpp index 662c555..733b371 100644 --- a/sdlmine/minesweeper.cpp +++ b/sdlmine/minesweeper.cpp @@ -51,7 +51,7 @@ int may_restart = 0, game_over = 0, game_start, counter2 = 0; int timer_started = 0, mouth_idx = 0; -ImGuiIO io; +ImGuiIO * io; #ifdef EMSCRIPTEN #include @@ -94,7 +94,7 @@ void game_loop(void) { running = false; break; case SDL_MOUSEBUTTONDOWN: - if (io.WantCaptureMouse) break; + if (io->WantCaptureMouse) break; if (event.button.button == SDL_BUTTON_LEFT) { // If within the bounds of the face SDL_Rect rect; @@ -115,7 +115,7 @@ void game_loop(void) { } break; case SDL_MOUSEBUTTONUP: - if (io.WantCaptureMouse) break; + if (io->WantCaptureMouse) break; if (event.button.button == SDL_BUTTON_LEFT) { // If within the bounds of the face SDL_Rect rect; @@ -397,10 +397,10 @@ int main(void) { IMGUI_CHECKVERSION(); ImGui::CreateContext(); - io = ImGui::GetIO(); - (void)io; - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - io.IniFilename = NULL; + io = &ImGui::GetIO(); + io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io->IniFilename = NULL; + io->LogFilename = NULL; ImGui::StyleColorsClassic(); diff --git a/sdlreversi/reversi.cpp b/sdlreversi/reversi.cpp index 3898e12..9f15baa 100644 --- a/sdlreversi/reversi.cpp +++ b/sdlreversi/reversi.cpp @@ -264,7 +264,7 @@ Uint32 animate(Uint32 interval, void * param) { SDL_Window * window; SDL_Renderer * renderer; -ImGuiIO io; +ImGuiIO * io; char difficulty; bool done = false; @@ -277,7 +277,7 @@ void game_loop() { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_MOUSEBUTTONUP: - if (io.WantCaptureMouse) break; + if (io->WantCaptureMouse) break; if (event.button.button == SDL_BUTTON_LEFT) { int mx = event.button.x; int my = event.button.y; @@ -500,10 +500,10 @@ int main() { IMGUI_CHECKVERSION(); ImGui::CreateContext(); - io = ImGui::GetIO(); - (void)io; - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - io.IniFilename = NULL; + io = &ImGui::GetIO(); + io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io->IniFilename = NULL; + io->LogFilename = NULL; ImGui::StyleColorsClassic(); diff --git a/spidersol/Makefile.am b/spidersol/Makefile.am index 2f442d6..0fe9647 100644 --- a/spidersol/Makefile.am +++ b/spidersol/Makefile.am @@ -2,5 +2,5 @@ AM_CXXFLAGS = $(SDL_CFLAGS) $(SDL_ttf_CFLAGS) AM_CFLAGS = $(SDL_CFLAGS) $(SDL_ttf_CFLAGS) bin_PROGRAMS = spidersol -spidersol_SOURCES = cntrl.c engine.c infobox.c settings.c ui.c win.c deal.c game_state.c leaderboard.c spidersol.c undo.c +spidersol_SOURCES = cntrl.c engine.c infobox.c ui.c win.c deal.c game_state.c spidersol.cpp undo.c ../imgui/imgui.cpp ../imgui/imgui_impl_sdl2.cpp ../imgui/imgui_tables.cpp ../imgui/imgui_draw.cpp ../imgui/imgui_impl_sdlrenderer2.cpp ../imgui/imgui_widgets.cpp spidersol_LDADD = $(SDL_LIBS) $(SDL_ttf_LIBS) \ No newline at end of file diff --git a/spidersol/configure.ac b/spidersol/configure.ac index 351555d..25c6d19 100644 --- a/spidersol/configure.ac +++ b/spidersol/configure.ac @@ -1,12 +1,12 @@ AC_PREREQ([2.71]) AC_INIT([spidersol], [1.0], [kspalaiologos@gmail.com]) -AC_CONFIG_SRCDIR([spidersol.c]) +AC_CONFIG_SRCDIR([spidersol.cpp]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([build-aux]) AC_COPYRIGHT([Copyright (C) 2023 Kamila Szewczyk; licensed under the terms of the GNU GPLv3 license.]) -AM_INIT_AUTOMAKE([foreign]) +AM_INIT_AUTOMAKE([foreign subdir-objects]) # Checks for programs. AC_PROG_CXX diff --git a/spidersol/engine.c b/spidersol/engine.c index df0a1ae..d459da4 100644 --- a/spidersol/engine.c +++ b/spidersol/engine.c @@ -34,87 +34,6 @@ int has_moves() { if (game.remainingExtraDeals > 0) return 1; - for (int i = 0; i < 10; i++) { - if (game.stacks[i].num_cards == 0) return 1; - } - - // Compute the offsets in each stack that give a consecutive column slice. - int offsets[10]; - compute_offsets(offsets); - - // Check if there are any moves possible that won't just end up in a loop. - // E.g., if we move a 2 to a 3, but the 2 was previously on a 3, this makes no sense unless an entire stack is - // getting folded. - - // In other words: Move only full stacks as defined from offsets[i] to stacks[i].num_cards, UNLESS the last card is - // an Ace and this operation will result in a full stack from king, queen, jack, etc... until an ace. - - // Start with the easy case first: Check if any _full_ stack can be moved anywhere. - - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - if (i == j || offsets[i] == -1) continue; - - // Can be moved! - if (game.stacks[i].cards[offsets[i]].value + 1 == - game.stacks[j].cards[game.stacks[j].num_cards - 1].value && - game.stacks[i].cards[offsets[i]].suit == game.stacks[j].cards[game.stacks[j].num_cards - 1].suit) - return 1; - } - } - - // The difficult case: - // Mask out the stacks that start with a king and the stacks that end with an ace. - - int ends[10], begins[10]; - int ec[10], bc[10]; - - for (int i = 0; i < 10; i++) { - ends[i] = -1; - begins[i] = -1; - ec[i] = -1; - bc[i] = -1; - } - - for (int i = 0; i < 10; i++) { - if (game.stacks[i].num_cards == 0 || offsets[i] == -1) continue; - - if (game.stacks[i].cards[offsets[i]].value == 0) { - ends[i] = game.stacks[i].cards[game.stacks[i].num_cards - 1].value; - ec[i] = game.stacks[i].cards[game.stacks[i].num_cards - 1].suit; - } - - if (game.stacks[i].cards[game.stacks[i].num_cards - 1].value == 12) { - begins[i] = game.stacks[i].cards[offsets[i]].value; - bc[i] = game.stacks[i].cards[offsets[i]].suit; - } - } - - // Determine if there is such ends[i] and begins[j] that ends[i] <= begins[j] - // and i != j. If so, return 1. - - for (int i = 0; i < 10; i++) { - if (ends[i] == -1) continue; - - for (int j = 0; j < 10; j++) { - // stack begins with begins[j] and ends with Ace. - // stack starts with King and ends with ends[i]. - // meaning that we're seeking for overlap in these two stacks. - - // assume we have a run from K to 6 and from 8 to A. - // begins = 8, ends = 6, but it's reverse so ends > begins. - - if (begins[j] == -1) continue; - - if (i == j) continue; - - if (ec[i] == bc[j] && begins[j] <= ends[i]) { - return 1; - } - } - } - - // Assume no legal moves. - - return 0; + // TODO. + return 1; } diff --git a/spidersol/game_state.c b/spidersol/game_state.c index 619dcf0..3059dd2 100644 --- a/spidersol/game_state.c +++ b/spidersol/game_state.c @@ -1,15 +1,14 @@ #include "game_state.h" -#include "leaderboard.h" #include "undo.h" +#include + static char * fs_name() { return "solitaire.dat"; } static void fs_flush_data(FILE * f) { fflush(f); } -#include - struct game_data game = { .remainingExtraDeals = 5, .timeDelta = -1, .selected_card_back = 9, @@ -38,8 +37,8 @@ void reset_game() { } void new_game() { + game.lastseed = time(NULL); reset_game(); - srand(game.lastseed = time(NULL)); } void load_storage() { @@ -51,14 +50,6 @@ void load_storage() { return; } - // Leaderboard entries. - for (int i = 0; i < 10; i++) { - fscanf(f, "%d %d %d %d\n", &game.leaderboard[i].score, &game.leaderboard[i].moves, &game.leaderboard[i].time, - &game.leaderboard[i].when); - } - - onLeaderboardUpdate(); - fscanf(f, "%d %d \n", &game.selected_card_back, &game.difficulty); for (int i = 0; i < 8; i++) { fscanf(f, "%d ", &game.wonKings[i]); @@ -99,20 +90,14 @@ void save_storage() { return; } - // Leaderboard entries: - for (int i = 0; i < 10; i++) { - fprintf(f, "%d %d %d %d\n", game.leaderboard[i].score, game.leaderboard[i].moves, game.leaderboard[i].time, - game.leaderboard[i].when); - } - fprintf(f, "%d %d \n", game.selected_card_back, game.difficulty); for (int i = 0; i < 8; i++) { fprintf(f, "%d ", game.wonKings[i]); } fprintf(f, "\n"); - // Synchronise the game state only if we're in the IDLE, LEADERBOARD or SETTINGS state. - if (game.state == STATE_GAME_IDLE || game.state == STATE_GAME_SETTINGS || game.state == STATE_GAME_LEADERBOARD) { + // Synchronise the game state only if we're in the IDLE state. + if (game.state == STATE_GAME_IDLE) { fprintf(f, "1\n"); fprintf(f, "%d %d %d %d %d \n", game.points, game.time, game.moves, game.prevdiff, game.remainingExtraDeals); for (int i = 0; i < 5; i++) { diff --git a/spidersol/game_state.h b/spidersol/game_state.h index 64dce6b..3b2caac 100644 --- a/spidersol/game_state.h +++ b/spidersol/game_state.h @@ -11,9 +11,7 @@ enum { STATE_GAME_DEAL, STATE_GAME_DRAGGING_STACK, STATE_GAME_DEALING_ROW, - STATE_GAME_SETTINGS, STATE_GAME_FIREWORKS, - STATE_GAME_LEADERBOARD, STATE_GAME_LOST }; @@ -40,13 +38,6 @@ struct historical_state { int remainingExtraDeals; }; -struct leaderboard_entry { - int score; - int moves; - int time; - time_t when; -}; - struct game_data { int remainingExtraDeals; struct card extracards[5][10]; @@ -68,8 +59,6 @@ struct game_data { int needsTextRepaint; int counts[4][13]; - - struct leaderboard_entry leaderboard[10]; }; extern struct game_data game; diff --git a/spidersol/leaderboard.c b/spidersol/leaderboard.c deleted file mode 100644 index 570f650..0000000 --- a/spidersol/leaderboard.c +++ /dev/null @@ -1,148 +0,0 @@ - -#include "leaderboard.h" - -#include "game_state.h" -#include "ui.h" - -void leaderboardHandleMouseUp(int x, int y) { - // Check if we clicked outside of the settings window. - if (x <= LEADERBOARD_WND_OFFSET_X || x >= LEADERBOARD_WND_OFFSET_X + LEADERBOARD_WND_WIDTH || - y <= LEADERBOARD_WND_OFFSET_Y || y >= LEADERBOARD_WND_OFFSET_Y + LEADERBOARD_WND_HEIGHT) { - game.state = STATE_GAME_IDLE; - return; - } -} - -struct text_row { - SDL_Texture * no; - SDL_Texture * points; - SDL_Texture * moves; - SDL_Texture * time; - SDL_Texture * date; -}; - -static struct text_row leaderboard_data[11]; - -#define registerEntry(msg, dest) \ - surface = TTF_RenderText_Blended(font, msg, black); \ - leaderboard_data[i].dest = SDL_CreateTextureFromSurface(renderer, surface); \ - SDL_FreeSurface(surface); - -void onLeaderboardUpdate() { - SDL_Color black = { 0, 0, 0, 255 }; - int i; - for (i = 0; i < 11; i++) { - if (leaderboard_data[i].points) SDL_DestroyTexture(leaderboard_data[i].points); - if (leaderboard_data[i].moves) SDL_DestroyTexture(leaderboard_data[i].moves); - if (leaderboard_data[i].time) SDL_DestroyTexture(leaderboard_data[i].time); - if (leaderboard_data[i].date) SDL_DestroyTexture(leaderboard_data[i].date); - - char buf[32]; - SDL_Surface * surface; - - if (i > 0 && game.leaderboard[i - 1].score == 0) { - // Empty score. - sprintf(buf, "%d", i); - registerEntry(buf, no); - registerEntry("--", points); - registerEntry("--", moves); - registerEntry("--", time); - registerEntry("--", date); - } else if (i == 0) { - // Header. - registerEntry("No.", no); - registerEntry("Score", points); - registerEntry("Moves", moves); - registerEntry("Time", time); - registerEntry("Date", date); - } else { - // Score. - sprintf(buf, "%d", i); - registerEntry(buf, no); - sprintf(buf, "%d", game.leaderboard[i - 1].score); - registerEntry(buf, points); - sprintf(buf, "%d", game.leaderboard[i - 1].moves); - registerEntry(buf, moves); - int time = game.leaderboard[i - 1].time; - int minutes = time / 60; - int seconds = time % 60; - sprintf(buf, "%d:%02d", minutes, seconds); - registerEntry(buf, time); - strftime(buf, 32, "%d/%m/%Y", localtime(&game.leaderboard[i - 1].when)); - registerEntry(buf, date); - } - } -} - -#undef registerEntry - -void leaderboardHandleRender() { - SDL_Rect rect; - rect.x = LEADERBOARD_WND_OFFSET_X; - rect.y = LEADERBOARD_WND_OFFSET_Y; - rect.w = LEADERBOARD_WND_WIDTH; - rect.h = LEADERBOARD_WND_HEIGHT; - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_RenderDrawRect(renderer, &rect); - rect.x++; - rect.y++; - rect.w -= 2; - rect.h -= 2; - SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255); - SDL_RenderFillRect(renderer, &rect); - - // Draw a table spanning the entire window. - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - rect.x = LEADERBOARD_WND_OFFSET_X + 10; - rect.y = LEADERBOARD_WND_OFFSET_Y + 10; - rect.w = LEADERBOARD_WND_WIDTH - 20; - rect.h = LEADERBOARD_WND_HEIGHT - 20; - SDL_RenderDrawRect(renderer, &rect); - - // Draw all table rows. - for (int i = 0; i < 10; i++) { - SDL_Rect row; - SDL_QueryTexture(leaderboard_data[i].no, NULL, NULL, &row.w, &row.h); - row.x = LEADERBOARD_WND_OFFSET_X + 15; - row.y = LEADERBOARD_WND_OFFSET_Y + 15 + i * 20; - SDL_RenderCopy(renderer, leaderboard_data[i].no, NULL, &row); - row.x += 30; - SDL_QueryTexture(leaderboard_data[i].points, NULL, NULL, &row.w, &row.h); - SDL_RenderCopy(renderer, leaderboard_data[i].points, NULL, &row); - row.x += 45; - SDL_QueryTexture(leaderboard_data[i].moves, NULL, NULL, &row.w, &row.h); - SDL_RenderCopy(renderer, leaderboard_data[i].moves, NULL, &row); - row.x += 50; - SDL_QueryTexture(leaderboard_data[i].time, NULL, NULL, &row.w, &row.h); - SDL_RenderCopy(renderer, leaderboard_data[i].time, NULL, &row); - row.x += 50; - SDL_QueryTexture(leaderboard_data[i].date, NULL, NULL, &row.w, &row.h); - SDL_RenderCopy(renderer, leaderboard_data[i].date, NULL, &row); - } - - // Draw the bars. - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - int x_offset = LEADERBOARD_WND_OFFSET_X; - int y_offset = LEADERBOARD_WND_OFFSET_Y; -#define draw_horiz(x) \ - x_offset += x; \ - SDL_RenderDrawLine(renderer, x_offset, LEADERBOARD_WND_OFFSET_Y + 10, x_offset, \ - LEADERBOARD_WND_OFFSET_Y + LEADERBOARD_WND_HEIGHT - 10); - draw_horiz(40); - draw_horiz(45); - draw_horiz(50); - draw_horiz(50); -#define draw_vert(x) \ - y_offset += x; \ - SDL_RenderDrawLine(renderer, LEADERBOARD_WND_OFFSET_X + 10, y_offset, \ - LEADERBOARD_WND_OFFSET_X + LEADERBOARD_WND_WIDTH - 10, y_offset); - draw_vert(33); - draw_vert(20); - draw_vert(20); - draw_vert(20); - draw_vert(20); - draw_vert(20); - draw_vert(20); - draw_vert(20); - draw_vert(20); -} diff --git a/spidersol/leaderboard.h b/spidersol/leaderboard.h deleted file mode 100644 index 3c92d05..0000000 --- a/spidersol/leaderboard.h +++ /dev/null @@ -1,17 +0,0 @@ - -#ifndef _LEADERBOARD_H -#define _LEADERBOARD_H - -#include "ui.h" - -#define LEADERBOARD_WND_HEIGHT 225 -#define LEADERBOARD_WND_WIDTH 290 -#define LEADERBOARD_WND_OFFSET_X (WIN_WIDTH - LEADERBOARD_WND_WIDTH) / 2 -#define LEADERBOARD_WND_OFFSET_Y (WIN_HEIGHT - LEADERBOARD_WND_HEIGHT) / 2 -#define LEADERBOARD_CARDS_X_SPACING 10 - -void onLeaderboardUpdate(); -void leaderboardHandleRender(); -void leaderboardHandleMouseUp(int x, int y); - -#endif diff --git a/spidersol/settings.c b/spidersol/settings.c deleted file mode 100644 index 5e7c845..0000000 --- a/spidersol/settings.c +++ /dev/null @@ -1,102 +0,0 @@ - -#include "settings.h" - -#include "game_state.h" -#include "ui.h" - -void settingsHandleMouseUp(int x, int y) { - // Check if we clicked outside of the settings window. - if (x <= SETTINGS_WND_OFFSET_X || x >= SETTINGS_WND_OFFSET_X + SETTINGS_WND_WIDTH || y <= SETTINGS_WND_OFFSET_Y || - y >= SETTINGS_WND_OFFSET_Y + SETTINGS_WND_HEIGHT) { - // OK, assume that we save the settings and proceed. - if (game.difficulty != game.prevdiff) { - // Reset the game. - new_game(); - } else { - game.state = STATE_GAME_IDLE; - } - return; - } - - // Check if we clicked on the card back selector. - if (x > SETTINGS_WND_OFFSET_X + 10 && x < SETTINGS_WND_OFFSET_X + 10 + CARD_WIDTH && - y > SETTINGS_WND_OFFSET_Y + 10 && y < SETTINGS_WND_OFFSET_Y + 10 + CARD_HEIGHT) { - game.selected_card_back = (game.selected_card_back + 1) % 13; - } - - // Check if we clicked on the difficulty selector. - int diffwidth = 0; - switch (game.difficulty) { - case 1: - diffwidth = CARD_WIDTH + SETTINGS_CARDS_X_SPACING; - break; - case 2: - diffwidth = CARD_WIDTH * 2 + SETTINGS_CARDS_X_SPACING * 2; - break; - case 3: - diffwidth = CARD_WIDTH * 4 + SETTINGS_CARDS_X_SPACING * 4; - break; - } - int baseX = SETTINGS_WND_OFFSET_X + CARD_WIDTH + 80, baseY = SETTINGS_WND_OFFSET_Y + 10; - if (x > baseX && x < baseX + diffwidth && y > baseY && y < baseY + CARD_HEIGHT) { - game.difficulty = (game.difficulty % 3) + 1; - } -} - -void settingsHandleRender() { - SDL_Rect rect; - rect.x = SETTINGS_WND_OFFSET_X; - rect.y = SETTINGS_WND_OFFSET_Y; - rect.w = SETTINGS_WND_WIDTH; - rect.h = SETTINGS_WND_HEIGHT; - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_RenderDrawRect(renderer, &rect); - rect.x++; - rect.y++; - rect.w -= 2; - rect.h -= 2; - SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255); - SDL_RenderFillRect(renderer, &rect); - static SDL_Texture * selBackText = NULL; - static SDL_Texture * diffText = NULL; - if (selBackText == NULL) { - SDL_Color color = { 0, 0, 0, 255 }; - SDL_Surface * surface = TTF_RenderText_Blended(font, "Selected card back:", color); - selBackText = SDL_CreateTextureFromSurface(renderer, surface); - SDL_FreeSurface(surface); - surface = TTF_RenderText_Blended(font, "Difficulty:", color); - diffText = SDL_CreateTextureFromSurface(renderer, surface); - SDL_FreeSurface(surface); - } - SDL_Rect text_rect; - text_rect.y = SETTINGS_WND_OFFSET_Y + 10; - text_rect.x = SETTINGS_WND_OFFSET_X + 10; - SDL_QueryTexture(selBackText, NULL, NULL, &text_rect.w, &text_rect.h); - SDL_RenderCopy(renderer, selBackText, NULL, &text_rect); - text_rect.y = SETTINGS_WND_OFFSET_Y + 30; - text_rect.w = CARD_WIDTH; - text_rect.h = CARD_HEIGHT; - SDL_RenderCopy(renderer, card_backs[game.selected_card_back], NULL, &text_rect); - text_rect.x = SETTINGS_WND_OFFSET_X + CARD_WIDTH + 80; - text_rect.y = SETTINGS_WND_OFFSET_Y + 10; - SDL_QueryTexture(diffText, NULL, NULL, &text_rect.w, &text_rect.h); - SDL_RenderCopy(renderer, diffText, NULL, &text_rect); - text_rect.y += 20; - text_rect.w = CARD_WIDTH; - text_rect.h = CARD_HEIGHT; - render_card(text_rect.x, text_rect.y, 3, 0); - text_rect.x += SETTINGS_CARDS_X_SPACING; - switch (game.difficulty) { - case 2: - render_card(text_rect.x, text_rect.y, 0, 0); - text_rect.x += SETTINGS_CARDS_X_SPACING; - break; - case 3: - render_card(text_rect.x, text_rect.y, 0, 0); - text_rect.x += SETTINGS_CARDS_X_SPACING; - render_card(text_rect.x, text_rect.y, 1, 0); - text_rect.x += SETTINGS_CARDS_X_SPACING; - render_card(text_rect.x, text_rect.y, 2, 0); - break; - } -} diff --git a/spidersol/settings.h b/spidersol/settings.h deleted file mode 100644 index f046351..0000000 --- a/spidersol/settings.h +++ /dev/null @@ -1,16 +0,0 @@ - -#ifndef _SETTINGS_H -#define _SETTINGS_H - -#include "ui.h" - -#define SETTINGS_WND_HEIGHT 150 -#define SETTINGS_WND_WIDTH 258 -#define SETTINGS_WND_OFFSET_X (WIN_WIDTH - SETTINGS_WND_WIDTH) / 2 -#define SETTINGS_WND_OFFSET_Y (WIN_HEIGHT - SETTINGS_WND_HEIGHT) / 2 -#define SETTINGS_CARDS_X_SPACING 10 - -void settingsHandleRender(); -void settingsHandleMouseUp(int x, int y); - -#endif diff --git a/spidersol/spidersol.c b/spidersol/spidersol.cpp similarity index 67% rename from spidersol/spidersol.c rename to spidersol/spidersol.cpp index cd7b0a0..38e65e5 100644 --- a/spidersol/spidersol.c +++ b/spidersol/spidersol.cpp @@ -5,17 +5,21 @@ #include #include +extern "C" { #include "cntrl.h" #include "deal.h" #include "engine.h" #include "game_state.h" #include "infobox.h" -#include "leaderboard.h" -#include "settings.h" #include "ui.h" #include "undo.h" #include "vector.h" #include "win.h" +} + +#include "../imgui/imgui.h" +#include "../imgui/imgui_impl_sdl2.h" +#include "../imgui/imgui_impl_sdlrenderer2.h" #define EXTRA_CARDS_X_OFFSET 740 #define EXTRA_CARDS_Y_OFFSET 570 @@ -28,10 +32,7 @@ #define MENU_HEIGHT 25 #define MENU_PADDING 5 -/* Misc game stuff */ -SDL_Rect menuButtons[7]; -void (*menuActions[7])(void); -int highlightedMenu = -1; +ImGuiIO * io; /* Dragging. */ int dragging_stack, dragging_stack_offset, dragging_stack_x, dragging_stack_y; @@ -209,118 +210,8 @@ void drop_stack(int x, int y) { } } -void onclickSettings() { - game.prevdiff = game.difficulty; - game.state = STATE_GAME_SETTINGS; -} - void onclickQuit() { exit(0); } -void onclickLeaderboard() { game.state = STATE_GAME_LEADERBOARD; } - -void render_menu() { - SDL_Rect rect; - rect.x = 0; - rect.y = 0; - rect.w = WIN_WIDTH; - rect.h = MENU_HEIGHT; - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_RenderDrawRect(renderer, &rect); - rect.x++; - rect.y++; - rect.w -= 2; - rect.h -= 2; - SDL_SetRenderDrawColor(renderer, 200, 200, 200, 255); - SDL_RenderFillRect(renderer, &rect); - -#define createmenu(var, selvar, name, action) \ - { \ - SDL_Color color = { 0, 0, 0, 255 }; \ - SDL_Surface * surface = TTF_RenderText_Blended(font, name, color); \ - var = SDL_CreateTextureFromSurface(renderer, surface); \ - SDL_Color selcolor = { 255, 255, 255, 255 }; \ - surface = TTF_RenderText_Blended(font, name, selcolor); \ - selvar = SDL_CreateTextureFromSurface(renderer, surface); \ - SDL_QueryTexture(var, NULL, NULL, &tmp_rect.w, &tmp_rect.h); \ - menuButtons[current_item] = tmp_rect; \ - menuActions[current_item] = action; \ - current_item++; \ - tmp_rect.x += tmp_rect.w + 2 * MENU_PADDING; \ - SDL_FreeSurface(surface); \ - } - - // Draw menu options: - // New Game | Restart | Undo | Redo | Settings | Quit - static SDL_Texture * newGameTexture = NULL; - static SDL_Texture * restartTexture = NULL; - static SDL_Texture * undoTexture = NULL; - static SDL_Texture * redoTexture = NULL; - static SDL_Texture * settingsTexture = NULL; - static SDL_Texture * leaderboardTexture = NULL; - static SDL_Texture * quitTexture = NULL; - static SDL_Texture * selnewGameTexture = NULL; - static SDL_Texture * selrestartTexture = NULL; - static SDL_Texture * selundoTexture = NULL; - static SDL_Texture * selredoTexture = NULL; - static SDL_Texture * selsettingsTexture = NULL; - static SDL_Texture * selleaderboardTexture = NULL; - static SDL_Texture * selquitTexture = NULL; - if (newGameTexture == NULL) { - int current_item = 0; - SDL_Rect tmp_rect; - tmp_rect.x = 2 * MENU_PADDING; - tmp_rect.y = MENU_PADDING; - createmenu(newGameTexture, selnewGameTexture, "New Game", new_game); - createmenu(restartTexture, selrestartTexture, "Restart", reset_game); - createmenu(undoTexture, selundoTexture, "Undo", undo); - createmenu(redoTexture, selredoTexture, "Redo", redo); - createmenu(settingsTexture, selsettingsTexture, "Settings", onclickSettings); - createmenu(leaderboardTexture, selleaderboardTexture, "Leaderboard", onclickLeaderboard); - createmenu(quitTexture, selquitTexture, "Quit", onclickQuit); - } - -#undef createmenu - -#define rendermenu(name, selname) \ - { \ - if (n++ == highlightedMenu) { \ - SDL_QueryTexture(selname, NULL, NULL, &menu_rect.w, &menu_rect.h); \ - SDL_Rect border; \ - border.x = menu_rect.x - MENU_PADDING; \ - border.y = 1; \ - border.h = MENU_HEIGHT - 2; \ - border.w = menu_rect.w + 2 * MENU_PADDING; \ - SDL_SetRenderDrawColor(renderer, 80, 80, 80, 255); \ - SDL_RenderDrawRect(renderer, &border); \ - SDL_SetRenderDrawColor(renderer, 20, 20, 128, 255); \ - rect.x++; \ - rect.y++; \ - rect.w -= 2; \ - rect.h -= 2; \ - SDL_RenderFillRect(renderer, &border); \ - SDL_RenderCopy(renderer, selname, NULL, &menu_rect); \ - } else { \ - SDL_QueryTexture(name, NULL, NULL, &menu_rect.w, &menu_rect.h); \ - SDL_RenderCopy(renderer, name, NULL, &menu_rect); \ - } \ - menu_rect.x += menu_rect.w + 2 * MENU_PADDING; \ - } - - SDL_Rect menu_rect; - int n = 0; - menu_rect.x = 2 * MENU_PADDING; - menu_rect.y = MENU_PADDING; - rendermenu(newGameTexture, selnewGameTexture); - rendermenu(restartTexture, selrestartTexture); - rendermenu(undoTexture, selundoTexture); - rendermenu(redoTexture, selredoTexture); - rendermenu(settingsTexture, selsettingsTexture); - rendermenu(leaderboardTexture, selleaderboardTexture); - rendermenu(quitTexture, selquitTexture); - -#undef rendermenu -} - #ifdef EMSCRIPTEN #include #include @@ -347,6 +238,7 @@ void main_loop(void) { done = SDL_TRUE; break; case SDL_MOUSEBUTTONDOWN: + if (io->WantCaptureMouse) break; if (event.button.button == SDL_BUTTON_LEFT) { switch (game.state) { case STATE_GAME_IDLE: @@ -390,26 +282,18 @@ void main_loop(void) { } break; case SDL_MOUSEMOTION: + if (io->WantCaptureMouse) break; if (game.state == STATE_GAME_DRAGGING_STACK) { dragging_stack_x = event.motion.x; dragging_stack_y = event.motion.y; - } else { - // Highlight menus? - highlightedMenu = -1; - for (int i = 0; i < 7; i++) { - if (event.motion.x >= menuButtons[i].x && event.motion.x >= menuButtons[i].y && - event.motion.x <= menuButtons[i].x + menuButtons[i].w && - event.motion.y <= menuButtons[i].y + menuButtons[i].h) { - highlightedMenu = i; - break; - } - } } break; case SDL_KEYDOWN: + if (io->WantCaptureKeyboard) break; cntrlHandleKey(event.key.keysym); break; case SDL_MOUSEBUTTONUP: + if (io->WantCaptureMouse) break; if (event.button.button == SDL_BUTTON_LEFT) { switch (game.state) { case STATE_GAME_IDLE: @@ -430,35 +314,24 @@ void main_loop(void) { game.state = STATE_GAME_DEALING_ROW; game.remainingExtraDeals--; } - } else if (highlightedMenu != -1) { - (menuActions[highlightedMenu])(); - } - break; - case STATE_GAME_FIREWORKS: - if (highlightedMenu != -1) { - (menuActions[highlightedMenu])(); } break; case STATE_GAME_DRAGGING_STACK: drop_stack(event.button.x, event.button.y); game.state = STATE_GAME_IDLE; break; - case STATE_GAME_SETTINGS: - settingsHandleMouseUp(event.button.x, event.button.y); - break; - case STATE_GAME_LEADERBOARD: - leaderboardHandleMouseUp(event.button.x, event.button.y); - break; case STATE_GAME_LOST: handleLossMouseUp(event.button.x, event.button.y); - if (highlightedMenu != -1) { - (menuActions[highlightedMenu])(); - } break; } } break; } + if (ImGui_ImplSDL2_ProcessEvent(&event)) continue; + if (event.type == SDL_QUIT || + (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && + event.window.windowID == SDL_GetWindowID(window))) + done = SDL_TRUE; } // Limit the game to 32fps. @@ -496,12 +369,6 @@ void main_loop(void) { case STATE_GAME_FIREWORKS: render_fireworks(); break; - case STATE_GAME_SETTINGS: - settingsHandleRender(); - break; - case STATE_GAME_LEADERBOARD: - leaderboardHandleRender(); - break; case STATE_GAME_LOST: handle_loss(); break; @@ -509,7 +376,66 @@ void main_loop(void) { tick_fireworks(frame_end - frame_start); - render_menu(); + ImGui_ImplSDLRenderer2_NewFrame(); + ImGui_ImplSDL2_NewFrame(window); + ImGui::NewFrame(); + + if (ImGui::BeginMainMenuBar()) { + if (ImGui::BeginMenu("Game")) { + if (ImGui::MenuItem("New Game", "Ctrl+N")) { + new_game(); + } + if (ImGui::MenuItem("Restart", "Ctrl+X")) { + reset_game(); + } + if (ImGui::MenuItem("Undo", "Ctrl+U")) { + undo(); + } + if (ImGui::MenuItem("Redo", "Ctrl+R")) { + redo(); + } + if (ImGui::MenuItem("Quit", "Ctrl+Q")) { + done = SDL_TRUE; + } + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Difficulty")) { + if (ImGui::MenuItem("Easy: One suit", NULL, game.difficulty == 1)) { + game.difficulty = 1; + new_game(); + } + if (ImGui::MenuItem("Medium: Two suits", NULL, game.difficulty == 2)) { + game.difficulty = 2; + new_game(); + } + if (ImGui::MenuItem("Hard: Four suits", NULL, game.difficulty == 3)) { + game.difficulty = 3; + new_game(); + } + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Card Back")) { + #define GEN_BACK(name, id) if (ImGui::MenuItem(name, NULL, game.selected_card_back == id)) game.selected_card_back = id; + GEN_BACK("Floral", 0); + GEN_BACK("Fish (blue)", 1); + GEN_BACK("Bricks", 2); + GEN_BACK("Acorns", 3); + GEN_BACK("Robot", 4); + GEN_BACK("Fish (cyan)", 5); + GEN_BACK("Dots", 6); + GEN_BACK("Castle", 7); + GEN_BACK("Fabric", 8); + GEN_BACK("Roses", 9); + GEN_BACK("Beach", 10); + GEN_BACK("Shell", 11); + GEN_BACK("Fish (yellow)", 12); + ImGui::EndMenu(); + } + ImGui::EndMainMenuBar(); + } + + ImGui::Render(); + ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData()); SDL_RenderPresent(renderer); @@ -542,6 +468,18 @@ int main(void) { frame_start = SDL_GetTicks64(); secondsCurrent = time(NULL); + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + io = &ImGui::GetIO(); + io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io->IniFilename = NULL; + io->LogFilename = NULL; + + ImGui::StyleColorsDark(); + + ImGui_ImplSDL2_InitForSDLRenderer(window, renderer); + ImGui_ImplSDLRenderer2_Init(renderer); + #ifndef EMSCRIPTEN while (!done) main_loop(); #else diff --git a/spidersol/ui.h b/spidersol/ui.h index 24696b2..c72e14f 100644 --- a/spidersol/ui.h +++ b/spidersol/ui.h @@ -14,7 +14,7 @@ #define CARD_HEIGHT 96 #define STACK_X_OFFSET 30 -#define STACK_Y_OFFSET 60 +#define STACK_Y_OFFSET 50 #define HIDDEN_Y_OFFSET 8 #define VISIBLE_Y_OFFSET 30 diff --git a/spidersol/win.c b/spidersol/win.c index 0d984bd..e243d64 100644 --- a/spidersol/win.c +++ b/spidersol/win.c @@ -2,7 +2,6 @@ #include "win.h" #include "game_state.h" -#include "leaderboard.h" #include "undo.h" void try_collapse_row() { @@ -57,40 +56,6 @@ void try_collapse_row() { int handle_victory() { boardStateChangedDispatcher(); - - // Add to the highest scores leaderboard? - // Check if there are empty leaderboard entries. - int i; - for (i = 0; i < 10; i++) { - if (game.leaderboard[i].when == 0) { - break; - } - } - - // If so, fill the slot with our score. - if (i < 10) { - game.leaderboard[i].score = game.points; - game.leaderboard[i].moves = game.moves; - game.leaderboard[i].time = game.time; - game.leaderboard[i].when = time(NULL); - onLeaderboardUpdate(); - } else { - // Otherwise, check if our score is higher than the lowest score. - int lowest = 0; - for (i = 0; i < 10; i++) { - if (game.leaderboard[i].score < game.points) { - lowest = i; - } - } - - if (game.points > game.leaderboard[lowest].score) { - game.leaderboard[lowest].score = game.points; - game.leaderboard[lowest].moves = game.moves; - game.leaderboard[lowest].time = game.time; - game.leaderboard[lowest].when = time(NULL); - onLeaderboardUpdate(); - } - } } #include "ui.h"