92 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #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);
 | |
| }
 | 
