#include "apps.h" #include "os_gfx.h" #include "os_status.h" #include #include #define GROUND_Y 34 typedef enum { GAME_STATE_READY, GAME_STATE_PLAYING, GAME_STATE_OVER } game_state_t; static game_state_t s_game_state = GAME_STATE_READY; static int16_t s_player_y = GROUND_Y; static int16_t s_player_vy = 0; static bool s_is_jumping = false; static int16_t s_obs_x = 72; static int16_t s_obs_h = 6; static uint16_t s_score = 0; static uint16_t s_high_score = 0; static void game_reset(void) { s_player_y = GROUND_Y; s_player_vy = 0; s_is_jumping = false; s_obs_x = 72; s_obs_h = 5 + (rand() % 4); s_score = 0; } static void game_init(void) { s_game_state = GAME_STATE_READY; s_high_score = 0; game_reset(); } static void game_enter(void) { s_game_state = GAME_STATE_READY; game_reset(); } static void game_update(uint32_t delta_ms) { sys_gfx_draw_line(0, GROUND_Y + 1, OLED_WIDTH - 1, GROUND_Y + 1, COLOR_WHITE); if (s_game_state == GAME_STATE_READY) { sys_gfx_draw_str_5x7(10, 8, "TINY JUMP", COLOR_WHITE); sys_gfx_draw_str_3x5(8, 20, "CLICK TO START", COLOR_WHITE); sys_gfx_draw_action_bar("C:JUMP", "H:HOME"); sys_gfx_fill_rect(8, GROUND_Y - 5, 5, 5, COLOR_WHITE); return; } if (s_game_state == GAME_STATE_PLAYING) { if (s_is_jumping) { s_player_y += s_player_vy; s_player_vy += 1; if (s_player_y >= GROUND_Y) { s_player_y = GROUND_Y; s_player_vy = 0; s_is_jumping = false; } } s_obs_x -= 3; if (s_obs_x < -4) { s_obs_x = 72 + (rand() % 16); s_obs_h = 5 + (rand() % 5); s_score++; if (s_score > s_high_score) s_high_score = s_score; } if (s_obs_x <= 13 && (s_obs_x + 3) >= 8) { if ((s_player_y - 1) >= (GROUND_Y - s_obs_h + 1)) { s_game_state = GAME_STATE_OVER; sys_gfx_show_toast("GAME OVER", 800); } } sys_gfx_fill_rect(8, s_player_y - 5, 5, 5, COLOR_WHITE); sys_gfx_fill_rect(s_obs_x, GROUND_Y - s_obs_h + 1, 3, s_obs_h, COLOR_WHITE); char score_str[12]; snprintf(score_str, sizeof(score_str), "SC:%u", s_score); sys_gfx_draw_str_3x5(45, 1, score_str, COLOR_WHITE); } else if (s_game_state == GAME_STATE_OVER) { sys_gfx_draw_str_5x7(12, 6, "GAME OVER", COLOR_WHITE); char buf[16]; snprintf(buf, sizeof(buf), "SCORE: %u", s_score); sys_gfx_draw_str_3x5(16, 17, buf, COLOR_WHITE); snprintf(buf, sizeof(buf), "BEST: %u", s_high_score); sys_gfx_draw_str_3x5(16, 24, buf, COLOR_WHITE); sys_gfx_draw_action_bar("C:RESTART", "H:HOME"); } } static void game_handle_input(input_action_t action) { if (action == INPUT_ACTION_CLICK) { if (s_game_state == GAME_STATE_READY) { s_game_state = GAME_STATE_PLAYING; game_reset(); } else if (s_game_state == GAME_STATE_PLAYING) { if (!s_is_jumping) { s_is_jumping = true; s_player_vy = -5; } } else if (s_game_state == GAME_STATE_OVER) { s_game_state = GAME_STATE_PLAYING; game_reset(); } } } static void game_exit(void) { } const sys_app_t g_app_game = { .id = "game", .name = "Tiny Jump", .init = game_init, .enter = game_enter, .update = game_update, .handle_input = game_handle_input, .exit = game_exit, };