laser_tag_app.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #include "laser_tag_app.h"
  2. #include "laser_tag_view.h"
  3. #include "infrared_controller.h"
  4. #include "game_state.h"
  5. #include <furi.h>
  6. #include <gui/gui.h>
  7. #include <gui/view.h>
  8. #include <input/input.h>
  9. #include <notification/notification.h>
  10. #include <notification/notification_messages.h>
  11. #define TAG "LaserTag"
  12. struct LaserTagApp {
  13. Gui* gui;
  14. ViewPort* view_port;
  15. LaserTagView* view;
  16. FuriMessageQueue* event_queue;
  17. FuriTimer* timer;
  18. NotificationApp* notifications;
  19. InfraredController* ir_controller;
  20. GameState* game_state;
  21. LaserTagState state;
  22. };
  23. const NotificationSequence sequence_vibro_1 = {
  24. &message_vibro_on,
  25. &message_vibro_off,
  26. NULL
  27. };
  28. static void laser_tag_app_timer_callback(void* context) {
  29. furi_assert(context);
  30. LaserTagApp* app = context;
  31. game_state_update_time(app->game_state, 1);
  32. laser_tag_view_update(app->view, app->game_state);
  33. }
  34. static void laser_tag_app_input_callback(InputEvent* input_event, void* context) {
  35. furi_assert(context);
  36. LaserTagApp* app = context;
  37. furi_message_queue_put(app->event_queue, input_event, FuriWaitForever);
  38. }
  39. static void laser_tag_app_draw_callback(Canvas* canvas, void* context) {
  40. furi_assert(context);
  41. LaserTagApp* app = context;
  42. if(app->state == LaserTagStateTeamSelect) {
  43. canvas_clear(canvas);
  44. canvas_set_font(canvas, FontPrimary);
  45. canvas_draw_str(canvas, 32, 32, "Select Team:");
  46. canvas_set_font(canvas, FontSecondary);
  47. canvas_draw_str(canvas, 32, 48, "LEFT: Red RIGHT: Blue");
  48. } else {
  49. laser_tag_view_draw(laser_tag_view_get_view(app->view), canvas);
  50. }
  51. }
  52. LaserTagApp* laser_tag_app_alloc() {
  53. LaserTagApp* app = malloc(sizeof(LaserTagApp));
  54. app->gui = furi_record_open(RECORD_GUI);
  55. app->view_port = view_port_alloc();
  56. app->view = laser_tag_view_alloc();
  57. app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
  58. app->notifications = furi_record_open(RECORD_NOTIFICATION);
  59. app->ir_controller = infrared_controller_alloc();
  60. app->game_state = game_state_alloc();
  61. app->state = LaserTagStateTeamSelect;
  62. view_port_draw_callback_set(app->view_port, laser_tag_app_draw_callback, app);
  63. view_port_input_callback_set(app->view_port, laser_tag_app_input_callback, app);
  64. gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
  65. app->timer = furi_timer_alloc(laser_tag_app_timer_callback, FuriTimerTypePeriodic, app);
  66. furi_timer_start(app->timer, furi_kernel_get_tick_frequency());
  67. return app;
  68. }
  69. void laser_tag_app_free(LaserTagApp* app) {
  70. furi_assert(app);
  71. furi_timer_free(app->timer);
  72. view_port_enabled_set(app->view_port, false);
  73. gui_remove_view_port(app->gui, app->view_port);
  74. view_port_free(app->view_port);
  75. laser_tag_view_free(app->view);
  76. furi_message_queue_free(app->event_queue);
  77. infrared_controller_free(app->ir_controller);
  78. game_state_free(app->game_state);
  79. furi_record_close(RECORD_GUI);
  80. furi_record_close(RECORD_NOTIFICATION);
  81. free(app);
  82. }
  83. void laser_tag_app_fire(LaserTagApp* app) {
  84. infrared_controller_send(app->ir_controller);
  85. game_state_decrease_ammo(app->game_state, 1);
  86. notification_message(app->notifications, &sequence_blink_blue_100);
  87. }
  88. void laser_tag_app_handle_hit(LaserTagApp* app) {
  89. game_state_decrease_health(app->game_state, 10);
  90. notification_message(app->notifications, &sequence_vibro_1);
  91. }
  92. void laser_tag_app_enter_game_state(LaserTagApp* app) {
  93. app->state = LaserTagStateGame;
  94. game_state_reset(app->game_state);
  95. laser_tag_view_update(app->view, app->game_state);
  96. }
  97. int32_t laser_tag_app(void* p) {
  98. UNUSED(p);
  99. LaserTagApp* app = laser_tag_app_alloc();
  100. InputEvent event;
  101. bool running = true;
  102. while(running) {
  103. FuriStatus status = furi_message_queue_get(app->event_queue, &event, 100);
  104. if(status == FuriStatusOk) {
  105. if(event.type == InputTypePress) {
  106. if(app->state == LaserTagStateTeamSelect) {
  107. switch(event.key) {
  108. case InputKeyLeft:
  109. infrared_controller_set_team(app->ir_controller, TeamRed);
  110. game_state_set_team(app->game_state, TeamRed);
  111. laser_tag_app_enter_game_state(app);
  112. break;
  113. case InputKeyRight:
  114. infrared_controller_set_team(app->ir_controller, TeamBlue);
  115. game_state_set_team(app->game_state, TeamBlue);
  116. laser_tag_app_enter_game_state(app);
  117. break;
  118. default:
  119. break;
  120. }
  121. } else {
  122. switch(event.key) {
  123. case InputKeyBack:
  124. running = false;
  125. break;
  126. case InputKeyOk:
  127. laser_tag_app_fire(app);
  128. break;
  129. default:
  130. break;
  131. }
  132. }
  133. }
  134. }
  135. if(app->state == LaserTagStateGame) {
  136. if(infrared_controller_receive(app->ir_controller)) {
  137. laser_tag_app_handle_hit(app);
  138. }
  139. if(game_state_is_game_over(app->game_state)) {
  140. notification_message(app->notifications, &sequence_error);
  141. running = false;
  142. }
  143. laser_tag_view_update(app->view, app->game_state);
  144. }
  145. view_port_update(app->view_port);
  146. }
  147. laser_tag_app_free(app);
  148. return 0;
  149. }