jetpack.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include <stdlib.h>
  2. #include <furi.h>
  3. #include <gui/gui.h>
  4. #include <gui/icon_animation.h>
  5. #include <input/input.h>
  6. #define TAG "Jetpack Joyride"
  7. typedef enum {
  8. GameStateLife,
  9. GameStateGameOver,
  10. } State;
  11. typedef struct {
  12. int points;
  13. State state;
  14. FuriMutex* mutex;
  15. } GameState;
  16. typedef enum {
  17. EventTypeTick,
  18. EventTypeKey,
  19. } EventType;
  20. typedef struct {
  21. EventType type;
  22. InputEvent input;
  23. } GameEvent;
  24. static void jetpack_game_state_init(GameState* const game_state) {
  25. UNUSED(game_state);
  26. }
  27. static void jetpack_game_state_free(GameState* const game_state) {
  28. free(game_state);
  29. }
  30. static void jetpack_game_tick(GameState* const game_state) {
  31. if(game_state->state == GameStateLife) {
  32. // Do jetpack things
  33. }
  34. }
  35. static void jetpack_game_render_callback(Canvas* const canvas, void* ctx) {
  36. furi_assert(ctx);
  37. const GameState* game_state = ctx;
  38. furi_mutex_acquire(game_state->mutex, FuriWaitForever);
  39. canvas_draw_frame(canvas, 0, 0, 128, 64);
  40. if(game_state->state == GameStateLife) {
  41. // Draw scene
  42. }
  43. if(game_state->state == GameStateGameOver) {
  44. // Show highscore
  45. }
  46. furi_mutex_release(game_state->mutex);
  47. }
  48. static void jetpack_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
  49. furi_assert(event_queue);
  50. GameEvent event = {.type = EventTypeKey, .input = *input_event};
  51. furi_message_queue_put(event_queue, &event, FuriWaitForever);
  52. }
  53. static void jetpack_game_update_timer_callback(FuriMessageQueue* event_queue) {
  54. furi_assert(event_queue);
  55. GameEvent event = {.type = EventTypeTick};
  56. furi_message_queue_put(event_queue, &event, 0);
  57. }
  58. int32_t jetpack_game_app(void* p) {
  59. UNUSED(p);
  60. int32_t return_code = 0;
  61. FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(GameEvent));
  62. GameState* game_state = malloc(sizeof(GameState));
  63. jetpack_game_state_init(game_state);
  64. game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  65. if(!game_state->mutex) {
  66. FURI_LOG_E(TAG, "cannot create mutex\r\n");
  67. return_code = 255;
  68. goto free_and_exit;
  69. }
  70. // Set system callbacks
  71. ViewPort* view_port = view_port_alloc();
  72. view_port_draw_callback_set(view_port, jetpack_game_render_callback, game_state);
  73. view_port_input_callback_set(view_port, jetpack_game_input_callback, event_queue);
  74. FuriTimer* timer =
  75. furi_timer_alloc(jetpack_game_update_timer_callback, FuriTimerTypePeriodic, event_queue);
  76. furi_timer_start(timer, furi_kernel_get_tick_frequency() / 25);
  77. // Open GUI and register view_port
  78. Gui* gui = furi_record_open(RECORD_GUI);
  79. gui_add_view_port(gui, view_port, GuiLayerFullscreen);
  80. GameEvent event;
  81. for(bool processing = true; processing;) {
  82. FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
  83. furi_mutex_acquire(game_state->mutex, FuriWaitForever);
  84. if(event_status == FuriStatusOk) {
  85. // press events
  86. if(event.type == EventTypeKey) {
  87. if(event.input.type == InputTypePress) {
  88. switch(event.input.key) {
  89. case InputKeyUp:
  90. break;
  91. case InputKeyDown:
  92. break;
  93. case InputKeyRight:
  94. break;
  95. case InputKeyLeft:
  96. break;
  97. case InputKeyOk:
  98. if(game_state->state == GameStateGameOver) {
  99. jetpack_game_state_init(game_state);
  100. }
  101. if(game_state->state == GameStateLife) {
  102. // Do something
  103. }
  104. break;
  105. case InputKeyBack:
  106. processing = false;
  107. break;
  108. default:
  109. break;
  110. }
  111. }
  112. } else if(event.type == EventTypeTick) {
  113. jetpack_game_tick(game_state);
  114. }
  115. }
  116. view_port_update(view_port);
  117. furi_mutex_release(game_state->mutex);
  118. }
  119. furi_timer_free(timer);
  120. view_port_enabled_set(view_port, false);
  121. gui_remove_view_port(gui, view_port);
  122. furi_record_close(RECORD_GUI);
  123. view_port_free(view_port);
  124. furi_mutex_free(game_state->mutex);
  125. free_and_exit:
  126. jetpack_game_state_free(game_state);
  127. furi_message_queue_free(event_queue);
  128. return return_code;
  129. }