From 08f6518253fb4e08b970744a57616592307c9fab Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Fri, 31 Jan 2020 21:25:02 +1100 Subject: [PATCH] Added another sound source child entity to enemy entity and added remaining turret properties to editor and in serialization to file --- assets/entities/turret.symtres | 38 ++++++++++++++++-- src/common/limits.h | 3 ++ src/common/version.h | 2 +- src/game/editor.c | 23 ++++++++++- src/game/enemy.c | 72 ++++++++++++++++++---------------- src/game/entity.c | 19 +++++++++ src/game/entity.h | 2 + src/game/scene.c | 6 ++- src/game/scene.h | 2 +- todo.txt | 6 +-- 10 files changed, 129 insertions(+), 44 deletions(-) diff --git a/assets/entities/turret.symtres b/assets/entities/turret.symtres index 9b477a3..b93205c 100644 --- a/assets/entities/turret.symtres +++ b/assets/entities/turret.symtres @@ -2,18 +2,27 @@ Entity { type : 8 scale : 1.000 1.000 1.000 - max_turn_angle : 60.0000 - rotation : 0.000 0.423 0.000 0.906 + pulsate_height : 1.5000 + vision_range : 15.0000 + pulsate_speed_scale : 0.1000 + rotation : 0.000 0.001 0.000 1.001 health : 116 + alert_cooldown : 1.0000 + color_alert : 1.000 1.000 0.000 1.000 active : true - position : 5.000 3.000 6.000 + turn_speed_when_targetting : 50.0000 + max_yaw : 60.0000 + position : 0.000 3.000 0.000 bouding_box_min : -0.500 -0.500 -0.500 enemy_type : 0 + turn_speed_default : 50.0000 turn_direction_positive : true + attack_cooldown : 0.0500 name : Turret bouding_box_max : 0.500 0.500 0.500 + color_default : 0.000 1.000 1.000 1.000 + color_attack : 1.000 0.000 0.000 1.000 damage : 10 - turn_speed : 50.0000 } Entity @@ -37,6 +46,27 @@ Entity sound_attenuation_type : 2 } +Entity +{ + type : 7 + scale : 1.000 1.000 1.000 + volume : 1.0000 + rolloff_factor : 0.9500 + rotation : 0.000 0.000 0.000 1.000 + loop : true + sound_min_distance : 0.0000 + active : true + playing : true + position : 0.000 0.000 0.000 + bouding_box_min : -0.500 -0.500 -0.500 + source_filename : sounds/windy_ambience.ogg + sound_type : 2 + sound_max_distance : 60.0000 + name : Turret_Ambient_Sound + bouding_box_max : 0.500 0.500 0.500 + sound_attenuation_type : 2 +} + Entity { type : 6 diff --git a/src/common/limits.h b/src/common/limits.h index b90cb41..36aaa22 100644 --- a/src/common/limits.h +++ b/src/common/limits.h @@ -22,4 +22,7 @@ #define MAX_FRAME_TIME 0.5f +#define MAX_ENEMY_SOUND_SOURCES 2 +#define MAX_ENEMY_MESHES 1 + #endif diff --git a/src/common/version.h b/src/common/version.h index a6fa642..7e22992 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 323 +#define SYMMETRY_VERSION_REVISION 324 #define SYMMETRY_VERSION_BRANCH "dev" #endif \ No newline at end of file diff --git a/src/game/editor.c b/src/game/editor.c index 0156e9b..ab09517 100755 --- a/src/game/editor.c +++ b/src/game/editor.c @@ -41,6 +41,9 @@ #include #include +#define LABEL_FLAGS_ALIGN_LEFT NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_LEFT +#define LABEL_FLAGS_ALIGN_RIGHT NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_RIGHT + enum Editor_Tool { EDITOR_TOOL_NORMAL = 0, @@ -2226,7 +2229,25 @@ void editor_window_property_inspector(struct nk_context* context, struct Editor* { case ENEMY_TURRET: { - nk_property_float(context, "Turn Speed", 0.f, &enemy->Turret.turn_speed_default, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Turn Speed Default", 0.f, &enemy->Turret.turn_speed_default, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Turn Speed Targetting", 0.f, &enemy->Turret.turn_speed_when_targetting, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Turn Speed Current", 0.f, &enemy->Turret.turn_speed_current, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Max Yaw", 0.f, &enemy->Turret.max_yaw, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Target Yaw", 0.f, &enemy->Turret.target_yaw, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Pulsate Speed Scale", 0.f, &enemy->Turret.pulsate_speed_scale, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Pulsate Height", 0.f, &enemy->Turret.pulsate_height, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Attack Cooldown", 0.f, &enemy->Turret.attack_cooldown, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Time since attack", 0.f, &enemy->Turret.time_elapsed_since_attack, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Time since alert", 0.f, &enemy->Turret.time_elapsed_since_alert, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Alert Cooldown", 0.f, &enemy->Turret.alert_cooldown, FLT_MAX, 0.5f, 0.1f); + nk_property_float(context, "Vision Range", 0.f, &enemy->Turret.vision_range, FLT_MAX, 0.5f, 0.1f); + nk_layout_row_dynamic(context, row_height, 2); + nk_label(context, "Yaw Positive", LABEL_FLAGS_ALIGN_LEFT); nk_labelf(context, LABEL_FLAGS_ALIGN_LEFT, "%s", enemy->Turret.yaw_direction_positive ? "True" : "False"); + nk_label(context, "Pulsate", LABEL_FLAGS_ALIGN_LEFT); nk_labelf(context, LABEL_FLAGS_ALIGN_LEFT, "%s", enemy->Turret.pulsate ? "True" : "False"); + nk_label(context, "Scan", LABEL_FLAGS_ALIGN_LEFT); nk_labelf(context, LABEL_FLAGS_ALIGN_LEFT, "%s", enemy->Turret.scan ? "True" : "False"); + nk_label(context, "Default Color", LABEL_FLAGS_ALIGN_LEFT); editor_widget_color_combov4(context, &enemy->Turret.color_default, 50, row_height * 2); + nk_label(context, "Alert Color", LABEL_FLAGS_ALIGN_LEFT); editor_widget_color_combov4(context, &enemy->Turret.color_alert, 50, row_height * 2); + nk_label(context, "Attack Color", LABEL_FLAGS_ALIGN_LEFT); editor_widget_color_combov4(context, &enemy->Turret.color_attack, 50, row_height * 2); } break; } diff --git a/src/game/enemy.c b/src/game/enemy.c index 5efc51b..96c64a3 100644 --- a/src/game/enemy.c +++ b/src/game/enemy.c @@ -143,8 +143,16 @@ struct Enemy* enemy_read(struct Parser_Object* object, const char* name, struct { case ENEMY_TURRET: { - if(hashmap_value_exists(object->data, "turn_speed")) new_enemy->Turret.turn_speed_default = hashmap_float_get(object->data, "turn_speed"); - if(hashmap_value_exists(object->data, "max_turn_angle")) new_enemy->Turret.max_yaw = hashmap_float_get(object->data, "max_turn_angle"); + if(hashmap_value_exists(object->data, "turn_speed_default")) new_enemy->Turret.turn_speed_default = hashmap_float_get(object->data, "turn_speed_default"); + if(hashmap_value_exists(object->data, "max_yaw")) new_enemy->Turret.max_yaw = hashmap_float_get(object->data, "max_yaw"); + if(hashmap_value_exists(object->data, "pulsate_speed_scale")) new_enemy->Turret.pulsate_speed_scale = hashmap_float_get(object->data, "pulsate_speed_scale"); + if(hashmap_value_exists(object->data, "pulsate_height")) new_enemy->Turret.pulsate_height = hashmap_float_get(object->data, "pulsate_height"); + if(hashmap_value_exists(object->data, "attack_cooldown")) new_enemy->Turret.attack_cooldown = hashmap_float_get(object->data, "attack_cooldown"); + if(hashmap_value_exists(object->data, "alert_cooldown")) new_enemy->Turret.alert_cooldown = hashmap_float_get(object->data, "alert_cooldown"); + if(hashmap_value_exists(object->data, "vision_range")) new_enemy->Turret.vision_range = hashmap_float_get(object->data, "vision_range"); + if(hashmap_value_exists(object->data, "color_default")) new_enemy->Turret.color_default = hashmap_vec4_get(object->data, "color_default"); + if(hashmap_value_exists(object->data, "color_alert")) new_enemy->Turret.color_alert = hashmap_vec4_get(object->data, "color_alert"); + if(hashmap_value_exists(object->data, "color_attack")) new_enemy->Turret.color_attack = hashmap_vec4_get(object->data, "color_attack"); if(hashmap_value_exists(object->data, "turn_direction_positive")) new_enemy->Turret.yaw_direction_positive = hashmap_bool_get(object->data, "turn_direction_positive"); } break; @@ -163,8 +171,17 @@ void enemy_write(struct Enemy* enemy, struct Hashmap* entity_data) { case ENEMY_TURRET: { - hashmap_float_set(entity_data, "turn_speed", enemy->Turret.turn_speed_default); - hashmap_float_set(entity_data, "max_turn_angle", enemy->Turret.max_yaw); + hashmap_float_set(entity_data, "turn_speed_default", enemy->Turret.turn_speed_default); + hashmap_float_set(entity_data, "turn_speed_when_targetting", enemy->Turret.turn_speed_default); + hashmap_float_set(entity_data, "max_yaw", enemy->Turret.max_yaw); + hashmap_float_set(entity_data, "pulsate_speed_scale", enemy->Turret.pulsate_speed_scale); + hashmap_float_set(entity_data, "pulsate_height", enemy->Turret.pulsate_height); + hashmap_float_set(entity_data, "attack_cooldown", enemy->Turret.attack_cooldown); + hashmap_float_set(entity_data, "alert_cooldown", enemy->Turret.alert_cooldown); + hashmap_float_set(entity_data, "vision_range", enemy->Turret.vision_range); + hashmap_vec4_set(entity_data, "color_default", &enemy->Turret.color_default); + hashmap_vec4_set(entity_data, "color_alert", &enemy->Turret.color_alert); + hashmap_vec4_set(entity_data, "color_attack", &enemy->Turret.color_attack); hashmap_bool_set(entity_data, "turn_direction_positive", enemy->Turret.yaw_direction_positive); } break; @@ -176,23 +193,26 @@ void enemy_on_scene_loaded(struct Event* event, void* enemy_ptr) struct Enemy* enemy = (struct Enemy*)enemy_ptr; // Assign pointers to static_mesh and sound_source child entities - for(int i = 0; i < array_len(enemy->base.transform.children); i++) + struct Entity* enemy_mesh[MAX_ENEMY_MESHES] = { NULL }; + struct Entity* enemy_sound_sources[MAX_ENEMY_SOUND_SOURCES] = { NULL }; + if(entity_get_num_children_of_type(enemy, ET_STATIC_MESH, &enemy_mesh, MAX_ENEMY_MESHES) == MAX_ENEMY_MESHES) { - struct Entity* child = enemy->base.transform.children[i]; - if(child->type == ET_STATIC_MESH) - enemy->mesh = (struct Static_Mesh*)child; - else if(child->type == ET_SOUND_SOURCE) - enemy->weapon_sound = (struct Sound_Source*)child; + enemy->mesh = enemy_mesh[0]; } - - if(enemy->mesh) - enemy->mesh->base.flags |= EF_TRANSIENT; else - log_error("enemy:on_scene_loaded", "Could not find mesh child entity for enemy %s", enemy->base.name); - if(enemy->weapon_sound) - enemy->weapon_sound->base.flags |= EF_TRANSIENT; + { + log_error("enemy:on_scene_load", "Could not find %d child mesh entities for enemy %s", MAX_ENEMY_MESHES, enemy->base.name); + } + + if(entity_get_num_children_of_type(enemy, ET_SOUND_SOURCE, &enemy_sound_sources, MAX_ENEMY_SOUND_SOURCES) == MAX_ENEMY_SOUND_SOURCES) + { + enemy->weapon_sound = enemy_sound_sources[0]; + enemy->ambient_sound = enemy_sound_sources[1]; + } else - log_error("enemy:on_scene_loaded", "Could not find weapon_sound child entity for enemy %s", enemy->base.name); + { + log_error("enemy:on_scene_load", "Could not find %d child sound source entities for enemy %s", MAX_ENEMY_SOUND_SOURCES, enemy->base.name); + } // Do other post-scene-load initialization stuff per enemy type here switch(enemy->type) @@ -235,10 +255,8 @@ void enemy_update_physics_turret(struct Enemy* enemy, struct Game_State* game_st float epsilon = 0.5f; float current_yaw = quat_get_yaw(&enemy->base.transform.rotation); float difference = enemy->Turret.target_yaw - current_yaw; - //if(fabsf(current_yaw) > enemy->Turret.target_yaw - EPSILON && fabsf(current_yaw) < enemy->Turret.target_yaw + EPSILON) if(fabsf(difference) > epsilon) { - //log_message("Difference %.5f", difference); float yaw = enemy->Turret.turn_speed_current * 1.f * fixed_dt; if(current_yaw > enemy->Turret.target_yaw) yaw *= -1.f; @@ -283,7 +301,6 @@ void enemy_update_ai_turret(struct Enemy* enemy, struct Game_State* game_state, if(distance <= enemy->Turret.vision_range) { enemy_state_set_turret(enemy, TURRET_ALERT); - log_message("Player spotted"); } } } @@ -304,7 +321,6 @@ void enemy_update_ai_turret(struct Enemy* enemy, struct Game_State* game_state, if(distance <= enemy->Turret.vision_range) { enemy_state_set_turret(enemy, TURRET_ATTACK); - log_message("Player spotted"); } } } @@ -336,15 +352,10 @@ void enemy_update_ai_turret(struct Enemy* enemy, struct Game_State* game_state, float new_target_yaw = current_yaw - yaw_required_to_face_player; if(fabsf(floorf(new_target_yaw)) > enemy->Turret.max_yaw) { - log_message("Can't face player"); - log_message("New Yaw : %.3f", new_target_yaw); - log_message("Cur yaw : %.3f", current_yaw); - log_message("Ang bet : %.3f", yaw_required_to_face_player); enemy_state_set_turret(enemy, TURRET_ALERT); } else { - log_message("Acquiring Target..."); float difference = fabsf(enemy->Turret.target_yaw - new_target_yaw); if(difference > 1.f) enemy->Turret.target_yaw = new_target_yaw; @@ -352,7 +363,6 @@ void enemy_update_ai_turret(struct Enemy* enemy, struct Game_State* game_state, } else { - log_message("No target in range"); enemy_state_set_turret(enemy, TURRET_ALERT); } } @@ -371,17 +381,14 @@ void enemy_update_ai_turret(struct Enemy* enemy, struct Game_State* game_state, { enemy->Turret.time_elapsed_since_attack = 0.f; sound_source_play(game_state->sound, enemy->weapon_sound); - log_message("Player spotted and attacked"); } else { enemy_state_set_turret(enemy, TURRET_ACQUIRE_TARGET); - log_message("Target too far"); } } else { - log_message("Can't find player, cannot attack"); enemy_state_set_turret(enemy, TURRET_ACQUIRE_TARGET); } } @@ -402,6 +409,7 @@ void enemy_state_set_turret(struct Enemy* enemy, int state) case TURRET_DEFAULT: { vec4_assign(&model->material_params[MMP_DIFFUSE_COL].val_vec4, &enemy->Turret.color_default); + sound_source_play(game_state_get()->sound, enemy->ambient_sound); enemy->Turret.time_elapsed_since_alert = 0.f; enemy->Turret.time_elapsed_since_attack = 0.f; enemy->Turret.pulsate = true; @@ -424,9 +432,7 @@ void enemy_state_set_turret(struct Enemy* enemy, int state) break; case TURRET_ACQUIRE_TARGET: { - //vec4_assign(&model->material_params[MMP_DIFFUSE_COL].val_vec4, &enemy->Turret.color_attack); - vec4 color = {0.f, 0.f, 1.f, 1.f}; - vec4_assign(&model->material_params[MMP_DIFFUSE_COL].val_vec4, &color); + vec4_assign(&model->material_params[MMP_DIFFUSE_COL].val_vec4, &enemy->Turret.color_attack); enemy->Turret.scan = false; enemy->Turret.turn_speed_current = enemy->Turret.turn_speed_when_targetting; } diff --git a/src/game/entity.c b/src/game/entity.c index 6cfb0c4..6ab4bb4 100755 --- a/src/game/entity.c +++ b/src/game/entity.c @@ -737,3 +737,22 @@ void entity_rename(struct Entity* entity, const char* new_name) memset(entity->name, '\0', MAX_ENTITY_NAME_LEN); snprintf(entity->name, MAX_ENTITY_NAME_LEN, new_name); } + +int entity_get_num_children_of_type(struct Entity* entity, int type, struct Entity** in_children, int max_children) +{ + assert(type < ET_MAX && max_children >= 1); + + int found_count = -1; + for(int i = 0; i < array_len(entity->transform.children); i++) + { + struct Entity* child = entity->transform.children[i]; + if(!(child->flags & EF_MARKED_FOR_DELETION) && (child->flags & EF_ACTIVE) && child->type == type) + { + found_count++; + if(found_count == max_children) + break; + in_children[found_count] = child; + } + } + return found_count + 1; +} diff --git a/src/game/entity.h b/src/game/entity.h index eaed25d..beb43b8 100755 --- a/src/game/entity.h +++ b/src/game/entity.h @@ -200,6 +200,7 @@ struct Enemy int current_state; struct Static_Mesh* mesh; struct Sound_Source* weapon_sound; + struct Sound_Source* ambient_sound; union { struct @@ -233,6 +234,7 @@ struct Entity* entity_load(const char* filename, int directory_type, bool send_o bool entity_write(struct Entity* entity, struct Parser_Object* object, bool write_transform); struct Entity* entity_read(struct Parser_Object* object, struct Entity* parent_entity); const char* entity_type_name_get(struct Entity* entity); +int entity_get_num_children_of_type(struct Entity* entity, int type, struct Entity** in_children, int max_children); void entity_rigidbody_on_move(Rigidbody body); void entity_rigidbody_on_collision(Rigidbody body_A, Rigidbody body_B); void entity_rigidbody_set(struct Entity* entity, struct Collision* collision, Rigidbody body); diff --git a/src/game/scene.c b/src/game/scene.c index 694f147..75aa26f 100755 --- a/src/game/scene.c +++ b/src/game/scene.c @@ -842,7 +842,7 @@ struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* na return sound_source; } -struct Enemy* scene_enemy_get(struct Scene* scene, const char* name) +struct Enemy* scene_enemy_find(struct Scene* scene, const char* name) { assert(scene && name); struct Enemy* enemy = NULL; @@ -872,6 +872,7 @@ struct Entity* scene_base_entity_get(struct Scene* scene, int id, int type) case ET_LIGHT: entity = &scene->lights[id]; break; case ET_STATIC_MESH: entity = &scene->static_meshes[id]; break; case ET_SOUND_SOURCE: entity = &scene->sound_sources[id]; break; + case ET_ENEMY: entity = &scene->enemies[id]; break; case ET_PLAYER: entity = &scene->player; break; case ET_ROOT: entity = &scene->root_entity; break; } @@ -898,6 +899,9 @@ void* scene_find(struct Scene* scene, const char* name) entity = scene_sound_source_find(scene, name); if(entity) return entity; + entity = scene_enemy_find(scene, name); + if(entity) return entity; + return entity; } diff --git a/src/game/scene.h b/src/game/scene.h index 725250d..354d5e7 100755 --- a/src/game/scene.h +++ b/src/game/scene.h @@ -53,7 +53,7 @@ struct Camera* scene_camera_find(struct Scene* scene, const char* name); struct Static_Mesh* scene_static_mesh_find(struct Scene* scene, const char* name); struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* name); struct Entity* scene_base_entity_get(struct Scene* scene, int id, int type); -struct Enemy* scene_enemy_get(struct Scene* scene, const char* name); +struct Enemy* scene_enemy_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 7397bc4..84bafad 100644 --- a/todo.txt +++ b/todo.txt @@ -1,8 +1,6 @@ Todo: - Implement separate property window for player related variables that can be shown in the editor similar to renderer settings etc - Add all sound source properties to propery inspector - - Add turret properties to property inspector - - Add another ambient sound_source entity as child to enemy entity - Fix rotate gizmo's origin not being set to the selected entity - Player shooting - Player jump cooldown, don't allow jump until a certian time interval has passed, even if we're grounded @@ -414,4 +412,6 @@ Done: * Introduced fixed time step interval which can be configured and be used for movement and other physics related updates * Made movement framerate independent * Implement turret state machine - * Fix Turret losing target at diagonals \ No newline at end of file + * Fix Turret losing target at diagonals + * Add turret properties to property inspector + * Add another ambient sound_source entity as child to enemy entity \ No newline at end of file