level.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #include "level.h"
  2. #include "level_i.h"
  3. #include "entity_i.h"
  4. #include <m-list.h>
  5. #include <furi.h>
  6. LIST_DEF(EntityList, Entity*, M_POD_OPLIST);
  7. struct Level {
  8. EntityList_t entities;
  9. EntityList_t entities_to_add;
  10. EntityList_t entities_to_remove;
  11. LevelBehaviour behaviour;
  12. void* context;
  13. };
  14. static void level_process_add(Level* level) {
  15. EntityList_it_t it;
  16. EntityList_it(it, level->entities_to_add);
  17. while(!EntityList_end_p(it)) {
  18. EntityList_push_back(level->entities, *EntityList_cref(it));
  19. entity_call_start(*EntityList_ref(it));
  20. EntityList_next(it);
  21. }
  22. EntityList_clear(level->entities_to_add);
  23. }
  24. static void level_find_and_remove(Level* level, Entity* entity) {
  25. EntityList_it_t it;
  26. EntityList_it(it, level->entities);
  27. while(!EntityList_end_p(it)) {
  28. if(*EntityList_ref(it) == entity) {
  29. entity_call_stop(*EntityList_ref(it));
  30. EntityList_remove(level->entities, it);
  31. entity_free(entity);
  32. break;
  33. }
  34. EntityList_next(it);
  35. }
  36. }
  37. static void level_process_remove(Level* level) {
  38. EntityList_it_t it;
  39. EntityList_it(it, level->entities_to_remove);
  40. while(!EntityList_end_p(it)) {
  41. level_find_and_remove(level, *EntityList_cref(it));
  42. EntityList_next(it);
  43. }
  44. EntityList_clear(level->entities_to_remove);
  45. }
  46. Level* level_alloc(void) {
  47. Level* level = malloc(sizeof(Level));
  48. EntityList_init(level->entities);
  49. EntityList_init(level->entities_to_add);
  50. EntityList_init(level->entities_to_remove);
  51. level->behaviour = LEVEL_BEHAVIOUR_EMPTY;
  52. level->context = NULL;
  53. FURI_LOG_D("Level", "Allocated level at %p", level);
  54. return level;
  55. }
  56. void level_free(Level* level) {
  57. level_process_add(level);
  58. level_process_remove(level);
  59. EntityList_it_t it;
  60. EntityList_it(it, level->entities);
  61. while(!EntityList_end_p(it)) {
  62. entity_call_stop(*EntityList_ref(it));
  63. entity_free(*EntityList_ref(it));
  64. EntityList_next(it);
  65. }
  66. EntityList_clear(level->entities);
  67. EntityList_clear(level->entities_to_add);
  68. EntityList_clear(level->entities_to_remove);
  69. FURI_LOG_D("Level", "Freeing level at %p", level);
  70. free(level);
  71. }
  72. void level_behaviour_set(Level* level, LevelBehaviour behaviour, void* context) {
  73. level->behaviour = behaviour;
  74. level->context = context;
  75. }
  76. Entity* level_add_entity(Level* level, const EntityDescription* behaviour) {
  77. Entity* entity = entity_alloc(behaviour);
  78. EntityList_push_back(level->entities_to_add, entity);
  79. return entity;
  80. }
  81. void level_remove_entity(Level* level, Entity* entity) {
  82. EntityList_push_back(level->entities_to_remove, entity);
  83. }
  84. void level_update(Level* level, Director* director) {
  85. level_process_add(level);
  86. level_process_remove(level);
  87. EntityList_it_t it;
  88. EntityList_it(it, level->entities);
  89. while(!EntityList_end_p(it)) {
  90. entity_call_update(*EntityList_ref(it), director);
  91. EntityList_next(it);
  92. }
  93. }
  94. void level_render(Level* level, Director* director, Canvas* canvas) {
  95. EntityList_it_t it;
  96. EntityList_it(it, level->entities);
  97. while(!EntityList_end_p(it)) {
  98. entity_call_render(*EntityList_ref(it), director, canvas);
  99. EntityList_next(it);
  100. }
  101. }