game.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include "game.h"
  2. /****** Entities: Player ******/
  3. // Forward declaration of player_desc, because it's used in player_spawn function.
  4. static void player_spawn(Level *level, GameManager *manager)
  5. {
  6. Entity *player = level_add_entity(level, &player_desc);
  7. // Set player position.
  8. // Depends on your game logic, it can be done in start entity function, but also can be done here.
  9. entity_pos_set(player, (Vector){WORLD_WIDTH / 2, WORLD_HEIGHT / 2});
  10. // Add collision box to player entity
  11. // Box is centered in player x and y, and it's size is 10x10
  12. entity_collider_add_rect(player, 10, 10);
  13. // Get player context
  14. PlayerContext *player_context = entity_context_get(player);
  15. // Load player sprite
  16. player_context->sprite = game_manager_sprite_load(manager, "player.fxbm");
  17. }
  18. // Modify player_update to track direction
  19. static void player_update(Entity *self, GameManager *manager, void *context)
  20. {
  21. PlayerContext *player = (PlayerContext *)context;
  22. InputState input = game_manager_input_get(manager);
  23. Vector pos = entity_pos_get(self);
  24. // Reset direction each frame
  25. player->dx = 0;
  26. player->dy = 0;
  27. if (input.held & GameKeyUp)
  28. {
  29. pos.y -= 2;
  30. player->dy = -1;
  31. }
  32. if (input.held & GameKeyDown)
  33. {
  34. pos.y += 2;
  35. player->dy = 1;
  36. }
  37. if (input.held & GameKeyLeft)
  38. {
  39. pos.x -= 2;
  40. player->dx = -1;
  41. }
  42. if (input.held & GameKeyRight)
  43. {
  44. pos.x += 2;
  45. player->dx = 1;
  46. }
  47. pos.x = CLAMP(pos.x, WORLD_WIDTH - 5, 5);
  48. pos.y = CLAMP(pos.y, WORLD_HEIGHT - 5, 5);
  49. entity_pos_set(self, pos);
  50. if (input.pressed & GameKeyBack)
  51. {
  52. game_manager_game_stop(manager);
  53. }
  54. }
  55. static void player_render(Entity *self, GameManager *manager, Canvas *canvas, void *context)
  56. {
  57. // Get player context
  58. UNUSED(manager);
  59. PlayerContext *player = context;
  60. // Get player position
  61. Vector pos = entity_pos_get(self);
  62. // Draw background (updates camera_x and camera_y)
  63. draw_background(canvas, pos);
  64. // Draw player sprite relative to camera
  65. canvas_draw_sprite(canvas, player->sprite, pos.x - camera_x - 5, pos.y - camera_y - 5);
  66. }
  67. const EntityDescription player_desc = {
  68. .start = NULL, // called when entity is added to the level
  69. .stop = NULL, // called when entity is removed from the level
  70. .update = player_update, // called every frame
  71. .render = player_render, // called every frame, after update
  72. .collision = NULL, // called when entity collides with another entity
  73. .event = NULL, // called when entity receives an event
  74. .context_size = sizeof(PlayerContext), // size of entity context, will be automatically allocated and freed
  75. };
  76. /****** Level ******/
  77. static void level_alloc(Level *level, GameManager *manager, void *context)
  78. {
  79. UNUSED(manager);
  80. UNUSED(context);
  81. // Add player entity to the level
  82. player_spawn(level, manager);
  83. draw_tree_world(level);
  84. // draw_example_world(level);
  85. }
  86. static const LevelBehaviour level = {
  87. .alloc = level_alloc, // called once, when level allocated
  88. .free = NULL, // called once, when level freed
  89. .start = NULL, // called when level is changed to this level
  90. .stop = NULL, // called when level is changed from this level
  91. .context_size = 0, // size of level context, will be automatically allocated and freed
  92. };
  93. /****** Game ******/
  94. /*
  95. Write here the start code for your game, for example: creating a level and so on.
  96. Game context is allocated (game.context_size) and passed to this function, you can use it to store your game data.
  97. */
  98. static void game_start(GameManager *game_manager, void *ctx)
  99. {
  100. // Do some initialization here, for example you can load score from storage.
  101. // For simplicity, we will just set it to 0.
  102. GameContext *game_context = ctx;
  103. game_context->score = 0;
  104. // Add level to the game
  105. game_manager_add_level(game_manager, &level);
  106. }
  107. /*
  108. Write here the stop code for your game, for example, freeing memory, if it was allocated.
  109. You don't need to free level, sprites or entities, it will be done automatically.
  110. Also, you don't need to free game_context, it will be done automatically, after this function.
  111. */
  112. static void game_stop(void *ctx)
  113. {
  114. UNUSED(ctx);
  115. // GameContext *game_context = ctx;
  116. // Do some deinitialization here, for example you can save score to storage.
  117. // For simplicity, we will just print it.
  118. // FURI_LOG_I("Game", "Your score: %lu", game_context->score);
  119. }
  120. float game_fps_int()
  121. {
  122. if (strcmp(game_fps, "30") == 0)
  123. {
  124. return 30.0;
  125. }
  126. else if (strcmp(game_fps, "60") == 0)
  127. {
  128. return 60.0;
  129. }
  130. else if (strcmp(game_fps, "120") == 0)
  131. {
  132. return 120.0;
  133. }
  134. else if (strcmp(game_fps, "240") == 0)
  135. {
  136. return 240.0;
  137. }
  138. else
  139. {
  140. return 60.0;
  141. }
  142. }
  143. /*
  144. Your game configuration, do not rename this variable, but you can change its content here.
  145. */
  146. const Game game = {
  147. .target_fps = 240, // target fps, game will try to keep this value
  148. .show_fps = false, // show fps counter on the screen
  149. .always_backlight = true, // keep display backlight always on
  150. .start = game_start, // will be called once, when game starts
  151. .stop = game_stop, // will be called once, when game stops
  152. .context_size = sizeof(GameContext), // size of game context
  153. };