From 2a714c74362937530aed750d26170919f8501ff9 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 11 Aug 2025 20:47:01 -0400 Subject: [PATCH 01/22] Moved face --- movement_faces.h | 1 + watch-faces.mk | 1 + .../complication/endless_runner_face.c | 0 .../complication/endless_runner_face.h | 0 4 files changed, 2 insertions(+) rename {legacy/watch_faces => watch-faces}/complication/endless_runner_face.c (100%) rename {legacy/watch_faces => watch-faces}/complication/endless_runner_face.h (100%) diff --git a/movement_faces.h b/movement_faces.h index fc43716d..bcd82330 100644 --- a/movement_faces.h +++ b/movement_faces.h @@ -73,4 +73,5 @@ #include "wareki_face.h" #include "deadline_face.h" #include "wordle_face.h" +#include "endless_runner_face.h" // New includes go above this line. diff --git a/watch-faces.mk b/watch-faces.mk index 22e262cf..95d81875 100644 --- a/watch-faces.mk +++ b/watch-faces.mk @@ -48,4 +48,5 @@ SRCS += \ ./watch-faces/sensor/lis2dw_monitor_face.c \ ./watch-faces/complication/wareki_face.c \ ./watch-faces/complication/deadline_face.c \ + ./watch-faces/complication/endless_runner_face.c \ # New watch faces go above this line. diff --git a/legacy/watch_faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c similarity index 100% rename from legacy/watch_faces/complication/endless_runner_face.c rename to watch-faces/complication/endless_runner_face.c diff --git a/legacy/watch_faces/complication/endless_runner_face.h b/watch-faces/complication/endless_runner_face.h similarity index 100% rename from legacy/watch_faces/complication/endless_runner_face.h rename to watch-faces/complication/endless_runner_face.h From d9466cb2d1180057acbbd9a4d0c22be26dbba305 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 11 Aug 2025 21:05:04 -0400 Subject: [PATCH 02/22] Modified for custom display --- .../complication/endless_runner_face.c | 175 ++++++++---------- 1 file changed, 74 insertions(+), 101 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 1a173293..e1368707 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -77,6 +77,23 @@ typedef struct { uint8_t fuel; } game_state_t; +// always-on, left, right, bottom, jump-top, jump-left, jump-right +int8_t classic_ball_arr_com[] = {1, 0, 1, 0, 2, 1, 2}; +int8_t classic_ball_arr_seg[] = {20, 20, 21, 21, 20, 17, 21}; +int8_t custom_ball_arr_com[] = {2, 1, 1, 0, 3, 3, 2}; +int8_t custom_ball_arr_seg[] = {15, 15, 14, 15, 14, 15, 14}; + +// obstacle 0-11 +int8_t classic_obstacle_arr_com[] = {0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0}; +int8_t classic_obstacle_arr_seg[] = {18, 19, 20, 21, 22, 23, 0, 1, 2, 4, 5, 6}; +int8_t custom_obstacle_arr_com[] = {1, 1, 1, 1, 1, 0, 1, 0, 3, 0, 0, 2}; +int8_t custom_obstacle_arr_seg[] = {22, 16, 15, 14, 1, 2, 3, 4, 4, 5, 6, 7}; + +int8_t *ball_arr_com; +int8_t *ball_arr_seg; +int8_t *obstacle_arr_com; +int8_t *obstacle_arr_seg; + static game_state_t game_state; static const uint8_t _num_bits_obst_pattern = sizeof(game_state.obst_pattern) * 8; @@ -84,7 +101,7 @@ static void print_binary(uint32_t value, int bits) { #if __EMSCRIPTEN__ for (int i = bits - 1; i >= 0; i--) { // Print each bit - printf("%lu", (value >> i) & 1); + printf("%u", (value >> i) & 1); // Optional: add a space every 4 bits for readability if (i % 4 == 0 && i != 0) { printf(" "); @@ -188,22 +205,22 @@ static uint32_t get_random_legal(uint32_t prev_val, uint16_t difficulty) { static void display_ball(bool jumping) { if (!jumping) { - watch_set_pixel(0, 21); - watch_set_pixel(1, 21); - watch_set_pixel(0, 20); - watch_set_pixel(1, 20); - watch_clear_pixel(1, 17); - watch_clear_pixel(2, 20); - watch_clear_pixel(2, 21); + watch_set_pixel(ball_arr_com[3], ball_arr_seg[3]); + watch_set_pixel(ball_arr_com[2], ball_arr_seg[2]); + watch_set_pixel(ball_arr_com[1], ball_arr_seg[1]); + watch_set_pixel(ball_arr_com[0], ball_arr_seg[0]); + watch_clear_pixel(ball_arr_com[6], ball_arr_seg[6]); + watch_clear_pixel(ball_arr_com[5], ball_arr_seg[5]); + watch_clear_pixel(ball_arr_com[4], ball_arr_seg[4]); } else { - watch_clear_pixel(0, 21); - watch_clear_pixel(1, 21); - watch_clear_pixel(0, 20); - watch_set_pixel(1, 20); - watch_set_pixel(1, 17); - watch_set_pixel(2, 20); - watch_set_pixel(2, 21); + watch_clear_pixel(ball_arr_com[3], ball_arr_seg[3]); + watch_clear_pixel(ball_arr_com[2], ball_arr_seg[2]); + watch_clear_pixel(ball_arr_com[1], ball_arr_seg[1]); + watch_set_pixel(ball_arr_com[0], ball_arr_seg[0]); + watch_set_pixel(ball_arr_com[6], ball_arr_seg[6]); + watch_set_pixel(ball_arr_com[5], ball_arr_seg[5]); + watch_set_pixel(ball_arr_com[4], ball_arr_seg[4]); } } @@ -212,12 +229,12 @@ static void display_score(uint8_t score) { if (game_state.fuel_mode) { score %= (MAX_DISP_SCORE_FUEL + 1); sprintf(buf, "%1d", score); - watch_display_string(buf, 0); + watch_display_text(WATCH_POSITION_TOP_LEFT, buf); } else { score %= (MAX_DISP_SCORE + 1); sprintf(buf, "%2d", score); - watch_display_string(buf, 2); + watch_display_text(WATCH_POSITION_TOP_RIGHT, buf); } } @@ -234,11 +251,11 @@ static void add_to_score(endless_runner_state_t *state) { static void display_fuel(uint8_t subsecond, uint8_t difficulty) { char buf[4]; if (difficulty == DIFF_FUEL_1 && game_state.fuel == 0 && subsecond % (FREQ/2) == 0) { - watch_display_string(" ", 2); // Blink the 0 fuel to show it cannot be refilled. + watch_display_text(WATCH_POSITION_TOP_RIGHT, " "); // Blink the 0 fuel to show it cannot be refilled. return; } sprintf(buf, "%2d", game_state.fuel); - watch_display_string(buf, 2); + watch_display_text(WATCH_POSITION_TOP_RIGHT, buf); } static void check_and_reset_hi_score(endless_runner_state_t *state) { @@ -255,28 +272,15 @@ static void check_and_reset_hi_score(endless_runner_state_t *state) { } static void display_difficulty(uint16_t difficulty) { - switch (difficulty) - { - case DIFF_BABY: - watch_display_string(" b", 2); - break; - case DIFF_EASY: - watch_display_string(" E", 2); - break; - case DIFF_HARD: - watch_display_string(" H", 2); - break; - case DIFF_FUEL: - watch_display_string(" F", 2); - break; - case DIFF_FUEL_1: - watch_display_string("1F", 2); - break; - case DIFF_NORM: - default: - watch_display_string(" N", 2); - break; - } + static const char *labels[] = { + [DIFF_BABY] = " b", + [DIFF_EASY] = " E", + [DIFF_HARD] = " H", + [DIFF_FUEL] = " F", + [DIFF_FUEL_1] = "1F", + [DIFF_NORM] = " N" + }; + watch_display_text(WATCH_POSITION_TOP_RIGHT, labels[difficulty]); game_state.fuel_mode = difficulty >= DIFF_FUEL && difficulty <= DIFF_FUEL_1; } @@ -309,13 +313,15 @@ static void display_title(endless_runner_state_t *state) { game_state.sec_before_moves = 1; // The first obstacles will all be 0s, which is about an extra second of delay. if (sound_on) game_state.sec_before_moves--; // Start chime is about 1 second watch_set_colon(); + watch_display_text_with_fallback(WATCH_POSITION_TOP, "RUN", "ER"); + watch_display_text(WATCH_POSITION_TOP_RIGHT, " "); if (hi_score > MAX_HI_SCORE) { - watch_display_string("ER HS --", 0); + watch_display_text(WATCH_POSITION_BOTTOM, "HS --"); } else { - char buf[14]; - sprintf(buf, "ER HS%4d", hi_score); - watch_display_string(buf, 0); + char buf[10]; + sprintf(buf, "HS%4d", hi_score); + watch_display_text(WATCH_POSITION_BOTTOM, buf); } display_difficulty(difficulty); } @@ -337,17 +343,12 @@ static void display_time(watch_date_time_t date_time, bool clock_mode_24h) { } watch_set_colon(); sprintf( buf, "%2d%02d ", hour, date_time.unit.minute); - watch_display_string(buf, 4); + watch_display_text(WATCH_POSITION_BOTTOM, buf); } - // If both digits of the minute need updating - else if ((date_time.unit.minute / 10) != (previous_date_time.unit.minute / 10)) { - sprintf( buf, "%02d ", date_time.unit.minute); - watch_display_string(buf, 6); - } - // If only the ones-place of the minute needs updating. - else if (date_time.unit.minute != previous_date_time.unit.minute) { - sprintf( buf, "%d ", date_time.unit.minute % 10); - watch_display_string(buf, 7); + // If only the minute need updating + else { + sprintf( buf, "%02d", date_time.unit.minute); + watch_display_text(WATCH_POSITION_MINUTES, buf); } previous_date_time.reg = date_time.reg; } @@ -358,14 +359,15 @@ static void begin_playing(endless_runner_state_t *state) { watch_clear_colon(); movement_request_tick_frequency((state -> difficulty == DIFF_BABY) ? FREQ_SLOW : FREQ); if (game_state.fuel_mode) { - watch_display_string(" ", 0); + watch_clear_display(); game_state.obst_pattern = get_random_fuel(0); if ((16 * JUMP_FRAMES_FUEL_RECHARGE) < JUMP_FRAMES_FUEL) // 16 frames of zeros at the start of a level game_state.fuel = JUMP_FRAMES_FUEL - (16 * JUMP_FRAMES_FUEL_RECHARGE); // Have it below its max to show it counting up when starting. if (game_state.fuel < JUMP_FRAMES_FUEL_RECHARGE) game_state.fuel = JUMP_FRAMES_FUEL_RECHARGE; } else { - watch_display_string(" ", 2); + watch_display_text(WATCH_POSITION_TOP_RIGHT, " "); + watch_display_text(WATCH_POSITION_BOTTOM, " "); game_state.obst_pattern = get_random_legal(0, difficulty); } game_state.jump_state = NOT_JUMPING; @@ -381,7 +383,8 @@ static void begin_playing(endless_runner_state_t *state) { static void display_lose_screen(endless_runner_state_t *state) { game_state.curr_screen = SCREEN_LOSE; game_state.curr_score = 0; - watch_display_string(" LOSE ", 0); + watch_clear_display(); + watch_display_text(WATCH_POSITION_BOTTOM, " LOSE "); if (state -> soundOn) watch_buzzer_play_note(BUZZER_NOTE_A1, 600); else @@ -395,9 +398,9 @@ static void display_obstacle(bool obstacle, int grid_loc, endless_runner_state_t case 2: game_state.loc_2_on = obstacle; if (obstacle) - watch_set_pixel(0, 20); + watch_set_pixel(obstacle_arr_com[grid_loc], obstacle_arr_seg[grid_loc]); else if (game_state.jump_state != NOT_JUMPING) { - watch_clear_pixel(0, 20); + watch_clear_pixel(obstacle_arr_com[grid_loc], obstacle_arr_seg[grid_loc]); if (game_state.fuel_mode && prev_obst_pos_two) add_to_score(state); } @@ -406,55 +409,20 @@ static void display_obstacle(bool obstacle, int grid_loc, endless_runner_state_t case 3: game_state.loc_3_on = obstacle; if (obstacle) - watch_set_pixel(1, 21); + watch_set_pixel(obstacle_arr_com[grid_loc], obstacle_arr_seg[grid_loc]); else if (game_state.jump_state != NOT_JUMPING) - watch_clear_pixel(1, 21); + watch_clear_pixel(obstacle_arr_com[grid_loc], obstacle_arr_seg[grid_loc]); break; case 1: if (!game_state.fuel_mode && obstacle) // If an obstacle is here, it means the ball cleared it add_to_score(state); //fall through - case 0: - case 5: - if (obstacle) - watch_set_pixel(0, 18 + grid_loc); - else - watch_clear_pixel(0, 18 + grid_loc); - break; - case 4: - if (obstacle) - watch_set_pixel(1, 22); - else - watch_clear_pixel(1, 22); - break; - case 6: - if (obstacle) - watch_set_pixel(1, 0); - else - watch_clear_pixel(1, 0); - break; - case 7: - case 8: - if (obstacle) - watch_set_pixel(0, grid_loc - 6); - else - watch_clear_pixel(0, grid_loc - 6); - break; - case 9: - case 10: - if (obstacle) - watch_set_pixel(0, grid_loc - 5); - else - watch_clear_pixel(0, grid_loc - 5); - break; - case 11: - if (obstacle) - watch_set_pixel(1, 6); - else - watch_clear_pixel(1, 6); - break; default: + if (obstacle) + watch_set_pixel(obstacle_arr_com[grid_loc], obstacle_arr_seg[grid_loc]); + else + watch_clear_pixel(obstacle_arr_com[grid_loc], obstacle_arr_seg[grid_loc]); break; } } @@ -551,6 +519,11 @@ void endless_runner_face_setup(uint8_t watch_face_index, void ** context_ptr) { void endless_runner_face_activate(void *context) { (void) context; + bool is_custom_lcd = watch_get_lcd_type() == WATCH_LCD_TYPE_CUSTOM; + ball_arr_com = is_custom_lcd ? custom_ball_arr_com : classic_ball_arr_com; + ball_arr_seg = is_custom_lcd ? custom_ball_arr_seg : classic_ball_arr_seg; + obstacle_arr_com = is_custom_lcd ? custom_obstacle_arr_com : classic_obstacle_arr_com; + obstacle_arr_seg = is_custom_lcd ? custom_obstacle_arr_seg : classic_obstacle_arr_seg; } bool endless_runner_face_loop(movement_event_t event, void *context) { From 89b58cbb795eed7082ab6446f547011fc1f98116 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 11 Aug 2025 21:12:27 -0400 Subject: [PATCH 03/22] Fixed time display --- watch-faces/complication/endless_runner_face.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index e1368707..b7e78667 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -573,7 +573,7 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { display_title(state); break; case EVENT_LOW_ENERGY_UPDATE: - display_time(watch_rtc_get_date_time(), movement_clock_mode_24h()); + display_time(movement_get_local_date_time(), movement_clock_mode_24h()); break; default: return movement_default_loop_handler(event); From 553572db5f8c844b727ef19c1b415c69197fb3be Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 11 Aug 2025 21:15:44 -0400 Subject: [PATCH 04/22] included delay.h --- watch-faces/complication/endless_runner_face.c | 1 + 1 file changed, 1 insertion(+) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index b7e78667..d3985d40 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -25,6 +25,7 @@ #include #include #include "endless_runner_face.h" +#include "delay.h" typedef enum { JUMPING_FINAL_FRAME = 0, From 47c62f66fdd1687bc71037c056246a4f45dc0f20 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 17 Aug 2025 12:54:33 -0400 Subject: [PATCH 05/22] Added tapping to endless runner --- watch-faces/complication/endless_runner_face.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index d3985d40..6084ef61 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -557,6 +557,10 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { if (game_state.curr_screen == SCREEN_TITLE) change_difficulty(state); break; + case EVENT_SINGLE_TAP: + case EVENT_DOUBLE_TAP: + if (state->difficulty > DIFF_HARD) break; // Don't do this on fuel modes + //fall through case EVENT_LIGHT_BUTTON_DOWN: case EVENT_ALARM_BUTTON_DOWN: if (game_state.curr_screen == SCREEN_PLAYING && game_state.jump_state == NOT_JUMPING){ From 95df9a66838ae2ae3dd6dc492a0bd3ffb05a18ad Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Tue, 19 Aug 2025 20:16:43 -0400 Subject: [PATCH 06/22] Enable tap functionality --- watch-faces/complication/endless_runner_face.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 6084ef61..c749cc9d 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -525,6 +525,7 @@ void endless_runner_face_activate(void *context) { ball_arr_seg = is_custom_lcd ? custom_ball_arr_seg : classic_ball_arr_seg; obstacle_arr_com = is_custom_lcd ? custom_obstacle_arr_com : classic_obstacle_arr_com; obstacle_arr_seg = is_custom_lcd ? custom_obstacle_arr_seg : classic_obstacle_arr_seg; + movement_enable_tap_detection_if_available(); } bool endless_runner_face_loop(movement_event_t event, void *context) { @@ -588,5 +589,6 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { void endless_runner_face_resign(void *context) { (void) context; + movement_disable_tap_detection_if_available(); } From 7b4f491db6d62ec6c17edcc67e9edf6e16577bf4 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Tue, 19 Aug 2025 20:18:20 -0400 Subject: [PATCH 07/22] Able to start runner with a tap --- watch-faces/complication/endless_runner_face.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index c749cc9d..1f245e8d 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -547,6 +547,10 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { break; } break; + case EVENT_SINGLE_TAP: + case EVENT_DOUBLE_TAP: + if (state->difficulty > DIFF_HARD) break; // Don't do this on fuel modes + //fall through case EVENT_LIGHT_BUTTON_UP: case EVENT_ALARM_BUTTON_UP: if (game_state.curr_screen == SCREEN_TITLE) From 0e13674a79e717cbf6eeb7eb5ae17beceb38e2f3 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Tue, 19 Aug 2025 21:47:51 -0400 Subject: [PATCH 08/22] Fixed duplicate cases --- watch-faces/complication/endless_runner_face.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 1f245e8d..7f6837ba 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -547,10 +547,6 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { break; } break; - case EVENT_SINGLE_TAP: - case EVENT_DOUBLE_TAP: - if (state->difficulty > DIFF_HARD) break; // Don't do this on fuel modes - //fall through case EVENT_LIGHT_BUTTON_UP: case EVENT_ALARM_BUTTON_UP: if (game_state.curr_screen == SCREEN_TITLE) @@ -565,6 +561,15 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { case EVENT_SINGLE_TAP: case EVENT_DOUBLE_TAP: if (state->difficulty > DIFF_HARD) break; // Don't do this on fuel modes + // Allow starting a new game by tapping. + if (game_state.curr_screen == SCREEN_TITLE) { + begin_playing(state); + break; + } + else if (game_state.curr_screen == SCREEN_LOSE) { + display_title(state); + break; + } //fall through case EVENT_LIGHT_BUTTON_DOWN: case EVENT_ALARM_BUTTON_DOWN: From c0c78411df515cf44bc68a6efb4b29977248fe6f Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 23 Aug 2025 07:37:24 -0400 Subject: [PATCH 09/22] Tap enabe and disable added; fixed soundOn icon --- .../complication/endless_runner_face.c | 31 +++++++++++++++---- .../complication/endless_runner_face.h | 5 ++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 7f6837ba..390f54c7 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -305,6 +305,20 @@ static void toggle_sound(endless_runner_state_t *state) { } } +static void enable_tap_control(endless_runner_state_t *state) { + if (!state->tap_control_on) { + movement_enable_tap_detection_if_available(); + state->tap_control_on = true; + } +} + +static void disable_tap_control(endless_runner_state_t *state) { + if (state->tap_control_on) { + movement_disable_tap_detection_if_available(); + state->tap_control_on = false; + } +} + static void display_title(endless_runner_state_t *state) { uint16_t hi_score = state -> hi_score; uint8_t difficulty = state -> difficulty; @@ -325,6 +339,7 @@ static void display_title(endless_runner_state_t *state) { watch_display_text(WATCH_POSITION_BOTTOM, buf); } display_difficulty(difficulty); + if (state -> soundOn) watch_set_indicator(WATCH_INDICATOR_BELL); } static void display_time(watch_date_time_t date_time, bool clock_mode_24h) { @@ -532,8 +547,8 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { endless_runner_state_t *state = (endless_runner_state_t *)context; switch (event.event_type) { case EVENT_ACTIVATE: + disable_tap_control(state); check_and_reset_hi_score(state); - if (state -> soundOn) watch_set_indicator(WATCH_INDICATOR_BELL); display_title(state); break; case EVENT_TICK: @@ -549,10 +564,13 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { break; case EVENT_LIGHT_BUTTON_UP: case EVENT_ALARM_BUTTON_UP: - if (game_state.curr_screen == SCREEN_TITLE) + if (game_state.curr_screen == SCREEN_TITLE) { + enable_tap_control(state); begin_playing(state); - else if (game_state.curr_screen == SCREEN_LOSE) + } + else if (game_state.curr_screen == SCREEN_LOSE) { display_title(state); + } break; case EVENT_LIGHT_LONG_PRESS: if (game_state.curr_screen == SCREEN_TITLE) @@ -580,10 +598,11 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { } break; case EVENT_ALARM_LONG_PRESS: - if (game_state.curr_screen != SCREEN_PLAYING) + if (game_state.curr_screen == SCREEN_TITLE) toggle_sound(state); break; case EVENT_TIMEOUT: + disable_tap_control(state); if (game_state.curr_screen != SCREEN_TITLE) display_title(state); break; @@ -597,7 +616,7 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { } void endless_runner_face_resign(void *context) { - (void) context; - movement_disable_tap_detection_if_available(); + endless_runner_state_t *state = (endless_runner_state_t *)context; + disable_tap_control(state); } diff --git a/watch-faces/complication/endless_runner_face.h b/watch-faces/complication/endless_runner_face.h index 3cfa6814..3a17a611 100644 --- a/watch-faces/complication/endless_runner_face.h +++ b/watch-faces/complication/endless_runner_face.h @@ -33,6 +33,8 @@ This is a basic endless-runner, like the [Chrome Dino game](https://en.wikipedia.org/wiki/Dinosaur_Game). On the title screen, you can select a difficulty by long-pressing LIGHT or toggle sound by long-pressing ALARM. LED or ALARM are used to jump. + If the accelerometer is installed, you can tap the screen to jump and move through the menus after using the + buttons to go into the first game. High-score is displayed on the top-right on the title screen. During a game, the current score is displayed. */ @@ -42,7 +44,8 @@ typedef struct { uint8_t month_last_hi_score : 4; uint8_t year_last_hi_score : 6; uint8_t soundOn : 1; - /* 24 bits, likely aligned to 32 bits = 4 bytes */ + uint8_t tap_control_on : 1; + uint8_t unused : 7; } endless_runner_state_t; void endless_runner_face_setup(uint8_t watch_face_index, void ** context_ptr); From a769b2968775cae34b3fba875ea101e4d4fe7a92 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 23 Aug 2025 07:55:12 -0400 Subject: [PATCH 10/22] Fixed up start chime --- watch-faces/complication/endless_runner_face.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 390f54c7..4588c2a3 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -369,10 +369,18 @@ static void display_time(watch_date_time_t date_time, bool clock_mode_24h) { previous_date_time.reg = date_time.reg; } +int8_t start_tune[] = { + BUZZER_NOTE_C5, 15, + BUZZER_NOTE_E5, 15, + BUZZER_NOTE_G5, 15, + 0 +}; + static void begin_playing(endless_runner_state_t *state) { uint8_t difficulty = state -> difficulty; game_state.curr_screen = SCREEN_PLAYING; watch_clear_colon(); + watch_clear_indicator(WATCH_INDICATOR_BELL); movement_request_tick_frequency((state -> difficulty == DIFF_BABY) ? FREQ_SLOW : FREQ); if (game_state.fuel_mode) { watch_clear_display(); @@ -390,9 +398,7 @@ static void begin_playing(endless_runner_state_t *state) { display_ball(game_state.jump_state != NOT_JUMPING); display_score( game_state.curr_score); if (state -> soundOn){ - watch_buzzer_play_note(BUZZER_NOTE_C5, 200); - watch_buzzer_play_note(BUZZER_NOTE_E5, 200); - watch_buzzer_play_note(BUZZER_NOTE_G5, 200); + watch_buzzer_play_sequence(start_tune, NULL); } } From 3dada3e9b5d551612658ad23ea57822be4b153cc Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 23 Aug 2025 08:04:09 -0400 Subject: [PATCH 11/22] Referenicng local time function --- watch-faces/complication/endless_runner_face.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 4588c2a3..d4aebf69 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -261,7 +261,7 @@ static void display_fuel(uint8_t subsecond, uint8_t difficulty) { static void check_and_reset_hi_score(endless_runner_state_t *state) { // Resets the hi score at the beginning of each month. - watch_date_time_t date_time = watch_rtc_get_date_time(); + watch_date_time_t date_time = movement_get_local_date_time(); if ((state -> year_last_hi_score != date_time.unit.year) || (state -> month_last_hi_score != date_time.unit.month)) { @@ -536,6 +536,7 @@ void endless_runner_face_setup(uint8_t watch_face_index, void ** context_ptr) { memset(*context_ptr, 0, sizeof(endless_runner_state_t)); endless_runner_state_t *state = (endless_runner_state_t *)*context_ptr; state->difficulty = DIFF_NORM; + state->tap_control_on = false; } } @@ -576,7 +577,7 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { } else if (game_state.curr_screen == SCREEN_LOSE) { display_title(state); - } + } break; case EVENT_LIGHT_LONG_PRESS: if (game_state.curr_screen == SCREEN_TITLE) @@ -625,4 +626,3 @@ void endless_runner_face_resign(void *context) { endless_runner_state_t *state = (endless_runner_state_t *)context; disable_tap_control(state); } - From a71d48d5d3681259b5f00a5967e9be8113175c5f Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 23 Aug 2025 09:41:42 -0400 Subject: [PATCH 12/22] Corrected obstacle on classic face --- watch-faces/complication/endless_runner_face.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index d4aebf69..aff3fd69 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -85,7 +85,7 @@ int8_t custom_ball_arr_com[] = {2, 1, 1, 0, 3, 3, 2}; int8_t custom_ball_arr_seg[] = {15, 15, 14, 15, 14, 15, 14}; // obstacle 0-11 -int8_t classic_obstacle_arr_com[] = {0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0}; +int8_t classic_obstacle_arr_com[] = {0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1}; int8_t classic_obstacle_arr_seg[] = {18, 19, 20, 21, 22, 23, 0, 1, 2, 4, 5, 6}; int8_t custom_obstacle_arr_com[] = {1, 1, 1, 1, 1, 0, 1, 0, 3, 0, 0, 2}; int8_t custom_obstacle_arr_seg[] = {22, 16, 15, 14, 1, 2, 3, 4, 4, 5, 6, 7}; From ba98aab4bd3dd73ae2d7aa23412826727e874087 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 27 Aug 2025 08:06:52 -0400 Subject: [PATCH 13/22] Blink colon on showing time in custom display --- watch-faces/complication/endless_runner_face.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index aff3fd69..0849c27b 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -346,6 +346,9 @@ static void display_time(watch_date_time_t date_time, bool clock_mode_24h) { static watch_date_time_t previous_date_time; char buf[6 + 1]; + if (!watch_sleep_animation_is_running()) { + watch_start_indicator_blink_if_possible(WATCH_INDICATOR_COLON, 500); + } // If the hour needs updating or it's the first time displaying the time if ((game_state.curr_screen != SCREEN_TIME) || (date_time.unit.hour != previous_date_time.unit.hour)) { uint8_t hour = date_time.unit.hour; @@ -358,7 +361,7 @@ static void display_time(watch_date_time_t date_time, bool clock_mode_24h) { if (hour == 0) hour = 12; } watch_set_colon(); - sprintf( buf, "%2d%02d ", hour, date_time.unit.minute); + sprintf( buf, movement_clock_mode_24h() == MOVEMENT_CLOCK_MODE_024H ? "%02d%02d " : "%2d%02d ", hour, date_time.unit.minute); watch_display_text(WATCH_POSITION_BOTTOM, buf); } // If only the minute need updating From 61b65c1d1768692592ca304f68a9fa4e0c69b773 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 27 Aug 2025 08:45:16 -0400 Subject: [PATCH 14/22] MOVEMENT_CLOCK_MODE_12H works on the time display --- .../complication/endless_runner_face.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 0849c27b..6fb9b9c5 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -342,26 +342,27 @@ static void display_title(endless_runner_state_t *state) { if (state -> soundOn) watch_set_indicator(WATCH_INDICATOR_BELL); } -static void display_time(watch_date_time_t date_time, bool clock_mode_24h) { +static void display_time(void) { static watch_date_time_t previous_date_time; + watch_date_time_t date_time = movement_get_local_date_time(); + movement_clock_mode_t clock_mode_24h = movement_clock_mode_24h(); char buf[6 + 1]; - if (!watch_sleep_animation_is_running()) { - watch_start_indicator_blink_if_possible(WATCH_INDICATOR_COLON, 500); - } // If the hour needs updating or it's the first time displaying the time if ((game_state.curr_screen != SCREEN_TIME) || (date_time.unit.hour != previous_date_time.unit.hour)) { uint8_t hour = date_time.unit.hour; game_state.curr_screen = SCREEN_TIME; - - if (clock_mode_24h) watch_set_indicator(WATCH_INDICATOR_24H); + if (!watch_sleep_animation_is_running()) { + watch_set_colon(); + watch_start_indicator_blink_if_possible(WATCH_INDICATOR_COLON, 500); + } + if (clock_mode_24h != MOVEMENT_CLOCK_MODE_12H) watch_set_indicator(WATCH_INDICATOR_24H); else { if (hour >= 12) watch_set_indicator(WATCH_INDICATOR_PM); hour %= 12; if (hour == 0) hour = 12; } - watch_set_colon(); - sprintf( buf, movement_clock_mode_24h() == MOVEMENT_CLOCK_MODE_024H ? "%02d%02d " : "%2d%02d ", hour, date_time.unit.minute); + sprintf( buf, clock_mode_24h == MOVEMENT_CLOCK_MODE_024H ? "%02d%02d " : "%2d%02d ", hour, date_time.unit.minute); watch_display_text(WATCH_POSITION_BOTTOM, buf); } // If only the minute need updating @@ -617,7 +618,7 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { display_title(state); break; case EVENT_LOW_ENERGY_UPDATE: - display_time(movement_get_local_date_time(), movement_clock_mode_24h()); + display_time(); break; default: return movement_default_loop_handler(event); From 71d7b4495b5063ff37c52a414b978dc379569468 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 27 Aug 2025 09:03:31 -0400 Subject: [PATCH 15/22] Stop blink animation when leaving sleep mode --- watch-faces/complication/endless_runner_face.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 6fb9b9c5..f43a831b 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -551,7 +551,6 @@ void endless_runner_face_activate(void *context) { ball_arr_seg = is_custom_lcd ? custom_ball_arr_seg : classic_ball_arr_seg; obstacle_arr_com = is_custom_lcd ? custom_obstacle_arr_com : classic_obstacle_arr_com; obstacle_arr_seg = is_custom_lcd ? custom_obstacle_arr_seg : classic_obstacle_arr_seg; - movement_enable_tap_detection_if_available(); } bool endless_runner_face_loop(movement_event_t event, void *context) { @@ -559,6 +558,7 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { switch (event.event_type) { case EVENT_ACTIVATE: disable_tap_control(state); + clock_stop_tick_tock_animation(); check_and_reset_hi_score(state); display_title(state); break; From 2770b8b924cb46308f17114cdc4c4aebad8a1d3f Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 27 Aug 2025 09:09:44 -0400 Subject: [PATCH 16/22] Fixed proper usage of blinkng --- watch-faces/complication/endless_runner_face.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index f43a831b..a3f7e371 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -558,7 +558,9 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { switch (event.event_type) { case EVENT_ACTIVATE: disable_tap_control(state); - clock_stop_tick_tock_animation(); + if (watch_sleep_animation_is_running()) { + watch_stop_blink(); + } check_and_reset_hi_score(state); display_title(state); break; From db2d5cbf68e3585342ff361e3f277d4a6c9a3bb1 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 27 Aug 2025 17:17:11 -0400 Subject: [PATCH 17/22] Moved sleep animation check into the function rather than the switch statement --- watch-faces/complication/endless_runner_face.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index a3f7e371..a0dc85db 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -551,6 +551,9 @@ void endless_runner_face_activate(void *context) { ball_arr_seg = is_custom_lcd ? custom_ball_arr_seg : classic_ball_arr_seg; obstacle_arr_com = is_custom_lcd ? custom_obstacle_arr_com : classic_obstacle_arr_com; obstacle_arr_seg = is_custom_lcd ? custom_obstacle_arr_seg : classic_obstacle_arr_seg; + if (watch_sleep_animation_is_running()) { + watch_stop_blink(); + } } bool endless_runner_face_loop(movement_event_t event, void *context) { @@ -558,9 +561,6 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { switch (event.event_type) { case EVENT_ACTIVATE: disable_tap_control(state); - if (watch_sleep_animation_is_running()) { - watch_stop_blink(); - } check_and_reset_hi_score(state); display_title(state); break; From d24ebce9da1d38957be37321bffe7cd9e1c03649 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 30 Aug 2025 10:45:06 -0400 Subject: [PATCH 18/22] Added lose_tune --- .../complication/endless_runner_face.c | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index a0dc85db..cd4f7249 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -98,6 +98,20 @@ int8_t *obstacle_arr_seg; static game_state_t game_state; static const uint8_t _num_bits_obst_pattern = sizeof(game_state.obst_pattern) * 8; +int8_t start_tune[] = { + BUZZER_NOTE_C5, 15, + BUZZER_NOTE_E5, 15, + BUZZER_NOTE_G5, 15, + 0 +}; + +int8_t lose_tune[] = { + BUZZER_NOTE_D3, 10, + BUZZER_NOTE_C3SHARP_D3FLAT, 10, + BUZZER_NOTE_C3, 10, + 0 +}; + static void print_binary(uint32_t value, int bits) { #if __EMSCRIPTEN__ for (int i = bits - 1; i >= 0; i--) { @@ -373,13 +387,6 @@ static void display_time(void) { previous_date_time.reg = date_time.reg; } -int8_t start_tune[] = { - BUZZER_NOTE_C5, 15, - BUZZER_NOTE_E5, 15, - BUZZER_NOTE_G5, 15, - 0 -}; - static void begin_playing(endless_runner_state_t *state) { uint8_t difficulty = state -> difficulty; game_state.curr_screen = SCREEN_PLAYING; @@ -412,7 +419,7 @@ static void display_lose_screen(endless_runner_state_t *state) { watch_clear_display(); watch_display_text(WATCH_POSITION_BOTTOM, " LOSE "); if (state -> soundOn) - watch_buzzer_play_note(BUZZER_NOTE_A1, 600); + watch_buzzer_play_sequence(lose_tune, NULL); else delay_ms(600); } From 8fbb2d48b0686f33a95dcb4eed584fbca7f3ba9d Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 30 Aug 2025 10:03:40 -0400 Subject: [PATCH 19/22] Added title screen to endless runner --- .../complication/endless_runner_face.c | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index cd4f7249..9f951d31 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -35,6 +35,7 @@ typedef enum { typedef enum { SCREEN_TITLE = 0, + SCREEN_SCORE, SCREEN_PLAYING, SCREEN_LOSE, SCREEN_TIME, @@ -334,11 +335,19 @@ static void disable_tap_control(endless_runner_state_t *state) { } static void display_title(endless_runner_state_t *state) { + game_state.curr_screen = SCREEN_TITLE; + watch_clear_colon(); + watch_display_text_with_fallback(WATCH_POSITION_TOP, "ENdLS", "ER "); + watch_display_text(WATCH_POSITION_BOTTOM, "RUNNER"); + if (state -> soundOn) watch_set_indicator(WATCH_INDICATOR_BELL); +} + +static void display_score_screen(endless_runner_state_t *state) { uint16_t hi_score = state -> hi_score; uint8_t difficulty = state -> difficulty; bool sound_on = state -> soundOn; - game_state.curr_screen = SCREEN_TITLE; memset(&game_state, 0, sizeof(game_state)); + game_state.curr_screen = SCREEN_SCORE; game_state.sec_before_moves = 1; // The first obstacles will all be 0s, which is about an extra second of delay. if (sound_on) game_state.sec_before_moves--; // Start chime is about 1 second watch_set_colon(); @@ -353,7 +362,7 @@ static void display_title(endless_runner_state_t *state) { watch_display_text(WATCH_POSITION_BOTTOM, buf); } display_difficulty(difficulty); - if (state -> soundOn) watch_set_indicator(WATCH_INDICATOR_BELL); + if (sound_on) watch_set_indicator(WATCH_INDICATOR_BELL); } static void display_time(void) { @@ -575,6 +584,7 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { switch (game_state.curr_screen) { case SCREEN_TITLE: + case SCREEN_SCORE: case SCREEN_LOSE: break; default: @@ -584,28 +594,28 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { break; case EVENT_LIGHT_BUTTON_UP: case EVENT_ALARM_BUTTON_UP: - if (game_state.curr_screen == SCREEN_TITLE) { + if (game_state.curr_screen == SCREEN_SCORE) { enable_tap_control(state); begin_playing(state); } - else if (game_state.curr_screen == SCREEN_LOSE) { - display_title(state); + else if (game_state.curr_screen == SCREEN_TITLE || game_state.curr_screen == SCREEN_LOSE) { + display_score_screen(state); } break; case EVENT_LIGHT_LONG_PRESS: - if (game_state.curr_screen == SCREEN_TITLE) + if (game_state.curr_screen == SCREEN_SCORE) change_difficulty(state); break; case EVENT_SINGLE_TAP: case EVENT_DOUBLE_TAP: if (state->difficulty > DIFF_HARD) break; // Don't do this on fuel modes // Allow starting a new game by tapping. - if (game_state.curr_screen == SCREEN_TITLE) { + if (game_state.curr_screen == SCREEN_SCORE) { begin_playing(state); break; } else if (game_state.curr_screen == SCREEN_LOSE) { - display_title(state); + display_score_screen(state); break; } //fall through @@ -618,13 +628,13 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { } break; case EVENT_ALARM_LONG_PRESS: - if (game_state.curr_screen == SCREEN_TITLE) + if (game_state.curr_screen == SCREEN_TITLE || game_state.curr_screen == SCREEN_SCORE) toggle_sound(state); break; case EVENT_TIMEOUT: disable_tap_control(state); - if (game_state.curr_screen != SCREEN_TITLE) - display_title(state); + if (game_state.curr_screen != SCREEN_SCORE) + display_score_screen(state); break; case EVENT_LOW_ENERGY_UPDATE: display_time(); From 8c5921538502c86b88e81503a6676d123407943b Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 31 Aug 2025 09:35:36 -0400 Subject: [PATCH 20/22] Better enterring of time mode and sound indicator during game --- .../complication/endless_runner_face.c | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 9f951d31..4b22262f 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -309,14 +309,19 @@ static void change_difficulty(endless_runner_state_t *state) { } } +static void display_sound_indicator(bool soundOn) { + if (soundOn){ + watch_set_indicator(WATCH_INDICATOR_BELL); + } else { + watch_clear_indicator(WATCH_INDICATOR_BELL); + } +} + static void toggle_sound(endless_runner_state_t *state) { state -> soundOn = !state -> soundOn; + display_sound_indicator(state -> soundOn); if (state -> soundOn){ watch_buzzer_play_note(BUZZER_NOTE_C5, 30); - watch_set_indicator(WATCH_INDICATOR_BELL); - } - else { - watch_clear_indicator(WATCH_INDICATOR_BELL); } } @@ -339,7 +344,7 @@ static void display_title(endless_runner_state_t *state) { watch_clear_colon(); watch_display_text_with_fallback(WATCH_POSITION_TOP, "ENdLS", "ER "); watch_display_text(WATCH_POSITION_BOTTOM, "RUNNER"); - if (state -> soundOn) watch_set_indicator(WATCH_INDICATOR_BELL); + display_sound_indicator(state -> soundOn); } static void display_score_screen(endless_runner_state_t *state) { @@ -351,8 +356,7 @@ static void display_score_screen(endless_runner_state_t *state) { game_state.sec_before_moves = 1; // The first obstacles will all be 0s, which is about an extra second of delay. if (sound_on) game_state.sec_before_moves--; // Start chime is about 1 second watch_set_colon(); - watch_display_text_with_fallback(WATCH_POSITION_TOP, "RUN", "ER"); - watch_display_text(WATCH_POSITION_TOP_RIGHT, " "); + watch_display_text_with_fallback(WATCH_POSITION_TOP, "RUN ", "ER "); if (hi_score > MAX_HI_SCORE) { watch_display_text(WATCH_POSITION_BOTTOM, "HS --"); } @@ -362,7 +366,7 @@ static void display_score_screen(endless_runner_state_t *state) { watch_display_text(WATCH_POSITION_BOTTOM, buf); } display_difficulty(difficulty); - if (sound_on) watch_set_indicator(WATCH_INDICATOR_BELL); + display_sound_indicator(sound_on); } static void display_time(void) { @@ -400,7 +404,7 @@ static void begin_playing(endless_runner_state_t *state) { uint8_t difficulty = state -> difficulty; game_state.curr_screen = SCREEN_PLAYING; watch_clear_colon(); - watch_clear_indicator(WATCH_INDICATOR_BELL); + display_sound_indicator(state -> soundOn); movement_request_tick_frequency((state -> difficulty == DIFF_BABY) ? FREQ_SLOW : FREQ); if (game_state.fuel_mode) { watch_clear_display(); @@ -586,6 +590,7 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { case SCREEN_TITLE: case SCREEN_SCORE: case SCREEN_LOSE: + case SCREEN_TIME: break; default: update_game(state, event.subsecond); @@ -637,6 +642,11 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { display_score_screen(state); break; case EVENT_LOW_ENERGY_UPDATE: + if (game_state.curr_screen != SCREEN_TIME) { + watch_display_text_with_fallback(WATCH_POSITION_TOP, "RUN ", "ER "); + display_sound_indicator(state -> soundOn); + display_difficulty(state->difficulty); + } display_time(); break; default: From e6b8be467630137d9890f0c096f00c869a8f1d24 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 31 Aug 2025 09:44:46 -0400 Subject: [PATCH 21/22] Lose chime plays fully when sound is on --- watch-faces/complication/endless_runner_face.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 4b22262f..5d479b9a 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -431,10 +431,10 @@ static void display_lose_screen(endless_runner_state_t *state) { game_state.curr_score = 0; watch_clear_display(); watch_display_text(WATCH_POSITION_BOTTOM, " LOSE "); - if (state -> soundOn) + if (state -> soundOn) { watch_buzzer_play_sequence(lose_tune, NULL); - else delay_ms(600); + } } static void display_obstacle(bool obstacle, int grid_loc, endless_runner_state_t *state) { From 2bce9bba65e1bb75b0b94e2961064cce31c9a37d Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 31 Aug 2025 16:28:59 -0400 Subject: [PATCH 22/22] Enable endless runner tapping right after leaving the title screen --- watch-faces/complication/endless_runner_face.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/watch-faces/complication/endless_runner_face.c b/watch-faces/complication/endless_runner_face.c index 5d479b9a..8a4b7a3b 100644 --- a/watch-faces/complication/endless_runner_face.c +++ b/watch-faces/complication/endless_runner_face.c @@ -599,12 +599,18 @@ bool endless_runner_face_loop(movement_event_t event, void *context) { break; case EVENT_LIGHT_BUTTON_UP: case EVENT_ALARM_BUTTON_UP: - if (game_state.curr_screen == SCREEN_SCORE) { - enable_tap_control(state); - begin_playing(state); - } - else if (game_state.curr_screen == SCREEN_TITLE || game_state.curr_screen == SCREEN_LOSE) { - display_score_screen(state); + switch (game_state.curr_screen) { + case SCREEN_SCORE: + enable_tap_control(state); + begin_playing(state); + break; + case SCREEN_TITLE: + enable_tap_control(state); + // fall through + case SCREEN_TIME: + case SCREEN_LOSE: + watch_clear_display(); + display_score_screen(state); } break; case EVENT_LIGHT_LONG_PRESS: