#include "game_world.h" #include "behaviour_entity.h" #include "list.h" #include "program.h" #include "debug.h" static List _add_queue; static List _remove_queue; static List _game_entities; static inline size_t _internal_find_index_for_entity(void* data, const List* list) { for(size_t i = 0; i < _game_entities.len; ++i) { BehaviourEntity* entity = list_at_as(BehaviourEntity, &_game_entities, i); if(entity->data == data) { return i; } } return list->len; } static inline void _internal_clear_removed() { list_foreach(BehaviourEntity*, entity, &_remove_queue) { size_t index = _internal_find_index_for_entity(entity->data, &_game_entities); entity->drop->drop(entity->data); list_erase(&_game_entities, index); } list_empty(&_remove_queue); } static inline void _internal_process_new() { list_foreach(BehaviourEntity*, entity, &_add_queue) { list_add(&_game_entities, entity); entity->tc->start(entity->data); } list_empty(&_add_queue); } void game_world_init() { _game_entities = list_from_type(BehaviourEntity); _add_queue = list_from_type(BehaviourEntity); _remove_queue = list_from_type(BehaviourEntity); } void game_world_close() { _internal_clear_removed(); _internal_process_new(); list_foreach(BehaviourEntity*, entity, &_game_entities) { entity->drop->drop(entity->data); } list_empty(&_game_entities); } void game_world_add_entity(BehaviourEntity entity) { list_add(&_add_queue, &entity); } void game_world_destroy_entity(BehaviourEntity entity) { list_add(&_remove_queue, &entity); } void game_world_update() { _internal_process_new(); list_foreach(BehaviourEntity*, entity, &_game_entities) { entity->tc->update(entity->data, delta_time()); } _internal_clear_removed(); } static int _internal_compare_depth(const BehaviourEntity* a, const BehaviourEntity* b) { return b->tc->get_depth(b->data) - a->tc->get_depth(a->data); } #define AS_COMPARISON(__FN) ((int(*)(const void*, const void*))__FN) void game_world_draw() { List draw_order = list_copy(&_game_entities); qsort(_game_entities.data, _game_entities.len, _game_entities.element_size, AS_COMPARISON(_internal_compare_depth)); list_foreach(BehaviourEntity*, entity, &draw_order) { entity->tc->draw(entity->data); } list_empty(&draw_order); }