summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMenase Teshale <osome3717@gmail.com>2026-09-29 03:11:31 +0300
committerMenase Teshale <osome3717@gmail.com>2026-09-29 03:11:31 +0300
commita82f702665b7dd299ae2b3ee03dba246029d0c58 (patch)
tree860b5eaba48f2d526504248a33cc5eb108085d63
parentb2b814b95769a2085652b2a51e766c4f240769d6 (diff)
Finally enabled cascading fallsHEADmain
- The ability to pick the time for timed mode also added - TODO: Massive refactor
-rw-r--r--src/game.c92
-rw-r--r--src/menu.c52
2 files changed, 101 insertions, 43 deletions
diff --git a/src/game.c b/src/game.c
index eef1328..a2fd6ad 100644
--- a/src/game.c
+++ b/src/game.c
@@ -92,6 +92,7 @@ typedef enum {
neutral_state,
piece_held_state,
swap_animation_state,
+ cascade_state,
game_over_state
} game_scene_state;
@@ -443,27 +444,6 @@ 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;
@@ -534,6 +514,12 @@ void process_clear(int sy, int sx, int ey, int ex) {
}
}
+
+static inline void play_sound_effect(MIX_Audio* audio) {
+ MIX_SetTrackAudio(game.effect_track, audio);
+ MIX_PlayTrack(game.effect_track, 0);
+}
+
bool try_clear_at(int y, int x) {
const int axes[2][2] = {
{1, 0}, //Horizontal
@@ -562,12 +548,25 @@ bool try_clear_at(int y, int x) {
ey += dy; ex += dx;
}
+ play_sound_effect(game.pop_audio);
return true;
}
return false;
}
+bool cascade_followup() {
+ bool tiles_cleared = false;
+
+ for (int i = game.board_height; i >= 0; i--) {
+ for (int j = game.board_width; j >= 0; j--) {
+ tiles_cleared |= try_clear_at(i, j);
+ }
+ }
+
+ return tiles_cleared;
+}
+
void cascade_tiles() {
for (int j = 0; j < game.board_width; j++) {
for (int i = 0; i < game.board_height; i++) {
@@ -591,9 +590,46 @@ void cascade_tiles() {
}
}
-static inline void play_sound_effect(MIX_Audio* audio) {
- MIX_SetTrackAudio(game.effect_track, audio);
- MIX_PlayTrack(game.effect_track, 0);
+void update_cascade_state() {
+ if (game.state != cascade_state)
+ return;
+
+ for (int i = 0; i < game.num_pieces; i++) {
+ if (game.pieces[i].state != static_state && game.pieces[i].state != fall_state) {
+ return;
+ }
+ }
+
+ bool extra_tiles_cleared = cascade_followup();
+
+ if (extra_tiles_cleared) {
+ cascade_tiles();
+ game.state = cascade_state;
+ } else {
+ 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 update_piece_swap_animation_state() {
@@ -621,7 +657,7 @@ void update_piece_swap_animation_state() {
if (tiles_cleared) {
play_sound_effect(game.pop_audio);
cascade_tiles();
- game.state = intro_state;
+ game.state = cascade_state;
return;
}
}
@@ -681,6 +717,7 @@ void update_game(float dt) {
scroll_background(dt);
update_intro_state();
+ update_cascade_state();
update_piece_swap_animation_state();
update_timed_mode(dt);
@@ -955,7 +992,10 @@ void game_event(SDL_Event* e) {
void update_timed_mode(float dt) {
timed_mode_data* timed_mode_data = &game.timed_mode_data;
- if (game.state != intro_state && game.state != swap_animation_state) {
+ if (game.state != intro_state &&
+ game.state != swap_animation_state
+ && game.state != cascade_state
+ ) {
timed_mode_data->time_remaining =
SDL_max(timed_mode_data->time_remaining - dt, 0);
}
diff --git a/src/menu.c b/src/menu.c
index 74e91ef..fa3b588 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1,10 +1,13 @@
#include "app.h"
#include "font.h"
+#include <stdio.h>
#define MENU_ITEM_TOP_YPOS_RELATIVE 0.3
-#define MENU_ITEM_YOFFSET_RELATIVE 0.03
-#define UNSELECTED_ITEM_SCALE 1
-#define SELECTED_ITEM_SCALE 1.2
+#define MENU_ITEM_YOFFSET_RELATIVE 0.05
+#define UNSELECTED_ITEM_SCALE 2
+#define SELECTED_ITEM_SCALE 2.4
+#define MINIMUM_TIMED_MODE_TIME 5
+#define TIMED_MODE_STEP 3
typedef enum {
timed_mode_option = 0,
@@ -12,6 +15,7 @@ typedef enum {
} menu_option;
menu_option selected_option;
+int timed_mode_time;
sprite_font text_font;
extern SDL_Window* window;
@@ -25,27 +29,37 @@ void init_menu(SDL_Renderer* renderer) {
}
selected_option = timed_mode_option;
+ timed_mode_time = MINIMUM_TIMED_MODE_TIME + 2*TIMED_MODE_STEP;
}
void draw_menu(SDL_Renderer* renderer) {
SDL_RenderClear(renderer);
- const char* labels[] = {
- "Timed Mode",
- "Exit",
- };
-
float yp = MENU_ITEM_TOP_YPOS_RELATIVE;
for (menu_option i = timed_mode_option; i <= exit_option; i++) {
float scale = i == selected_option ? SELECTED_ITEM_SCALE : UNSELECTED_ITEM_SCALE;
- draw_text_with_spritefont_extended(renderer,
- &text_font,
- (unsigned char*)labels[i],
- get_window_relative_xpos(0.5),
- get_window_relative_ypos(yp),
- scale
- );
+ if (i == timed_mode_option) {
+ char timed_mode_label[100];
+ snprintf(timed_mode_label, 100, "Timed Mode <%d>", timed_mode_time);
+
+ draw_text_with_spritefont_extended(renderer,
+ &text_font,
+ (unsigned char*)timed_mode_label,
+ get_window_relative_xpos(0.5),
+ get_window_relative_ypos(yp),
+ scale
+ );
+ } else if (i == exit_option) {
+ draw_text_with_spritefont_extended(renderer,
+ &text_font,
+ (unsigned char*)"Exit",
+ get_window_relative_xpos(0.5),
+ get_window_relative_ypos(yp),
+ scale
+ );
+ }
+
yp += MENU_ITEM_YOFFSET_RELATIVE;
}
@@ -66,7 +80,7 @@ SDL_AppResult menu_execute_action() {
if (selected_option == exit_option) {
return SDL_APP_SUCCESS;
} if (selected_option == timed_mode_option) {
- init_timed_game(NULL, NULL, 5);
+ init_timed_game(NULL, NULL, timed_mode_time);
app_state = game_state;
}
@@ -77,7 +91,11 @@ SDL_AppResult menu_event(SDL_Event* e) {
if (e->type == SDL_EVENT_KEY_DOWN) {
SDL_Scancode pressed_button = e->key.scancode;
- if (pressed_button == SDL_SCANCODE_RETURN) {
+ if (pressed_button == SDL_SCANCODE_RIGHT && selected_option == timed_mode_option) {
+ timed_mode_time += TIMED_MODE_STEP;
+ } else if (pressed_button == SDL_SCANCODE_LEFT && selected_option == timed_mode_option) {
+ timed_mode_time = SDL_max(MINIMUM_TIMED_MODE_TIME, timed_mode_time-TIMED_MODE_STEP);
+ } else if (pressed_button == SDL_SCANCODE_RETURN) {
return menu_execute_action();
} else if (pressed_button == SDL_SCANCODE_DOWN) {
select_next_option();