#include "map.h" #include "asset_manager.h" #include "game.h" #include "ecs.h" #include "components.h" #include "vector2d.h" #include "memory_alloc.h" #include "errors.h" map_t *load_map(void) { map_t *map = malloc(sizeof(map_t)); if(fread(&map->width, sizeof(map->width), 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } if(fread(&map->height, sizeof(map->height), 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } map->backgroundlayer1 = malloc(map->width * map->height * sizeof(uint16_t)); if(fread(map->backgroundlayer1, sizeof(uint16_t), map->width * map->height, game.asset_manager.asset_file) != (size_t)map->width * (size_t)map->height) { error_printf("Failed to read in asset file."); return NULL; } map->backgroundlayer2 = malloc(map->width * map->height * sizeof(uint16_t)); if(fread(map->backgroundlayer2, sizeof(uint16_t), map->width * map->height, game.asset_manager.asset_file) != (size_t)map->width * (size_t)map->height) { error_printf("Failed to read in asset file."); return NULL; } map->backgroundlayer3 = malloc(map->width * map->height * sizeof(uint16_t)); if(fread(map->backgroundlayer3, sizeof(uint16_t), map->width * map->height, game.asset_manager.asset_file) != (size_t)map->width * (size_t)map->height) { error_printf("Failed to read in asset file."); return NULL; } map->foregroundlayer = malloc(map->width * map->height * sizeof(uint16_t)); if(fread(map->foregroundlayer, sizeof(uint16_t), map->width * map->height, game.asset_manager.asset_file) != (size_t)map->width * (size_t)map->height) { error_printf("Failed to read in asset file."); return NULL; } map->hitboxes = malloc(map->width * map->height * sizeof(uint8_t)); if(fread(map->hitboxes, sizeof(uint8_t), map->width * map->height, game.asset_manager.asset_file) != (size_t)map->width * (size_t)map->height) { error_printf("Failed to read in asset file."); return NULL; } if(fread(&map->entities_nb, sizeof(map->entities_nb), 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } map->entities_defs = calloc(map->entities_nb, sizeof(map_entity_def_t)); for(uint32_t i = 0; i < map->entities_nb; i++) { map_entity_def_t *entity_def = &map->entities_defs[i]; if(fread(&entity_def->id, sizeof(entity_def->id), 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } if(fread(&entity_def->components_nb, sizeof(entity_def->components_nb), 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } entity_def->components_defs = calloc(entity_def->components_nb, sizeof(map_entity_component_def_t)); for(uint32_t j = 0; j < entity_def->components_nb; j++) { map_entity_component_def_t *component_def = &entity_def->components_defs[j]; if(fread(&component_def->type, sizeof(component_def->type), 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } switch(component_def->type) { size_t data_size; case TRANSFORM_COMPONENT: case HITBOX_COMPONENT: data_size = sizeof(fvector2d_t) * 2; component_def->attributes = malloc(data_size); if(fread(component_def->attributes, data_size, 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } break; case SPRITE_COMPONENT: { size_t cap = 0; if(getdelim((char **)&component_def->attributes, &cap, '\0', game.asset_manager.asset_file) == -1) { error_printf("Failed to read in asset file."); return NULL; } break; } case ANIMATION_SYSTEM: data_size = sizeof(int) * 2 + sizeof(float) + sizeof(bool) * 3; component_def->attributes = malloc(data_size); if(fread(component_def->attributes, data_size, 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } break; case INTERACT_COMPONENT: data_size = sizeof(fvector2d_t) * 2 + sizeof(int) * 3; component_def->attributes = malloc(data_size); if(fread(component_def->attributes, data_size, 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } break; case DOOR_COMPONENT: data_size = sizeof(int) + sizeof(bool); component_def->attributes = malloc(data_size); if(fread(component_def->attributes, data_size, 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } break; case LEVER_COMPONENT: data_size = sizeof(int) + sizeof(bool); component_def->attributes = malloc(data_size); if(fread(component_def->attributes, data_size, 1, game.asset_manager.asset_file) != 1) { error_printf("Failed to read in asset file."); return NULL; } break; default: error_printf("Component type not supported for loading : %s (%d)", component_type_to_name(component_def->type), component_def->type); return NULL; } } } return map; } void destroy_map(map_t *map) { if(map->entities_defs) { for(uint32_t i = 0; i < map->entities_nb; i++) { map_entity_def_t *entity_def = &map->entities_defs[i]; if(entity_def->components_defs) { for(uint32_t j = 0; j < entity_def->components_nb; j++) { map_entity_component_def_t *component_def = &entity_def->components_defs[j]; if(component_def->attributes) free(component_def->attributes); } free(entity_def->components_defs); } } free(map->entities_defs); } if(map->hitboxes) free(map->hitboxes); if(map->foregroundlayer) free(map->foregroundlayer); if(map->backgroundlayer3) free(map->backgroundlayer3); if(map->backgroundlayer2) free(map->backgroundlayer2); if(map->backgroundlayer1) free(map->backgroundlayer1); free(map); } int map_load_entities(map_t *map) { for(uint32_t i = 0; i < map->entities_nb; i++) { map_entity_def_t *entity_def = &map->entities_defs[i]; entity_t *entity = entity_manager_new_entity(entity_def->id); if(!entity) return_failure_int; for(uint32_t j = 0; j < entity_def->components_nb; j++) { map_entity_component_def_t *component_def = &entity_def->components_defs[j]; component_t *component = entity_new_component(entity, component_def->type); switch(component_def->type) { case TRANSFORM_COMPONENT: { struct { frect_t bounds; } *data = component_def->attributes; transform_component_data_t *component_data = component->data; component_data->bounds = data->bounds; break; } case SPRITE_COMPONENT: { sprite_component_data_t *component_data = component->data; asset_t *texture_asset = asset_manager_load_asset((char *)component_def->attributes, ASSET_TEXTURE); if(!texture_asset) return_failure_int; component_data->texture = texture_asset->data; break; } case ANIMATION_SYSTEM: { struct { int nb_frames; int current_frame_nb; float frame_delay_ms; bool play; bool loop; bool reverse; } *data = component_def->attributes; animation_system_data_t *system_data = component->data; system_data->nb_frames = data->nb_frames; system_data->current_frame_nb = data->current_frame_nb; system_data->frame_delay_ms = data->frame_delay_ms; system_data->play = data->play; system_data->loop = data->loop; system_data->reverse = data->reverse; animation_system_apply_changes(component); break; } case HITBOX_COMPONENT: { struct { fvector2d_t position; fvector2d_t scale; } *data = component_def->attributes; hitbox_component_data_t *component_data = component->data; component_data->position = data->position; component_data->scale = data->scale; break; } case DOOR_COMPONENT: { struct { int topic_id; bool state; } *data = component_def->attributes; door_component_data_t *component_data = component->data; component_data->topic_id = data->topic_id; component_data->state = data->state; if(door_component_subscribe(component)) return_failure_int; break; } case INTERACT_COMPONENT: { struct { fvector2d_t position; fvector2d_t scale; int topic_id; int type; int state; } *data = component_def->attributes; interact_component_data_t *component_data = component->data; component_data->position = data->position; component_data->scale = data->scale; component_data->type = data->type; component_data->state = data->state; if(event_bus_new_topic(data->topic_id)) return_failure_int; break; } case LEVER_COMPONENT: { struct { int topic_id; bool state; } *data = component_def->attributes; lever_component_data_t *component_data = component->data; component_data->topic_id = data->topic_id; component_data->state = data->state; if(lever_component_subscribe(component)) return_failure_int; break; } default: error_printf("Component type not supported for loading : %s (%d)", component_type_to_name(component_def->type), component_def->type); return EXIT_FAILURE; } } } return EXIT_SUCCESS; } int map_remove_entities(map_t *map) { for(uint32_t i = 0; i < map->entities_nb; i++) { map_entity_def_t *entity_def = &map->entities_defs[i]; if(entity_manager_remove_entity(entity_def->id)) return_failure_int; for(uint32_t j = 0; j < entity_def->components_nb; j++) { map_entity_component_def_t *component_def = &entity_def->components_defs[j]; switch(component_def->type) { case SPRITE_COMPONENT: if(asset_manager_let_go_asset((char *)component_def->attributes)) return_failure_int; break; case INTERACT_COMPONENT: { struct { fvector2d_t position; fvector2d_t scale; int topic_id; int type; int state; } *data = component_def->attributes; if(event_bus_remove_topic(data->topic_id)) return_failure_int; break; } default: break; } } } return EXIT_SUCCESS; }