enemy_entity.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include "enemy_entity.h"
  2. #include "src/engine/game_manager.h"
  3. #include "src/game.h"
  4. #include "src/game_notifications.h"
  5. #include "level_game.h"
  6. #include "player_entity.h"
  7. static Vector
  8. random_pos(Entity* player_entity)
  9. {
  10. const int full_size = ceilf(ENEMY_SIZE);
  11. const int half_size = ceilf(HALF_ENEMY_SIZE);
  12. Vector player_pos = entity_pos_get(player_entity);
  13. Vector pos;
  14. do {
  15. pos.x = half_size + rand() % (SCREEN_WIDTH - full_size);
  16. } while (fabsf(pos.x - player_pos.x) < 3 * ENEMY_SIZE);
  17. do {
  18. pos.y = half_size + rand() % (SCREEN_HEIGHT - full_size);
  19. } while (fabsf(pos.y - player_pos.y) < 3 * ENEMY_SIZE);
  20. return pos;
  21. }
  22. static EnemyDirection
  23. random_direction(Vector enemy_pos, Entity* player_entity)
  24. {
  25. Vector player_pos = entity_pos_get(player_entity);
  26. EnemyDirection direction = rand() % 4;
  27. if (direction == EnemyDirectionUp && enemy_pos.y > player_pos.y)
  28. direction = EnemyDirectionDown;
  29. else if (direction == EnemyDirectionDown && enemy_pos.y < player_pos.y)
  30. direction = EnemyDirectionUp;
  31. else if (direction == EnemyDirectionLeft && enemy_pos.x > player_pos.x)
  32. direction = EnemyDirectionRight;
  33. else if (direction == EnemyDirectionRight && enemy_pos.x < player_pos.x)
  34. direction = EnemyDirectionLeft;
  35. return direction;
  36. }
  37. void
  38. enemy_spawn(GameManager* manager)
  39. {
  40. GameContext* game_context = game_manager_game_context_get(manager);
  41. Level* level = game_manager_current_level_get(manager);
  42. // Add enemyh to level
  43. Entity* enemy = level_add_entity(level, &enemy_description);
  44. EnemyContext* enemy_context = entity_context_get(enemy);
  45. // Add to enemies list
  46. GameLevelContext* level_context = level_context_get(level);
  47. EntityList_push_back(level_context->enemies, enemy);
  48. // Set enemy position
  49. Vector enemy_pos = random_pos(level_context->player);
  50. entity_pos_set(enemy, enemy_pos);
  51. enemy_context->direction =
  52. random_direction(enemy_pos, level_context->player);
  53. // Add collision rect to enemy entity
  54. entity_collider_add_rect(enemy, ENEMY_SIZE, ENEMY_SIZE);
  55. // Load target sprite
  56. enemy_context->sprite = game_manager_sprite_load(manager, "enemy.fxbm");
  57. float speed;
  58. switch (game_context->difficulty) {
  59. case DifficultyEasy:
  60. speed = 0.25f;
  61. break;
  62. case DifficultyHard:
  63. speed = 1.0f;
  64. break;
  65. case DifficultyInsane:
  66. speed = 0.25f * (4 + rand() % 4);
  67. break;
  68. default:
  69. speed = 0.5f;
  70. break;
  71. }
  72. enemy_context->speed = speed;
  73. }
  74. static void
  75. enemy_update(Entity* self, GameManager* manager, void* context)
  76. {
  77. // Check pause
  78. Level* level = game_manager_current_level_get(manager);
  79. GameLevelContext* level_context = level_context_get(level);
  80. if (level_context->is_paused) {
  81. return;
  82. }
  83. EnemyContext* enemy_context = context;
  84. Vector pos = entity_pos_get(self);
  85. // Control player movement
  86. if (enemy_context->direction == EnemyDirectionUp)
  87. pos.y -= enemy_context->speed;
  88. if (enemy_context->direction == EnemyDirectionDown)
  89. pos.y += enemy_context->speed;
  90. if (enemy_context->direction == EnemyDirectionLeft)
  91. pos.x -= enemy_context->speed;
  92. if (enemy_context->direction == EnemyDirectionRight)
  93. pos.x += enemy_context->speed;
  94. // Clamp enemy position to screen bounds, and set it
  95. pos.x = CLAMP(pos.x, SCREEN_WIDTH - HALF_ENEMY_SIZE, HALF_ENEMY_SIZE);
  96. pos.y = CLAMP(pos.y, SCREEN_HEIGHT - HALF_ENEMY_SIZE, HALF_ENEMY_SIZE);
  97. entity_pos_set(self, pos);
  98. // Switching direction
  99. if (enemy_context->direction == EnemyDirectionUp &&
  100. pos.y <= HALF_ENEMY_SIZE)
  101. enemy_context->direction = EnemyDirectionDown;
  102. else if (enemy_context->direction == EnemyDirectionDown &&
  103. pos.y >= SCREEN_HEIGHT - HALF_ENEMY_SIZE)
  104. enemy_context->direction = EnemyDirectionUp;
  105. else if (enemy_context->direction == EnemyDirectionLeft &&
  106. pos.x <= HALF_ENEMY_SIZE)
  107. enemy_context->direction = EnemyDirectionRight;
  108. else if (enemy_context->direction == EnemyDirectionRight &&
  109. pos.x >= SCREEN_WIDTH - HALF_ENEMY_SIZE)
  110. enemy_context->direction = EnemyDirectionLeft;
  111. }
  112. static void
  113. enemy_render(Entity* self, GameManager* manager, Canvas* canvas, void* context)
  114. {
  115. UNUSED(context);
  116. UNUSED(manager);
  117. // Get enemy position
  118. Vector pos = entity_pos_get(self);
  119. // Draw enemy
  120. EnemyContext* enemy_context = entity_context_get(self);
  121. canvas_draw_sprite(canvas,
  122. enemy_context->sprite,
  123. pos.x - HALF_ENEMY_SIZE,
  124. pos.y - HALF_ENEMY_SIZE);
  125. }
  126. static void
  127. enemy_collision(Entity* self,
  128. Entity* other,
  129. GameManager* manager,
  130. void* context)
  131. {
  132. UNUSED(self);
  133. UNUSED(context);
  134. if (entity_description_get(other) != &player_description) {
  135. return;
  136. }
  137. // Game over
  138. GameContext* game_context = game_manager_game_context_get(manager);
  139. game_notify(game_context, &sequence_game_over);
  140. game_manager_next_level_set(manager, game_context->levels.game_over);
  141. }
  142. const EntityDescription enemy_description = {
  143. .start = NULL,
  144. .stop = NULL,
  145. .update = enemy_update,
  146. .render = enemy_render,
  147. .collision = enemy_collision,
  148. .event = NULL,
  149. .context_size = sizeof(EnemyContext),
  150. };