From fa300a8cdb9f20a3eec3144559599f59a7017dbd Mon Sep 17 00:00:00 2001 From: ostanton Date: Sat, 5 Apr 2025 22:43:07 +0100 Subject: UI additions + level and other things --- src/all.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 10 deletions(-) (limited to 'src/all.c') diff --git a/src/all.c b/src/all.c index e5c86db..14e37ac 100644 --- a/src/all.c +++ b/src/all.c @@ -91,12 +91,14 @@ static const Color colors[N_COLORS][4] = { #define BUTTON_SIZE 32 #define BUTTON_SPACING 16 -#define BUTTON_SPACER(i) (BUTTON_SPACING + (BUTTON_SIZE * (i) + (i) * BUTTON_SPACING)) +#define BUTTON_SPACER(i) (BUTTON_SPACING + BUTTON_SIZE + (BUTTON_SIZE * (i) + (i) * BUTTON_SPACING)) +// reverse order as they're anchored to bottom static const Button buttons[N_BUTTONS] = { - [BUTTON_CONTINUE] = {.x = BUTTON_SPACING, .y = BUTTON_SPACER(BUTTON_CONTINUE), .w = BUTTON_SIZE, .h = BUTTON_SIZE}, - [BUTTON_RETRY] = {.x = BUTTON_SPACING, .y = BUTTON_SPACER(BUTTON_RETRY), .w = BUTTON_SIZE, .h = BUTTON_SIZE}, [BUTTON_BACK] = {.x = BUTTON_SPACING, .y = BUTTON_SPACER(BUTTON_BACK), .w = BUTTON_SIZE, .h = BUTTON_SIZE}, + [BUTTON_RETRY] = {.x = BUTTON_SPACING, .y = BUTTON_SPACER(BUTTON_RETRY), .w = BUTTON_SIZE, .h = BUTTON_SIZE}, + [BUTTON_PLAY] = {.x = BUTTON_SPACING, .y = BUTTON_SPACER(BUTTON_PLAY), .w = BUTTON_SIZE, .h = BUTTON_SIZE}, + [BUTTON_CONTINUE] = {.x = BUTTON_SPACING, .y = BUTTON_SPACER(BUTTON_CONTINUE), .w = BUTTON_SIZE, .h = BUTTON_SIZE}, }; static DrawList *render(State *state, UI *ui, Arena *a) { @@ -132,6 +134,7 @@ static DrawList *render(State *state, UI *ui, Arena *a) { } } + // render end cell drawList->els[drawList->len++] = (DrawElement) { .x = cellWidth * state->goalx + GRID_OFFSET_X, .y = cellHeight * state->goaly, @@ -142,15 +145,17 @@ static DrawList *render(State *state, UI *ui, Arena *a) { .image = 1, }; + // render side panel drawList->els[drawList->len++] = (DrawElement) { .x = 0, .y = 0, .w = GRID_OFFSET_X, .h = ui->height, - .fill = {255, 255, 0, 255}, + .fill = {100, 100, 100, 255}, .border = {0, 0, 0, 255}, }; - + + // render buttons for (int i = 0; i < N_BUTTONS; i++) { Color colour = {0, 0, 0, 255}; switch (state->buttonStates[i]) { @@ -164,16 +169,51 @@ static DrawList *render(State *state, UI *ui, Arena *a) { colour = (Color) {255, 0, 0, 255}; break; } + int image = IMAGE_NULL; + switch (i) { + case BUTTON_CONTINUE: + image = IMAGE_CONTINUE; + break; + case BUTTON_BACK: + image = IMAGE_EXIT; + break; + case BUTTON_RETRY: + image = IMAGE_RETRY; + break; + case BUTTON_PLAY: + image = state->playing ? IMAGE_PAUSE : IMAGE_PLAY; + break; + } drawList->els[drawList->len++] = (DrawElement) { .x = buttons[i].x, - .y = buttons[i].y, + .y = ui->height - buttons[i].y, .w = buttons[i].w, .h = buttons[i].h, - .fill = colour, - .border = {0, 0, 0, 255} + .image = image, }; } + // render placeable cells + int cellCount = 0; // doesn't increment when ignoring empty cells + for (int i = 0; i < MAX_PLACEABLE_CELLS; i++) { + if (levels[state->currentLevel].placeableCells[i] == EMPTY) + continue; + + for (int x = 0; x < 2; x++) { + for (int y = 0; y < 2; y++) { + drawList->els[drawList->len++] = (DrawElement) { + .x = BUTTON_SIZE / 2 + x * (BUTTON_SIZE / 2), + .y = (BUTTON_SIZE / 2 + y * (BUTTON_SIZE / 2)) * (cellCount + 1), // TODO - padding + .w = BUTTON_SIZE / 2, + .h = BUTTON_SIZE / 2, + .fill = colors[cellCount + 1][x + 2 * y], + .border = {0, 0, 0, 0}, + }; + } + } + cellCount++; + } + return drawList; } @@ -189,15 +229,27 @@ static void update(Game *game, uint64_t now, Arena a) { for (int i = 0; i < N_BUTTONS; i++) { if ( game->mousex > buttons[i].x && game->mousex < buttons[i].x + buttons[i].w && - game->mousey > buttons[i].y && game->mousey < buttons[i].y + buttons[i].h + game->mousey > game->ui.height - buttons[i].y && + game->mousey < game->ui.height - buttons[i].y + buttons[i].h ) { // TODO - CLICK THINGS //game->state.buttonStates[i] = BUTTON_STATE_PRESSED; + switch (i) { + case BUTTON_RETRY: + break; + case BUTTON_CONTINUE: + break; + case BUTTON_BACK: + break; + case BUTTON_PLAY: + game->state.playing = !game->state.playing; + break; + } } } break; case INPUT_RCLICK: - x = game->mousex * GRIDWIDTH / game->ui.width; + x = (game->mousex - GRID_OFFSET_X) * GRIDWIDTH / offset_width; y = game->mousey * GRIDHEIGHT / game->ui.height; game->state.grid[x + y * GRIDWIDTH] = EMPTY; break; @@ -243,6 +295,7 @@ int main(int argc, char **argv) { xmemcpy(&game->state.grid, &levels[0].grid, sizeof(game->state.grid)); game->state.goalx = levels[0].goalx; game->state.goaly = levels[0].goaly; + game->state.currentLevel = 0; game->state.playing = 0; game->ui = (UI) { .width = 640, -- cgit v1.2.3 From af06f8718558683aa717bc98bcba1ed1a30e3737 Mon Sep 17 00:00:00 2001 From: ostanton <114495956+ostanton@users.noreply.github.com> Date: Sun, 6 Apr 2025 12:07:10 +0100 Subject: Functional continue and retry buttons --- src/all.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'src/all.c') diff --git a/src/all.c b/src/all.c index 2b0b850..9948b4b 100644 --- a/src/all.c +++ b/src/all.c @@ -225,7 +225,9 @@ static void update(Game *game, uint64_t now, Arena a) { case INPUT_CLICK: x = (game->mousex - GRID_OFFSET_X) * GRIDWIDTH / offset_width; y = game->mousey * GRIDHEIGHT / game->ui.height; - game->state.grid[x + y * GRIDWIDTH] = (game->state.grid[x + y * GRIDWIDTH] + 1) % (sizeof(colors) / sizeof(colors[0])); + if (x >= 0) + game->state.grid[x + y * GRIDWIDTH] = (game->state.grid[x + y * GRIDWIDTH] + 1) % (sizeof(colors) / sizeof(colors[0])); + for (int i = 0; i < N_BUTTONS; i++) { if ( game->mousex > buttons[i].x && game->mousex < buttons[i].x + buttons[i].w && @@ -235,10 +237,27 @@ static void update(Game *game, uint64_t now, Arena a) { // TODO - CLICK THINGS //game->state.buttonStates[i] = BUTTON_STATE_PRESSED; switch (i) { - case BUTTON_RETRY: + case BUTTON_RETRY: { + // reset to initial values + int currentLevel = game->state.currentLevel; + xmemcpy(&game->state.grid, &levels[currentLevel].grid, sizeof(game->state.grid)); + game->state.goalx = levels[currentLevel].goalx; + game->state.goaly = levels[currentLevel].goaly; + game->state.playing = 0; break; - case BUTTON_CONTINUE: + } + case BUTTON_CONTINUE: { + // TODO - don't allow if level has not been completed + if (game->state.currentLevel + 1 >= 2) // TODO - get size of levels array + break; + game->state.currentLevel++; + int currentLevel = game->state.currentLevel; + xmemcpy(&game->state.grid, &levels[currentLevel].grid, sizeof(game->state.grid)); + game->state.goalx = levels[currentLevel].goalx; + game->state.goaly = levels[currentLevel].goaly; + game->state.playing = 0; break; + } case BUTTON_BACK: break; case BUTTON_PLAY: -- cgit v1.2.3 From 672ae1cdc364d15787e0433b3578d0fb30e2231e Mon Sep 17 00:00:00 2001 From: ostanton <114495956+ostanton@users.noreply.github.com> Date: Sun, 6 Apr 2025 12:36:27 +0100 Subject: Tidied restart level, started on tracking placed cells --- src/all.c | 52 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) (limited to 'src/all.c') diff --git a/src/all.c b/src/all.c index 9948b4b..3e62732 100644 --- a/src/all.c +++ b/src/all.c @@ -199,11 +199,22 @@ static DrawList *render(State *state, UI *ui, Arena *a) { if (levels[state->currentLevel].placeableCells[i] == EMPTY) continue; + // TODO - FIXME (how to tell how many cells we have left of a colour? Maybe placedCells is a bad idea!) + int canContinue = 1; + for (int j = 0; j < MAX_PLACEABLE_CELLS; j++) { + if (levels[state->currentLevel].placeableCells[i] == state->placedCells[j]) { + canContinue = 0; + break; + } + } + if (canContinue == 0) + continue; + for (int x = 0; x < 2; x++) { for (int y = 0; y < 2; y++) { drawList->els[drawList->len++] = (DrawElement) { .x = BUTTON_SIZE / 2 + x * (BUTTON_SIZE / 2), - .y = (BUTTON_SIZE / 2 + y * (BUTTON_SIZE / 2)) * (cellCount + 1), // TODO - padding + .y = (BUTTON_SIZE / 2 + y * (BUTTON_SIZE / 2) + BUTTON_SPACING * (cellCount % 2 + 1)) * (cellCount + 1), // TODO - padding .w = BUTTON_SIZE / 2, .h = BUTTON_SIZE / 2, .fill = colors[cellCount + 1][x + 2 * y], @@ -217,7 +228,16 @@ static DrawList *render(State *state, UI *ui, Arena *a) { return drawList; } +static void restart_level(Game* game) { + const int level = game->state.currentLevel; + xmemcpy(&game->state.grid, &levels[level].grid, sizeof(game->state.grid)); + game->state.goalx = levels[level].goalx; + game->state.goaly = levels[level].goaly; + game->state.playing = 0; +} + static void update(Game *game, uint64_t now, Arena a) { + // TODO - offset some more because of right black bar, dependent on ui size and window size? const int offset_width = game->ui.width - GRID_OFFSET_X; switch (game->input) { @@ -225,8 +245,11 @@ static void update(Game *game, uint64_t now, Arena a) { case INPUT_CLICK: x = (game->mousex - GRID_OFFSET_X) * GRIDWIDTH / offset_width; y = game->mousey * GRIDHEIGHT / game->ui.height; - if (x >= 0) + if (x >= 0) { // TODO - 0 isn't far left of grid for some reason, it's slightly more game->state.grid[x + y * GRIDWIDTH] = (game->state.grid[x + y * GRIDWIDTH] + 1) % (sizeof(colors) / sizeof(colors[0])); + // TODO - some ignore list for which cells we have left to place + game->state.placedCells[0] = BLACK; + } for (int i = 0; i < N_BUTTONS; i++) { if ( @@ -237,27 +260,16 @@ static void update(Game *game, uint64_t now, Arena a) { // TODO - CLICK THINGS //game->state.buttonStates[i] = BUTTON_STATE_PRESSED; switch (i) { - case BUTTON_RETRY: { - // reset to initial values - int currentLevel = game->state.currentLevel; - xmemcpy(&game->state.grid, &levels[currentLevel].grid, sizeof(game->state.grid)); - game->state.goalx = levels[currentLevel].goalx; - game->state.goaly = levels[currentLevel].goaly; - game->state.playing = 0; + case BUTTON_RETRY: + restart_level(game); break; - } - case BUTTON_CONTINUE: { + case BUTTON_CONTINUE: // TODO - don't allow if level has not been completed if (game->state.currentLevel + 1 >= 2) // TODO - get size of levels array break; game->state.currentLevel++; - int currentLevel = game->state.currentLevel; - xmemcpy(&game->state.grid, &levels[currentLevel].grid, sizeof(game->state.grid)); - game->state.goalx = levels[currentLevel].goalx; - game->state.goaly = levels[currentLevel].goaly; - game->state.playing = 0; + restart_level(game); break; - } case BUTTON_BACK: break; case BUTTON_PLAY: @@ -275,6 +287,9 @@ static void update(Game *game, uint64_t now, Arena a) { case INPUT_PAUSE_PLAY: game->state.playing = !game->state.playing; break; + case INPUT_RESTART: + restart_level(game); + break; default: break; } @@ -377,6 +392,9 @@ int main(int argc, char **argv) { case SDLK_SPACE: game->input = INPUT_PAUSE_PLAY; break; + case SDLK_R: + game->input = INPUT_RESTART; + break; } break; case SDL_EVENT_WINDOW_RESIZED: -- cgit v1.2.3