diff --git a/src/common/limits.h b/src/common/limits.h index bc242bb..a7b14be 100644 --- a/src/common/limits.h +++ b/src/common/limits.h @@ -16,6 +16,7 @@ #define MAX_SCENE_ENTITY_ARCHETYPES 32 #define MAX_SCENE_ENEMIES 64 #define MAX_SCENE_TRIGGERS 256 +#define MAX_SCENE_DOORS 256 #define MAX_UNIFORM_NAME_LEN 64 diff --git a/src/common/version.h b/src/common/version.h index df2fbff..ce2e8fb 100755 --- a/src/common/version.h +++ b/src/common/version.h @@ -4,7 +4,7 @@ /* Auto generated version file. DO NOT MODIFY */ #define SYMMETRY_VERSION_MAJOR 0 #define SYMMETRY_VERSION_MINOR 1 -#define SYMMETRY_VERSION_REVISION 337 +#define SYMMETRY_VERSION_REVISION 338 #define SYMMETRY_VERSION_BRANCH "dev" #endif \ No newline at end of file diff --git a/src/game/door.c b/src/game/door.c new file mode 100644 index 0000000..09835e4 --- /dev/null +++ b/src/game/door.c @@ -0,0 +1,106 @@ +#include "door.h" +#include "entity.h" +#include "scene.h" +#include "game.h" +#include "transform.h" +#include "trigger.h" +#include "event.h" +#include "../common/log.h" +#include "../common/parser.h" +#include "../common/hashmap.h" + +static void door_on_scene_loaded(struct Event* event, void* door_ptr); +static void door_on_trigger(struct Event* event, void* trigger_ptr); + +void door_init(struct Door* door, int mask) +{ + struct Game_State* game_state = game_state_get(); + struct Event_Manager* event_manager = game_state->event_manager; + + door->base.type = ET_DOOR; + door->mask = mask; + door->speed = 20.f; + door->state = DOOR_CLOSED; + + event_manager_subscribe_with_object(event_manager, EVT_SCENE_LOADED, &door_on_scene_loaded, (void*)door); +} + +void door_reset(struct Door* door) +{ + door->state = -1; + door->speed = 0.f; + + struct Event_Manager* event_manager = game_state_get()->event_manager; + event_manager_unsubscribe_with_object(event_manager, EVT_TRIGGER, &door_on_trigger, (void*)door); + event_manager_unsubscribe_with_object(event_manager, EVT_SCENE_LOADED, &door_on_scene_loaded, (void*)door); +} + +struct Door* door_read(struct Parser_Object* object, const char* name, struct Entity* parent_entity) +{ + struct Door* new_door = NULL; + struct Scene* scene = game_state_get()->scene; + + new_door = scene_door_create(scene, name, parent_entity, DOOR_KEY_NONE); + if(hashmap_value_exists(object->data, "door_speed")) new_door->speed = hashmap_float_get(object->data, "door_speed"); + if(hashmap_value_exists(object->data, "door_state")) new_door->state = hashmap_int_get(object->data, "door_state"); + if(hashmap_value_exists(object->data, "door_mask")) new_door->mask = hashmap_int_get(object->data, "door_mask"); + + return new_door; + +} + +void door_write(struct Door* door, struct Hashmap* entity_data) +{ + hashmap_int_set(entity_data, "door_state", door->state); + hashmap_int_set(entity_data, "door_mask", door->mask); + hashmap_float_set(entity_data, "door_speed", door->speed); +} + +void door_update(struct Door* door, struct Scene* scene, float dt) +{ + switch(door->state) + { + case DOOR_CLOSED: + case DOOR_OPEN: + break; + case DOOR_OPENING: + break; + case DOOR_CLOSING: + break; + } +} + +void door_on_scene_loaded(struct Event* event, void* door_ptr) +{ + struct Door* door = (struct Door*)door_ptr; + struct Entity* door_mesh[1] = { NULL }; + struct Entity* door_sound[1] = { NULL }; + struct Entity* door_trigger[1] = { NULL }; + + if(entity_get_num_children_of_type(door, ET_STATIC_MESH, &door_mesh, 1) == 1) + door->mesh = door_mesh[0]; + else + log_error("door:on_scene_load", "Could not find mesh entity for door %s", door->base.name); + + if(entity_get_num_children_of_type(door, ET_SOUND_SOURCE, &door_sound, 1) == 1) + door->sound = door_sound[0]; + else + log_error("door:on_scene_load", "Could not find sound entity for door %s", door->base.name); + + if(entity_get_num_children_of_type(door, ET_TRIGGER, &door_trigger, 1) == 1) + { + door->trigger = door_trigger[0]; + struct Event_Manager* event_manager = game_state_get()->event_manager; + event_manager_subscribe_with_object(event_manager, EVT_TRIGGER, &door_on_trigger, (void*)door); + } + else + { + log_error("door:on_scene_load", "Could not find trigger entity for door %s", door->base.name); + } + +} + +void door_on_trigger(struct Event* event, void* trigger_ptr) +{ + +} diff --git a/src/game/door.h b/src/game/door.h new file mode 100644 index 0000000..501dc29 --- /dev/null +++ b/src/game/door.h @@ -0,0 +1,24 @@ +#ifndef DOOR_H +#define DOOR_H + +struct Door; +struct Static_Mesh; +struct Sound_Source; +struct Parser_Object; +struct Entity; + +enum Door_State +{ + DOOR_CLOSED = 0, + DOOR_OPEN, + DOOR_CLOSING, + DOOR_OPENING +}; + +void door_init(struct Door* door, int mask); +void door_reset(struct Door* door); +void door_update(struct Door* door, struct Scene* scene, float dt); +struct Door* door_read(struct Parser_Object* object, const char* name, struct Entity* parent_entity); +void door_write(struct Door* door, struct Hashmap* entity_data); + +#endif \ No newline at end of file diff --git a/src/game/entity.c b/src/game/entity.c index 97f384e..7c9d7ee 100755 --- a/src/game/entity.c +++ b/src/game/entity.c @@ -20,6 +20,7 @@ #include "enemy.h" #include "event.h" #include "sound_source.h" +#include "door.h" #include #include @@ -216,6 +217,12 @@ bool entity_write(struct Entity* entity, struct Parser_Object* object, bool writ enemy_write(enemy, entity_data); } break; + case ET_DOOR: + { + struct Door* door = (struct Door*)entity; + door_write(door, entity_data); + } + break; case ET_TRIGGER: { struct Trigger* trigger = (struct Trigger*)entity; @@ -477,6 +484,13 @@ struct Entity* entity_read(struct Parser_Object* object, struct Entity* parent_e new_entity = &trigger->base; } break; + case ET_DOOR: + { + new_entity = &door_read(object, name, parent_entity)->base; + if(!new_entity) + return new_entity; + } + break; default: log_warning("Unhandled Entity type '%d' detected", type); break; @@ -595,6 +609,7 @@ const char* entity_type_name_get(struct Entity* entity) case ET_STATIC_MESH: typename = "Static Mesh"; break; case ET_ENEMY: typename = "Enemy"; break; case ET_TRIGGER: typename = "Trigger"; break; + case ET_DOOR: typename = "Door"; break; default: typename = "Unknown"; break; }; return typename; diff --git a/src/game/entity.h b/src/game/entity.h index 431e668..d1e4189 100755 --- a/src/game/entity.h +++ b/src/game/entity.h @@ -27,6 +27,7 @@ enum Entity_Type ET_SOUND_SOURCE, ET_ENEMY, ET_TRIGGER, + ET_DOOR, ET_MAX }; @@ -85,6 +86,15 @@ enum Trigger_Mask TRIGM_ALL = TRIGM_PLAYER | TRIGM_ENEMY }; +enum Door_Mask +{ + DOOR_KEY_NONE = 0, + DOOR_KEY_RED = 1 << 0, + DOOR_KEY_GREEN = 1 << 1, + DOOR_KEY_BLUE = 1 << 2, + DOOR_KEY_ALL = DOOR_KEY_RED | DOOR_KEY_GREEN | DOOR_KEY_BLUE +}; + enum Trigger_Type { TRIG_TOGGLE = 0, // Toggled on once and fires event then wont fire event until it is deactivated and activated again @@ -243,6 +253,17 @@ struct Trigger int trigger_mask; }; +struct Door +{ + struct Entity base; + int mask; + int state; + float speed; + struct Static_Mesh* mesh; + struct Sound_Source* sound; + struct Trigger* trigger; +}; + void entity_init(struct Entity* entity, const char* name, struct Entity* parent); void entity_reset(struct Entity* entity, int id); bool entity_save(struct Entity* entity, const char* filename, int directory_type); diff --git a/src/game/scene.c b/src/game/scene.c index 872c6a3..838198e 100755 --- a/src/game/scene.c +++ b/src/game/scene.c @@ -21,6 +21,7 @@ #include "event.h" #include "scene_funcs.h" #include "trigger.h" +#include "door.h" #include #include @@ -277,6 +278,7 @@ bool scene_save(struct Scene* scene, const char* filename, int directory_type) scene_write_entity_list(scene, ET_SOUND_SOURCE, parser); scene_write_entity_list(scene, ET_ENEMY, parser); scene_write_entity_list(scene, ET_TRIGGER, parser); + scene_write_entity_list(scene, ET_DOOR, parser); if(parser_write_objects(parser, scene_file, prefixed_filename)) log_message("Scene saved to %s", prefixed_filename); @@ -329,6 +331,11 @@ void scene_write_entity_list(struct Scene* scene, int entity_type, struct Parser entity = &scene->triggers[0].base; stride = sizeof(struct Trigger); break; + case ET_DOOR: + max_length = MAX_SCENE_DOORS; + entity = &scene->doors[0].base; + stride = sizeof(struct Door); + break; default: return; } @@ -378,6 +385,8 @@ void scene_destroy(struct Scene* scene) for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++) scene_static_mesh_remove(scene, &scene->static_meshes[i]); for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++) scene_sound_source_remove(scene, &scene->sound_sources[i]); for(int i = 0; i < MAX_SCENE_ENEMIES; i++) scene_enemy_remove(scene, &scene->enemies[i]); + for(int i = 0; i < MAX_SCENE_TRIGGERS; i++) scene_trigger_remove(scene, &scene->triggers[i]); + for(int i = 0; i < MAX_SCENE_DOORS; i++) scene_door_remove(scene, &scene->doors[i]); for(int i = 0; i < MAX_SCENE_ENTITY_ARCHETYPES; i++) memset(&scene->entity_archetypes[i][0], '\0', MAX_FILENAME_LEN); player_destroy(&scene->player); entity_reset(&scene->root_entity, 0); @@ -393,6 +402,12 @@ void scene_update(struct Scene* scene, float dt) if(scene->enemies[i].base.flags & EF_ACTIVE) enemy_update(&scene->enemies[i], scene, dt); } + + for(int i = 0; i < MAX_SCENE_DOORS; i++) + { + if(scene->doors[i].base.flags & EF_ACTIVE) + door_update(&scene->doors[i], scene, dt); + } } } @@ -521,6 +536,18 @@ void scene_post_update(struct Scene* scene) } } + for(int i = 0; i < MAX_SCENE_DOORS; i++) + { + struct Door* door = &scene->doors[i]; + if(!(door->base.flags & EF_ACTIVE)) continue; + + if(door->base.flags & EF_MARKED_FOR_DELETION) + { + scene_door_remove(scene, door); + continue; + } + } + if(scene->player.base.transform.is_modified) { scene->player.base.transform.is_modified = false; @@ -731,6 +758,33 @@ struct Enemy* scene_enemy_create(struct Scene* scene, const char* name, struct E return new_enemy; } +struct Door* scene_door_create(struct Scene* scene, const char* name, struct Entity* parent, int mask) +{ + assert(scene); + struct Door* new_door = NULL; + for(int i = 0; i < MAX_SCENE_DOORS; i++) + { + struct Door* door = &scene->doors[i]; + if(!(door->base.flags & EF_ACTIVE)) + { + new_door = door; + break; + } + } + + if(new_door) + { + entity_init(&new_door->base, name, parent ? parent : &scene->root_entity); + door_init(new_door, mask); + } + else + { + log_error("scene:door_create", "Max door limit reached!"); + } + + return new_door; +} + struct Trigger* scene_trigger_create(struct Scene* scene, const char* name, struct Entity* parent, int type, int mask) { assert(scene); @@ -757,6 +811,7 @@ struct Trigger* scene_trigger_create(struct Scene* scene, const char* name, stru return new_trigger; } + void scene_entity_base_remove(struct Scene* scene, struct Entity* entity) { assert(scene && entity && entity->id >= 0); @@ -782,6 +837,13 @@ void scene_enemy_remove(struct Scene* scene, struct Enemy* enemy) scene_entity_base_remove(scene, enemy); } +void scene_door_remove(struct Scene* scene, struct Door* door) +{ + assert(scene && door); + door_reset(door); + scene_entity_base_remove(scene, door); +} + void scene_trigger_remove(struct Scene* scene, struct Trigger* trigger) { assert(scene && trigger); @@ -915,6 +977,23 @@ struct Enemy* scene_enemy_find(struct Scene* scene, const char* name) return enemy; } +struct Door* scene_door_find(struct Scene* scene, const char* name) +{ + assert(scene && name); + struct Door* door = NULL; + + for(int i = 0; i < MAX_SCENE_DOORS; i++) + { + if(strncmp(name, scene->doors[i].base.name, MAX_ENTITY_NAME_LEN) == 0) + { + door = &scene->doors[i]; + break; + } + } + + return door; +} + struct Trigger* scene_trigger_find(struct Scene* scene, const char* name) { assert(scene && name); diff --git a/src/game/scene.h b/src/game/scene.h index 512ccf3..0633c32 100755 --- a/src/game/scene.h +++ b/src/game/scene.h @@ -23,6 +23,7 @@ struct Scene struct Sound_Source sound_sources[MAX_SCENE_SOUND_SOURCES]; struct Enemy enemies[MAX_SCENE_ENEMIES]; struct Trigger triggers[MAX_SCENE_TRIGGERS]; + struct Door doors[MAX_SCENE_DOORS]; char entity_archetypes[MAX_SCENE_ENTITY_ARCHETYPES][MAX_FILENAME_LEN]; int active_camera_index; Scene_Init_Func init; @@ -45,6 +46,7 @@ struct Static_Mesh* scene_static_mesh_create(struct Scene* scene, const char* n struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* name, struct Entity* parent, const char* filename, int type, bool loop, bool play); struct Enemy* scene_enemy_create(struct Scene* scene, const char* name, struct Entity* parent, int type); struct Trigger* scene_trigger_create(struct Scene* scene, const char* name, struct Entity* parent, int type, int mask); +struct Door* scene_door_create(struct Scene* scene, const char* name, struct Entity* parent, int mask); void scene_entity_base_remove(struct Scene* scene, struct Entity* entity); void scene_light_remove(struct Scene* scene, struct Light* light); @@ -53,6 +55,7 @@ void scene_static_mesh_remove(struct Scene* scene, struct Static_Mesh* mesh); void scene_sound_source_remove(struct Scene* scene, struct Sound_Source* source); void scene_enemy_remove(struct Scene* scene, struct Enemy* enemy); void scene_trigger_remove(struct Scene* scene, struct Trigger* trigger); +void scene_door_remove(struct Scene* scene, struct Door* door); void* scene_find(struct Scene* scene, const char* name); // Looks in all entity type arrays and returns the first one found. Result should be cast back to expected type struct Entity* scene_entity_find(struct Scene* scene, const char* name); @@ -63,6 +66,7 @@ struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* na struct Entity* scene_base_entity_get(struct Scene* scene, int id, int type); struct Enemy* scene_enemy_find(struct Scene* scene, const char* name); struct Trigger* scene_trigger_find(struct Scene* scene, const char* name); +struct Door* scene_door_find(struct Scene* scene, const char* name); void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct Entity* parent); void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity); // Sets root entity as parent diff --git a/todo.txt b/todo.txt index 95ab1bb..8ee95bb 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,10 @@ Todo: + - Composite door entity made up of static mesh, sound entity and trigger. Door might require 0-3 keys in order to be opened. + - Doors that open using the red/green/blue keys only as a way of progressing the level or cordoing off certain sections + - RGB keys to progress to next level + - Player/enemies getting hit by bullets + - Win/fail States + - Remove excessive repitition in scene related code that handles multiple entity types - Allow switching to editor mode when game is in pause mode - Implement flag for ignoring collisions with certain entities - Implement separate property window for player related variables that can be shown in the editor similar to renderer settings etc