Просмотр исходного кода

Level: speed up collision check

SG 1 год назад
Родитель
Сommit
4d6fbb2e13
4 измененных файлов с 50 добавлено и 34 удалено
  1. 9 26
      entity.c
  2. 27 0
      entity_i.h
  3. 13 7
      level.c
  4. 1 1
      main.c

+ 9 - 26
entity.c

@@ -15,32 +15,6 @@ int32_t entities_get_count(void) {
     return entities_count;
 }
 
-typedef enum {
-    ColliderTypeCircle,
-    ColliderTypeRect,
-} ColliderType;
-
-typedef struct {
-    ColliderType type;
-    union {
-        struct {
-            float radius;
-        } circle;
-        struct {
-            float half_width;
-            float half_height;
-        } rect;
-    };
-} Collider;
-
-struct Entity {
-    Vector position;
-    const EntityDescription* description;
-    void* context;
-    Collider* collider;
-    Vector collider_offset;
-};
-
 Entity* entity_alloc(const EntityDescription* description) {
     entities_count++;
     Entity* entity = malloc(sizeof(Entity));
@@ -53,6 +27,7 @@ Entity* entity_alloc(const EntityDescription* description) {
     entity->collider = NULL;
     entity->collider_offset = VECTOR_ZERO;
     ENTITY_D("Allocated at %p", entity);
+    entity->collider_dirty = false;
     return entity;
 }
 
@@ -61,6 +36,7 @@ void entity_collider_add_circle(Entity* entity, float radius) {
     entity->collider = malloc(sizeof(Collider));
     entity->collider->type = ColliderTypeCircle;
     entity->collider->circle.radius = radius;
+    entity->collider_dirty = true;
 }
 
 void entity_collider_add_rect(Entity* entity, float width, float height) {
@@ -69,10 +45,12 @@ void entity_collider_add_rect(Entity* entity, float width, float height) {
     entity->collider->type = ColliderTypeRect;
     entity->collider->rect.half_width = width / 2;
     entity->collider->rect.half_height = height / 2;
+    entity->collider_dirty = true;
 }
 
 void entity_collider_offset_set(Entity* entity, Vector offset) {
     entity->collider_offset = offset;
+    entity->collider_dirty = true;
 }
 
 Vector entity_collider_offset_get(Entity* entity) {
@@ -108,6 +86,7 @@ Vector entity_pos_get(Entity* entity) {
 
 void entity_pos_set(Entity* entity, Vector position) {
     entity->position = position;
+    entity->collider_dirty = true;
 }
 
 void* entity_context_get(Entity* entity) {
@@ -193,6 +172,10 @@ bool entity_collider_check_collision(Entity* entity, Entity* other) {
     furi_check(entity->collider);
     furi_check(other->collider);
 
+    // if(entity->description == other->description) {
+    //     return false;
+    // }
+
     if(entity->collider->type == ColliderTypeCircle) {
         if(other->collider->type == ColliderTypeCircle) {
             return entity_collider_circle_circle(entity, other);

+ 27 - 0
entity_i.h

@@ -6,6 +6,33 @@
 extern "C" {
 #endif
 
+typedef enum {
+    ColliderTypeCircle,
+    ColliderTypeRect,
+} ColliderType;
+
+typedef struct {
+    ColliderType type;
+    union {
+        struct {
+            float radius;
+        } circle;
+        struct {
+            float half_width;
+            float half_height;
+        } rect;
+    };
+} Collider;
+
+struct Entity {
+    Vector position;
+    const EntityDescription* description;
+    void* context;
+    Collider* collider;
+    Vector collider_offset;
+    bool collider_dirty;
+};
+
 Entity* entity_alloc(const EntityDescription* behaviour);
 
 void entity_free(Entity* entity);

+ 13 - 7
level.c

@@ -134,18 +134,20 @@ static void level_process_collision(Level* level, GameManager* manager) {
 
     EntityList_it(it_first, level->entities);
     while(!EntityList_end_p(it_first)) {
-        if(entity_collider_exists(*EntityList_cref(it_first))) {
+        Entity* first = *EntityList_ref(it_first);
+        if(entity_collider_exists(first)) {
             // start second iterator at the next entity,
             // so we don't check the same pair twice
             EntityList_it_set(it_second, it_first);
             EntityList_next(it_second);
             while(!EntityList_end_p(it_second)) {
-                if(entity_collider_exists(*EntityList_cref(it_second))) {
-                    Entity* first = *EntityList_ref(it_first);
-                    Entity* second = *EntityList_ref(it_second);
-                    if(entity_collider_check_collision(first, second)) {
-                        entity_call_collision(first, second, manager);
-                        entity_call_collision(second, first, manager);
+                Entity* second = *EntityList_ref(it_second);
+                if(first->collider_dirty || second->collider_dirty) {
+                    if(entity_collider_exists(second)) {
+                        if(entity_collider_check_collision(first, second)) {
+                            entity_call_collision(first, second, manager);
+                            entity_call_collision(second, first, manager);
+                        }
                     }
                 }
                 EntityList_next(it_second);
@@ -153,6 +155,10 @@ static void level_process_collision(Level* level, GameManager* manager) {
         }
         EntityList_next(it_first);
     }
+
+    FOREACH(item, level->entities) {
+        (*item)->collider_dirty = false;
+    }
 }
 
 void level_update(Level* level, GameManager* manager) {

+ 1 - 1
main.c

@@ -26,7 +26,7 @@ int32_t game_app(void* p) {
     game.start(game_manager, game_context);
 
     GameEngineSettings settings = game_engine_settings_init();
-    settings.fps = 60.0f;
+    settings.target_fps = 60.0f;
     settings.show_fps = true;
     settings.always_backlight = true;
     settings.frame_callback = frame_cb;