From 7ddea7173d0e743e10329171ba9f796f74fb5fb9 Mon Sep 17 00:00:00 2001 From: Menase Teshale Date: Thu, 20 Aug 2026 00:48:11 +0300 Subject: Added a a delay to swap effects resolving - Now swapping pieces will store what was swapped and put you in a swap state - All effects are resolved after swapping animations are completed --- src/game.c | 219 +++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 134 insertions(+), 85 deletions(-) (limited to 'src') diff --git a/src/game.c b/src/game.c index 9c4d22e..b85d3ca 100644 --- a/src/game.c +++ b/src/game.c @@ -72,7 +72,8 @@ typedef struct { typedef enum { intro_state, neutral_state, - piece_held_state + piece_held_state, + swap_animation_state } game_scene_state; typedef struct { @@ -88,6 +89,7 @@ typedef struct { int board_height; int selected_piece_id; + int swap_piece_id; SDL_Texture* background_texture; float background_offset; @@ -323,6 +325,132 @@ void update_intro_state() { game.state = neutral_state; } +static inline void find_piece_on_board +( + int piece_id, + int* board_y_pos, + int* board_x_pos + ) { + *board_y_pos = -1; + *board_x_pos = -1; + + for (int i = 0; i < game.board_height; i++) { + for (int j = 0; j < game.board_width; j++) { + if (filled_tile_at(i, j) && game.board[i][j].piece_id == piece_id) { + *board_y_pos = i; + *board_x_pos = j; + + return; + } + } + } +} + +void find_last_color_matching_tile_in_direction(int* sy, int* sx, int dy, int dx) { + if (!filled_tile_at(*sy, *sx)) + return; + + piece* start_piece = retreive_piece(game.board[*sy][*sx].piece_id); + + for(;;) { + int ny = *sy + dy, nx = *sx + dx; + + if (!filled_tile_at(ny, nx)) + return; + + piece* next_piece = retreive_piece(game.board[ny][nx].piece_id); + + if (!next_piece || next_piece->piece_color != start_piece->piece_color) + return; + + *sy = ny; *sx = nx; + } +} + +bool try_clear_at(int y, int x) { + const int axes[2][2] = { + {1, 0}, //Horizontal + {0, 1} //Vertical + }; + + for (int a = 0; a < 2; a++) { + int sy = y, sx = x, dy = axes[a][1], dx = axes[a][0]; + find_last_color_matching_tile_in_direction(&sy, &sx, dy, dx); + + int ey = sy, ex = sx; + find_last_color_matching_tile_in_direction(&ey, &ex, -dy, -dx); + + if (SDL_abs(ey-sy) + SDL_abs(ex-sx) + 1 < MIN_TILES_TO_CLEAR) + continue; + + for (;;) { + piece_start_falling(retreive_piece(game.board[ey][ex].piece_id)); + game.board[ey][ex].state = tile_currently_empty; + + if (ey == sy && ex == sx) + break; + + ey += dy; ex += dx; + } + + return true; + } + + return false; +} + +void cascade_tiles() { + for (int j = 0; j < game.board_width; j++) { + for (int i = 0; i < game.board_height; i++) { + if (game.board[i][j].state != tile_currently_empty) + continue; + + //Look for the first filled tile above and start moving it down + for (int c = i-1; c >= 0; c--) { + if (game.board[c][j].state == tile_filled) { + piece* piece = retreive_piece(game.board[c][j].piece_id); + piece_start_moving_to(piece, + board_position(c+1, j), + PIECE_LINEAR_SPEED + ); + game.board[c+1][j] = game.board[c][j]; + } + } + + add_piece_at(0, j); + } + } +} + +void update_piece_swap_animation_state() { + for (int i = 0; i < game.num_pieces; i++) { + if (game.pieces[i].state != static_state && game.pieces[i].state != fall_state) + return; + } + + int selected_piece_id = game.selected_piece_id; + int swap_piece_id = game.swap_piece_id; + + int selected_y, selected_x; + int swap_y, swap_x; + + find_piece_on_board(selected_piece_id, &selected_y, &selected_x); + find_piece_on_board(swap_piece_id, &swap_y, &swap_x); + + if (filled_tile_at(selected_y, selected_x) && filled_tile_at(swap_y, swap_x)) { + bool tiles_cleared = try_clear_at(selected_y, selected_x); + tiles_cleared = try_clear_at(swap_y, swap_x) || tiles_cleared; + + if (tiles_cleared) { + cascade_tiles(); + game.state = intro_state; + return; + } + } + + game.state = neutral_state; +} + void handle_piece_rotation(float dt) { int selected_piece_id = mouse_on_piece(); @@ -367,6 +495,8 @@ void update_game(float dt) { if (game.state == intro_state) { update_intro_state(); + } else if (game.state == swap_animation_state) { + update_piece_swap_animation_state(); } } @@ -460,82 +590,6 @@ void swap_pieces_at(int x1, int y1, int x2 , int y2) { } } -void find_last_color_matching_tile_in_direction(int* sy, int* sx, int dy, int dx) { - if (!filled_tile_at(*sy, *sx)) - return; - - piece* start_piece = retreive_piece(game.board[*sy][*sx].piece_id); - - for(;;) { - int ny = *sy + dy, nx = *sx + dx; - - if (!filled_tile_at(ny, nx)) - return; - - piece* next_piece = retreive_piece(game.board[ny][nx].piece_id); - - if (!next_piece || next_piece->piece_color != start_piece->piece_color) - return; - - *sy = ny; *sx = nx; - } -} - -bool try_clear_at(int y, int x) { - const int axes[2][2] = { - {1, 0}, //Horizontal - {0, 1} //Vertical - }; - - for (int a = 0; a < 2; a++) { - int sy = y, sx = x, dy = axes[a][1], dx = axes[a][0]; - find_last_color_matching_tile_in_direction(&sy, &sx, dy, dx); - - int ey = sy, ex = sx; - find_last_color_matching_tile_in_direction(&ey, &ex, -dy, -dx); - - if (SDL_abs(ey-sy) + SDL_abs(ex-sx) + 1 < MIN_TILES_TO_CLEAR) - continue; - - for (;;) { - piece_start_falling(retreive_piece(game.board[ey][ex].piece_id)); - game.board[ey][ex].state = tile_currently_empty; - - if (ey == sy && ex == sx) - break; - - ey += dy; ex += dx; - } - - return true; - } - - return false; -} - -void cascade_pieces() { - for (int j = 0; j < game.board_width; j++) { - for (int i = 0; i < game.board_height; i++) { - if (game.board[i][j].state != tile_currently_empty) - continue; - - //Look for the first filled tile above and start moving it down - for (int c = i-1; c >= 0; c--) { - if (game.board[c][j].state == tile_filled) { - piece* piece = retreive_piece(game.board[c][j].piece_id); - piece_start_moving_to(piece, - board_position(c+1, j), - PIECE_LINEAR_SPEED - ); - game.board[c+1][j] = game.board[c][j]; - } - } - - add_piece_at(0, j); - } - } -} - void piece_held_event(SDL_Event* e) { if (e->type == SDL_EVENT_MOUSE_BUTTON_UP && e->button.button == SDL_BUTTON_LEFT) { int swap_piece_id = mouse_on_piece(); @@ -568,15 +622,10 @@ void piece_held_event(SDL_Event* e) { } swap_pieces_at(selected_x, selected_y, swap_x, swap_y); + game.swap_piece_id = swap_piece_id; - bool tiles_cleared = try_clear_at(selected_y, selected_x); - tiles_cleared = try_clear_at(swap_y, swap_x) || tiles_cleared; //sneaky short circuit glitch - - if (tiles_cleared) { - cascade_pieces(); - game.state = intro_state; - return; - } + game.state = swap_animation_state; + return; } game.state = neutral_state; -- cgit v1.2.3