Modified for custom display

This commit is contained in:
David Volovskiy 2025-08-11 21:05:04 -04:00
parent 2a714c7436
commit d9466cb2d1

View File

@ -77,6 +77,23 @@ typedef struct {
uint8_t fuel; uint8_t fuel;
} game_state_t; } 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 game_state_t game_state;
static const uint8_t _num_bits_obst_pattern = sizeof(game_state.obst_pattern) * 8; 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__ #if __EMSCRIPTEN__
for (int i = bits - 1; i >= 0; i--) { for (int i = bits - 1; i >= 0; i--) {
// Print each bit // Print each bit
printf("%lu", (value >> i) & 1); printf("%u", (value >> i) & 1);
// Optional: add a space every 4 bits for readability // Optional: add a space every 4 bits for readability
if (i % 4 == 0 && i != 0) { if (i % 4 == 0 && i != 0) {
printf(" "); printf(" ");
@ -188,22 +205,22 @@ static uint32_t get_random_legal(uint32_t prev_val, uint16_t difficulty) {
static void display_ball(bool jumping) { static void display_ball(bool jumping) {
if (!jumping) { if (!jumping) {
watch_set_pixel(0, 21); watch_set_pixel(ball_arr_com[3], ball_arr_seg[3]);
watch_set_pixel(1, 21); watch_set_pixel(ball_arr_com[2], ball_arr_seg[2]);
watch_set_pixel(0, 20); watch_set_pixel(ball_arr_com[1], ball_arr_seg[1]);
watch_set_pixel(1, 20); watch_set_pixel(ball_arr_com[0], ball_arr_seg[0]);
watch_clear_pixel(1, 17); watch_clear_pixel(ball_arr_com[6], ball_arr_seg[6]);
watch_clear_pixel(2, 20); watch_clear_pixel(ball_arr_com[5], ball_arr_seg[5]);
watch_clear_pixel(2, 21); watch_clear_pixel(ball_arr_com[4], ball_arr_seg[4]);
} }
else { else {
watch_clear_pixel(0, 21); watch_clear_pixel(ball_arr_com[3], ball_arr_seg[3]);
watch_clear_pixel(1, 21); watch_clear_pixel(ball_arr_com[2], ball_arr_seg[2]);
watch_clear_pixel(0, 20); watch_clear_pixel(ball_arr_com[1], ball_arr_seg[1]);
watch_set_pixel(1, 20); watch_set_pixel(ball_arr_com[0], ball_arr_seg[0]);
watch_set_pixel(1, 17); watch_set_pixel(ball_arr_com[6], ball_arr_seg[6]);
watch_set_pixel(2, 20); watch_set_pixel(ball_arr_com[5], ball_arr_seg[5]);
watch_set_pixel(2, 21); 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) { if (game_state.fuel_mode) {
score %= (MAX_DISP_SCORE_FUEL + 1); score %= (MAX_DISP_SCORE_FUEL + 1);
sprintf(buf, "%1d", score); sprintf(buf, "%1d", score);
watch_display_string(buf, 0); watch_display_text(WATCH_POSITION_TOP_LEFT, buf);
} }
else { else {
score %= (MAX_DISP_SCORE + 1); score %= (MAX_DISP_SCORE + 1);
sprintf(buf, "%2d", score); 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) { static void display_fuel(uint8_t subsecond, uint8_t difficulty) {
char buf[4]; char buf[4];
if (difficulty == DIFF_FUEL_1 && game_state.fuel == 0 && subsecond % (FREQ/2) == 0) { 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; return;
} }
sprintf(buf, "%2d", game_state.fuel); 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) { 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) { static void display_difficulty(uint16_t difficulty) {
switch (difficulty) static const char *labels[] = {
{ [DIFF_BABY] = " b",
case DIFF_BABY: [DIFF_EASY] = " E",
watch_display_string(" b", 2); [DIFF_HARD] = " H",
break; [DIFF_FUEL] = " F",
case DIFF_EASY: [DIFF_FUEL_1] = "1F",
watch_display_string(" E", 2); [DIFF_NORM] = " N"
break; };
case DIFF_HARD: watch_display_text(WATCH_POSITION_TOP_RIGHT, labels[difficulty]);
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;
}
game_state.fuel_mode = difficulty >= DIFF_FUEL && difficulty <= DIFF_FUEL_1; 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. 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 if (sound_on) game_state.sec_before_moves--; // Start chime is about 1 second
watch_set_colon(); 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) { if (hi_score > MAX_HI_SCORE) {
watch_display_string("ER HS --", 0); watch_display_text(WATCH_POSITION_BOTTOM, "HS --");
} }
else { else {
char buf[14]; char buf[10];
sprintf(buf, "ER HS%4d", hi_score); sprintf(buf, "HS%4d", hi_score);
watch_display_string(buf, 0); watch_display_text(WATCH_POSITION_BOTTOM, buf);
} }
display_difficulty(difficulty); display_difficulty(difficulty);
} }
@ -337,17 +343,12 @@ static void display_time(watch_date_time_t date_time, bool clock_mode_24h) {
} }
watch_set_colon(); watch_set_colon();
sprintf( buf, "%2d%02d ", hour, date_time.unit.minute); 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 // If only the minute need updating
else if ((date_time.unit.minute / 10) != (previous_date_time.unit.minute / 10)) { else {
sprintf( buf, "%02d ", date_time.unit.minute); sprintf( buf, "%02d", date_time.unit.minute);
watch_display_string(buf, 6); watch_display_text(WATCH_POSITION_MINUTES, buf);
}
// 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);
} }
previous_date_time.reg = date_time.reg; previous_date_time.reg = date_time.reg;
} }
@ -358,14 +359,15 @@ static void begin_playing(endless_runner_state_t *state) {
watch_clear_colon(); watch_clear_colon();
movement_request_tick_frequency((state -> difficulty == DIFF_BABY) ? FREQ_SLOW : FREQ); movement_request_tick_frequency((state -> difficulty == DIFF_BABY) ? FREQ_SLOW : FREQ);
if (game_state.fuel_mode) { if (game_state.fuel_mode) {
watch_display_string(" ", 0); watch_clear_display();
game_state.obst_pattern = get_random_fuel(0); 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 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. 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; if (game_state.fuel < JUMP_FRAMES_FUEL_RECHARGE) game_state.fuel = JUMP_FRAMES_FUEL_RECHARGE;
} }
else { 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.obst_pattern = get_random_legal(0, difficulty);
} }
game_state.jump_state = NOT_JUMPING; 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) { static void display_lose_screen(endless_runner_state_t *state) {
game_state.curr_screen = SCREEN_LOSE; game_state.curr_screen = SCREEN_LOSE;
game_state.curr_score = 0; game_state.curr_score = 0;
watch_display_string(" LOSE ", 0); watch_clear_display();
watch_display_text(WATCH_POSITION_BOTTOM, " LOSE ");
if (state -> soundOn) if (state -> soundOn)
watch_buzzer_play_note(BUZZER_NOTE_A1, 600); watch_buzzer_play_note(BUZZER_NOTE_A1, 600);
else else
@ -395,9 +398,9 @@ static void display_obstacle(bool obstacle, int grid_loc, endless_runner_state_t
case 2: case 2:
game_state.loc_2_on = obstacle; game_state.loc_2_on = obstacle;
if (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) { 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) if (game_state.fuel_mode && prev_obst_pos_two)
add_to_score(state); add_to_score(state);
} }
@ -406,55 +409,20 @@ static void display_obstacle(bool obstacle, int grid_loc, endless_runner_state_t
case 3: case 3:
game_state.loc_3_on = obstacle; game_state.loc_3_on = obstacle;
if (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) 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; break;
case 1: case 1:
if (!game_state.fuel_mode && obstacle) // If an obstacle is here, it means the ball cleared it if (!game_state.fuel_mode && obstacle) // If an obstacle is here, it means the ball cleared it
add_to_score(state); add_to_score(state);
//fall through //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: 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; 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 endless_runner_face_activate(void *context) {
(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) { bool endless_runner_face_loop(movement_event_t event, void *context) {