player_entity.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright 2025 Ivan Barsukov
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "player_entity.h"
  18. #include "src/engine/game_manager.h"
  19. #include "src/game.h"
  20. #include "level_game.h"
  21. #define PLAYER_SIZE 6
  22. #define PLAYER_SPEED 1
  23. #define PLAYER_INITIAL_X 64
  24. #define PLAYER_INITIAL_Y 32
  25. #define PLAYER_ANIMATION_DURATION 15.0f
  26. Entity*
  27. player_spawn(Level* level, GameManager* manager)
  28. {
  29. Entity* player = level_add_entity(level, &player_description);
  30. // Set position and collider rect
  31. entity_pos_set(player, (Vector){ PLAYER_INITIAL_X, PLAYER_INITIAL_Y });
  32. entity_collider_add_rect(player, PLAYER_SIZE, PLAYER_SIZE);
  33. // Load player sprite
  34. PlayerContext* player_context = entity_context_get(player);
  35. player_context->sprite = game_manager_sprite_load(manager, "player.fxbm");
  36. return player;
  37. }
  38. void
  39. player_respawn(Entity* player)
  40. {
  41. // Set player position.
  42. entity_pos_set(player, (Vector){ PLAYER_INITIAL_X, PLAYER_INITIAL_Y });
  43. // Reset animation
  44. PlayerContext* player_context = entity_context_get(player);
  45. player_context->time = 0.0f;
  46. }
  47. static void
  48. player_update(Entity* self, GameManager* manager, void* _entity_context)
  49. {
  50. // Check pause
  51. Level* level = game_manager_current_level_get(manager);
  52. GameLevelContext* level_context = level_context_get(level);
  53. if (level_context->is_paused) {
  54. return;
  55. }
  56. // Start level animation
  57. PlayerContext* player = _entity_context;
  58. if (player->time < PLAYER_ANIMATION_DURATION) {
  59. player->time += 1.0f;
  60. return;
  61. }
  62. InputState input = game_manager_input_get(manager);
  63. Vector pos = entity_pos_get(self);
  64. // Control player movement
  65. if (input.held & GameKeyUp)
  66. pos.y -= PLAYER_SPEED;
  67. if (input.held & GameKeyDown)
  68. pos.y += PLAYER_SPEED;
  69. if (input.held & GameKeyLeft)
  70. pos.x -= PLAYER_SPEED;
  71. if (input.held & GameKeyRight)
  72. pos.x += PLAYER_SPEED;
  73. // Clamp player position to screen bounds, and set it
  74. pos.x = CLAMP(pos.x, 125, 3);
  75. pos.y = CLAMP(pos.y, 61, 3);
  76. entity_pos_set(self, pos);
  77. // Control game pause
  78. if (input.pressed & GameKeyBack) {
  79. pause_game(level);
  80. }
  81. }
  82. static void
  83. player_render(Entity* self,
  84. GameManager* manager,
  85. Canvas* canvas,
  86. void* _entity_context)
  87. {
  88. PlayerContext* player = _entity_context;
  89. // Draw initial animation
  90. if (player->time < PLAYER_ANIMATION_DURATION) {
  91. float step = 61 / PLAYER_ANIMATION_DURATION;
  92. float left_x = player->time * step;
  93. float right_x = 122 - left_x;
  94. left_x = CLAMP(left_x, 61, 0);
  95. right_x = CLAMP(right_x, 122, 61);
  96. canvas_draw_sprite(canvas, player->sprite, left_x, 29);
  97. canvas_draw_sprite(canvas, player->sprite, right_x, 29);
  98. return;
  99. }
  100. // Draw player sprite
  101. Vector pos = entity_pos_get(self);
  102. canvas_draw_sprite(canvas, player->sprite, pos.x - 3, pos.y - 3);
  103. // Draw score
  104. GameContext* game_context = game_manager_game_context_get(manager);
  105. canvas_printf_aligned(
  106. canvas, 64, 0, AlignCenter, AlignTop, "%lu", game_context->score);
  107. }
  108. const EntityDescription player_description = {
  109. .start = NULL,
  110. .stop = NULL,
  111. .update = player_update,
  112. .render = player_render,
  113. .collision = NULL,
  114. .event = NULL,
  115. .context_size = sizeof(PlayerContext),
  116. };