Added aqcuire target state to turret

dev
Shariq Shah 6 years ago
parent 10727fbc33
commit 2ebd4feac4
  1. 20
      assets/scenes/Level_1.symtres
  2. 6
      src/common/linmath.c
  3. 1
      src/common/linmath.h
  4. 2
      src/common/version.h
  5. 2
      src/game/editor.c
  6. 149
      src/game/enemy.c
  7. 1
      src/game/enemy.h
  8. 9
      src/game/entity.h
  9. 5
      todo.txt

@ -16,12 +16,12 @@ Player
{ {
type : 2 type : 2
scale : 1.000 1.000 1.000 scale : 1.000 1.000 1.000
rotation : 0.000 0.102 0.000 -0.997 rotation : 0.000 0.971 0.000 -0.249
active : true active : true
position : -8.511 2.857 27.549 position : -30.395 2.857 -17.708
bouding_box_min : -0.500 -0.500 -0.500 bouding_box_min : -1.500 -1.500 -1.000
name : Player name : Player
bouding_box_max : 0.500 0.500 0.500 bouding_box_max : 1.500 1.500 1.000
camera_clear_color : 0.310 0.412 0.529 1.000 camera_clear_color : 0.310 0.412 0.529 1.000
} }
@ -127,7 +127,7 @@ Scene_Entity_Entry
Scene_Entity_Entry Scene_Entity_Entry
{ {
scale : 1.000 1.000 1.000 scale : 1.000 1.000 1.000
rotation : 0.000 -0.158 0.000 0.988 rotation : 0.000 0.001 0.000 1.001
position : 0.000 3.000 0.000 position : 0.000 3.000 0.000
filename : turret filename : turret
name : Turret name : Turret
@ -136,7 +136,7 @@ Scene_Entity_Entry
Scene_Entity_Entry Scene_Entity_Entry
{ {
scale : 1.000 1.000 1.000 scale : 1.000 1.000 1.000
rotation : 0.000 0.001 0.000 1.000 rotation : 0.000 -0.348 0.000 0.938
position : -13.000 3.000 4.000 position : -13.000 3.000 4.000
filename : turret filename : turret
name : Turret name : Turret
@ -145,8 +145,8 @@ Scene_Entity_Entry
Scene_Entity_Entry Scene_Entity_Entry
{ {
scale : 1.000 1.000 1.000 scale : 1.000 1.000 1.000
rotation : 0.000 0.005 0.000 1.000 rotation : 0.000 -0.002 0.000 1.000
position : 12.000 3.000 6.000 position : -33.000 3.000 8.000
filename : turret filename : turret
name : Turret name : Turret
} }
@ -154,7 +154,7 @@ Scene_Entity_Entry
Scene_Entity_Entry Scene_Entity_Entry
{ {
scale : 1.000 1.000 1.000 scale : 1.000 1.000 1.000
rotation : 0.000 -0.450 0.000 0.893 rotation : 0.000 -0.288 0.000 0.958
position : -7.000 3.000 2.000 position : -7.000 3.000 2.000
filename : turret filename : turret
name : Turret name : Turret
@ -163,7 +163,7 @@ Scene_Entity_Entry
Scene_Entity_Entry Scene_Entity_Entry
{ {
scale : 1.000 1.000 1.000 scale : 1.000 1.000 1.000
rotation : 0.000 0.423 0.000 0.906 rotation : 0.000 0.000 0.000 1.000
position : 5.000 3.000 6.000 position : 5.000 3.000 6.000
filename : turret filename : turret
name : Turret name : Turret

@ -204,6 +204,12 @@ float vec3_dot(vec3* v1, vec3* v2)
v1->z * v2->z); v1->z * v2->z);
} }
float vec3_angle(vec3* dir1, vec3* dir2)
{
float dot = vec3_dot(dir1, dir2);
return TO_DEGREES(acosf(dot));
}
void vec4_fill(vec4* res, float x, float y, float z, float w) void vec4_fill(vec4* res, float x, float y, float z, float w)
{ {

@ -91,6 +91,7 @@ int vec3_equals(vec3* v1, vec3* v2);
float vec3_len(vec3* val); float vec3_len(vec3* val);
float vec3_distance(vec3 p1, vec3 p2); float vec3_distance(vec3 p1, vec3 p2);
float vec3_dot(vec3* v1, vec3* v2); float vec3_dot(vec3* v1, vec3* v2);
float vec3_angle(vec3* dir1, vec3* dir2);
/* vec4 */ /* vec4 */
int vec4_equals(vec4* v1, vec4* v2); int vec4_equals(vec4* v1, vec4* v2);

@ -4,7 +4,7 @@
/* Auto generated version file. DO NOT MODIFY */ /* Auto generated version file. DO NOT MODIFY */
#define SYMMETRY_VERSION_MAJOR 0 #define SYMMETRY_VERSION_MAJOR 0
#define SYMMETRY_VERSION_MINOR 1 #define SYMMETRY_VERSION_MINOR 1
#define SYMMETRY_VERSION_REVISION 321 #define SYMMETRY_VERSION_REVISION 322
#define SYMMETRY_VERSION_BRANCH "dev" #define SYMMETRY_VERSION_BRANCH "dev"
#endif #endif

@ -2226,7 +2226,7 @@ void editor_window_property_inspector(struct nk_context* context, struct Editor*
{ {
case ENEMY_TURRET: case ENEMY_TURRET:
{ {
nk_property_float(context, "Turn Speed", 0.f, &enemy->Turret.turn_speed, FLT_MAX, 0.5f, 0.1f); nk_property_float(context, "Turn Speed", 0.f, &enemy->Turret.turn_speed_default, FLT_MAX, 0.5f, 0.1f);
} }
break; break;
} }

@ -34,22 +34,25 @@ void enemy_init(struct Enemy* enemy, int type)
{ {
case ENEMY_TURRET: case ENEMY_TURRET:
{ {
enemy->health = 100; enemy->health = 100;
enemy->damage = 10; enemy->damage = 10;
enemy->Turret.turn_direction_positive = true; enemy->Turret.yaw_direction_positive = true;
enemy->Turret.scan = false; enemy->Turret.scan = false;
enemy->Turret.turn_speed = 10.f; enemy->Turret.turn_speed_default = 50.f;
enemy->Turret.max_turn_angle = 60.f; enemy->Turret.turn_speed_when_targetting = 100.f;
enemy->Turret.pulsate_height = 1.5f; enemy->Turret.turn_speed_current = enemy->Turret.turn_speed_default;
enemy->Turret.pulsate_speed_scale = 0.1f; enemy->Turret.max_yaw = 60.f;
enemy->Turret.attack_cooldown = 0.05f; enemy->Turret.target_yaw = 0.f;
enemy->Turret.alert_cooldown = 1.f; enemy->Turret.pulsate_height = 1.5f;
enemy->Turret.color_default = (vec4){ 0.f, 1.f, 1.f, 1.f }; enemy->Turret.pulsate_speed_scale = 0.1f;
enemy->Turret.color_alert = (vec4){ 1.f, 1.f, 0.f, 1.f }; enemy->Turret.attack_cooldown = 0.05f;
enemy->Turret.color_attack = (vec4){ 1.f, 0.f, 0.f, 1.f }; enemy->Turret.alert_cooldown = 1.f;
enemy->Turret.time_elapsed_since_alert = 0.f; enemy->Turret.color_default = (vec4){ 0.f, 1.f, 1.f, 1.f };
enemy->Turret.time_elapsed_since_attack = 0.f; enemy->Turret.color_alert = (vec4){ 1.f, 1.f, 0.f, 1.f };
enemy->Turret.vision_range = 15.f; enemy->Turret.color_attack = (vec4){ 1.f, 0.f, 0.f, 1.f };
enemy->Turret.time_elapsed_since_alert = 0.f;
enemy->Turret.time_elapsed_since_attack = 0.f;
enemy->Turret.vision_range = 15.f;
} }
break; break;
default: default:
@ -83,7 +86,7 @@ void enemy_static_mesh_set(struct Enemy* enemy, const char* geometry_filename, i
void enemy_update(struct Enemy* enemy, struct Scene* scene, float dt) void enemy_update(struct Enemy* enemy, struct Scene* scene, float dt)
{ {
static float enemy_update_interval = 1.f / 120.f; static float enemy_update_interval = 1.f / 60.f;
static float time_elapsed_since_last_update = 0.f; static float time_elapsed_since_last_update = 0.f;
time_elapsed_since_last_update += dt; time_elapsed_since_last_update += dt;
@ -140,9 +143,9 @@ struct Enemy* enemy_read(struct Parser_Object* object, const char* name, struct
{ {
case ENEMY_TURRET: case ENEMY_TURRET:
{ {
if(hashmap_value_exists(object->data, "turn_speed")) new_enemy->Turret.turn_speed = hashmap_float_get(object->data, "turn_speed"); 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_turn_angle = hashmap_float_get(object->data, "max_turn_angle"); 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_direction_positive")) new_enemy->Turret.turn_direction_positive = hashmap_bool_get(object->data, "turn_direction_positive"); if(hashmap_value_exists(object->data, "turn_direction_positive")) new_enemy->Turret.yaw_direction_positive = hashmap_bool_get(object->data, "turn_direction_positive");
} }
break; break;
} }
@ -160,9 +163,9 @@ void enemy_write(struct Enemy* enemy, struct Hashmap* entity_data)
{ {
case ENEMY_TURRET: case ENEMY_TURRET:
{ {
hashmap_float_set(entity_data, "turn_speed", enemy->Turret.turn_speed); hashmap_float_set(entity_data, "turn_speed", enemy->Turret.turn_speed_default);
hashmap_float_set(entity_data, "max_turn_angle", enemy->Turret.max_turn_angle); hashmap_float_set(entity_data, "max_turn_angle", enemy->Turret.max_yaw);
hashmap_bool_set(entity_data, "turn_direction_positive", enemy->Turret.turn_direction_positive); hashmap_bool_set(entity_data, "turn_direction_positive", enemy->Turret.yaw_direction_positive);
} }
break; break;
} }
@ -208,20 +211,20 @@ void enemy_update_physics_turret(struct Enemy* enemy, struct Game_State* game_st
{ {
float current_yaw = quat_get_yaw(&enemy->base.transform.rotation); float current_yaw = quat_get_yaw(&enemy->base.transform.rotation);
float yaw = enemy->Turret.turn_speed * 1.f * fixed_dt; float yaw = enemy->Turret.turn_speed_current * 1.f * fixed_dt;
if(!enemy->Turret.turn_direction_positive) if(!enemy->Turret.yaw_direction_positive)
yaw *= -1.f; yaw *= -1.f;
current_yaw += yaw; current_yaw += yaw;
if(current_yaw >= enemy->Turret.max_turn_angle) if(current_yaw >= enemy->Turret.max_yaw)
{ {
yaw = 0.f; yaw = 0.f;
enemy->Turret.turn_direction_positive = false; enemy->Turret.yaw_direction_positive = false;
} }
else if(current_yaw <= -enemy->Turret.max_turn_angle) else if(current_yaw <= -enemy->Turret.max_yaw)
{ {
yaw = 0.f; yaw = 0.f;
enemy->Turret.turn_direction_positive = true; enemy->Turret.yaw_direction_positive = true;
} }
if(yaw != 0.f) if(yaw != 0.f)
@ -229,11 +232,15 @@ void enemy_update_physics_turret(struct Enemy* enemy, struct Game_State* game_st
} }
else if(!enemy->Turret.scan) else if(!enemy->Turret.scan)
{ {
float epsilon = 0.5f;
float current_yaw = quat_get_yaw(&enemy->base.transform.rotation); float current_yaw = quat_get_yaw(&enemy->base.transform.rotation);
if(fabsf(current_yaw) + EPSILON != 0.f) 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)
{ {
float yaw = enemy->Turret.turn_speed * 1.f * fixed_dt; //log_message("Difference %.5f", difference);
if(current_yaw > 0.f) float yaw = enemy->Turret.turn_speed_current * 1.f * fixed_dt;
if(current_yaw > enemy->Turret.target_yaw)
yaw *= -1.f; yaw *= -1.f;
transform_rotate(enemy, &yaw_axis, yaw, TS_LOCAL); transform_rotate(enemy, &yaw_axis, yaw, TS_LOCAL);
@ -297,6 +304,59 @@ void enemy_update_ai_turret(struct Enemy* enemy, struct Game_State* game_state,
} }
} }
break; break;
case TURRET_ACQUIRE_TARGET:
{
struct Entity* player = scene_ray_intersect_closest(scene, &turret_ray, ERM_PLAYER);
if(player)
{
float distance = scene_entity_distance(scene, &scene->player, enemy);
if(distance <= enemy->Turret.vision_range)
{
enemy_state_set_turret(enemy, TURRET_ATTACK);
break;
}
}
float distance = scene_entity_distance(scene, &scene->player, enemy);
if(distance <= enemy->Turret.vision_range)
{
vec3 player_pos = { 0.f };
transform_get_absolute_position(&scene->player, &player_pos);
vec3 dir_to_player = { 0.f };
turret_ray.origin.y = 0.f;
player_pos.y = 0.f;
vec3_sub(&dir_to_player, &player_pos, &turret_ray.origin);
vec3_norm(&dir_to_player, &dir_to_player);
im_ray_origin_dir(turret_ray.origin, dir_to_player, 10.f, (vec4) { 0.f, 1.f, 0.f, 1.f }, 5);
//dir_to_player.y = 0.f;
//turret_ray.direction.y = 0.f;
float yaw_required_to_face_player = vec3_angle(&dir_to_player, &turret_ray.direction);
float current_yaw = quat_get_yaw(&enemy->base.transform.rotation);
debug_vars_show_float("Yaw Required", yaw_required_to_face_player);
float new_target_yaw = yaw_required_to_face_player + current_yaw;
if(fabsf(new_target_yaw) > enemy->Turret.max_yaw)
{
log_message("Can't face player");
log_message("New Yaw : %.3f", new_target_yaw);
log_message("Max yaw : %.3f", enemy->Turret.max_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
{
float difference = fabsf(enemy->Turret.target_yaw - new_target_yaw);
if(difference > 1.f)
enemy->Turret.target_yaw = new_target_yaw;
}
}
else
{
log_message("No target in range");
enemy_state_set_turret(enemy, TURRET_ALERT);
}
}
break;
case TURRET_ATTACK: case TURRET_ATTACK:
{ {
enemy->Turret.time_elapsed_since_attack += dt; enemy->Turret.time_elapsed_since_attack += dt;
@ -304,7 +364,6 @@ void enemy_update_ai_turret(struct Enemy* enemy, struct Game_State* game_state,
{ {
im_ray(&turret_ray, enemy->Turret.vision_range, enemy->Turret.color_attack, 4); im_ray(&turret_ray, enemy->Turret.vision_range, enemy->Turret.color_attack, 4);
struct Entity* player = scene_ray_intersect_closest(scene, &turret_ray, ERM_PLAYER); struct Entity* player = scene_ray_intersect_closest(scene, &turret_ray, ERM_PLAYER);
bool target_lost = false;
if(player) if(player)
{ {
float distance = scene_entity_distance(scene, player, enemy); float distance = scene_entity_distance(scene, player, enemy);
@ -316,18 +375,13 @@ void enemy_update_ai_turret(struct Enemy* enemy, struct Game_State* game_state,
} }
else else
{ {
target_lost = true; enemy_state_set_turret(enemy, TURRET_ACQUIRE_TARGET);
log_message("Target too far");
} }
} }
else else
{ {
target_lost = true; enemy_state_set_turret(enemy, TURRET_ACQUIRE_TARGET);
}
if(target_lost)
{
enemy_state_set_turret(enemy, TURRET_ALERT);
log_message("Target lost");
} }
} }
} }
@ -350,6 +404,8 @@ void enemy_state_set_turret(struct Enemy* enemy, int state)
enemy->Turret.time_elapsed_since_attack = 0.f; enemy->Turret.time_elapsed_since_attack = 0.f;
enemy->Turret.pulsate = true; enemy->Turret.pulsate = true;
enemy->Turret.scan = false; enemy->Turret.scan = false;
enemy->Turret.target_yaw = 0.f;
enemy->Turret.turn_speed_current = enemy->Turret.turn_speed_default;
vec3 default_position = { 0.f }; vec3 default_position = { 0.f };
transform_set_position(enemy->mesh, &default_position); transform_set_position(enemy->mesh, &default_position);
} }
@ -357,17 +413,26 @@ void enemy_state_set_turret(struct Enemy* enemy, int state)
case TURRET_ALERT: case TURRET_ALERT:
{ {
enemy->Turret.pulsate = false; enemy->Turret.pulsate = false;
enemy->Turret.turn_speed_current = enemy->Turret.turn_speed_default;
enemy->Turret.scan = true; enemy->Turret.scan = true;
enemy->Turret.target_yaw = enemy->Turret.yaw_direction_positive ? enemy->Turret.max_yaw : -enemy->Turret.max_yaw;
vec4_assign(&model->material_params[MMP_DIFFUSE_COL].val_vec4, &enemy->Turret.color_alert); vec4_assign(&model->material_params[MMP_DIFFUSE_COL].val_vec4, &enemy->Turret.color_alert);
enemy->Turret.time_elapsed_since_alert = 0.f; enemy->Turret.time_elapsed_since_alert = 0.f;
} }
break; break;
case TURRET_ACQUIRE_TARGET:
{
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;
}
break;
case TURRET_ATTACK: case TURRET_ATTACK:
{ {
enemy->Turret.pulsate = false; enemy->Turret.pulsate = false;
enemy->Turret.scan = false; enemy->Turret.scan = false;
vec4_assign(&model->material_params[MMP_DIFFUSE_COL].val_vec4, &enemy->Turret.color_attack); vec4_assign(&model->material_params[MMP_DIFFUSE_COL].val_vec4, &enemy->Turret.color_attack);
enemy->Turret.time_elapsed_since_attack = 0.f; enemy->Turret.time_elapsed_since_attack = enemy->Turret.attack_cooldown;
} }
break; break;
} }

@ -11,6 +11,7 @@ enum Turret_State
{ {
TURRET_DEFAULT = 0, TURRET_DEFAULT = 0,
TURRET_ALERT, TURRET_ALERT,
TURRET_ACQUIRE_TARGET,
TURRET_ATTACK, TURRET_ATTACK,
TURRET_STATE_MAX TURRET_STATE_MAX
}; };

@ -204,9 +204,12 @@ struct Enemy
{ {
struct struct
{ {
float turn_speed; float turn_speed_default;
float max_turn_angle; float turn_speed_when_targetting;
bool turn_direction_positive; float turn_speed_current;
float max_yaw;
float target_yaw;
bool yaw_direction_positive;
bool pulsate; bool pulsate;
bool scan; bool scan;
float pulsate_speed_scale; float pulsate_speed_scale;

@ -1,11 +1,9 @@
Todo: Todo:
- Implement separate property window for player related variables that can be shown in the editor similar to renderer settings etc - Implement separate property window for player related variables that can be shown in the editor similar to renderer settings etc
- Implement turret state machine
- Add all sound source properties to propery inspector - Add all sound source properties to propery inspector
- Add turret properties to property inspector - Add turret properties to property inspector
- Add another ambient sound_source entity as child to enemy entity - Add another ambient sound_source entity as child to enemy entity
- Fix Turret losing target at diagonals - Fix Turret losing target at diagonals
- Track current height of the turret and return it to default once pulsation resumes
- Fix rotate gizmo's origin not being set to the selected entity - Fix rotate gizmo's origin not being set to the selected entity
- Player shooting - Player shooting
- Player jump cooldown, don't allow jump until a certian time interval has passed, even if we're grounded - Player jump cooldown, don't allow jump until a certian time interval has passed, even if we're grounded
@ -415,4 +413,5 @@ Done:
* Implemented on_load and on_update callbacks for enemies. Different enemy types have different callbacks that are assigned when they are created. * Implemented on_load and on_update callbacks for enemies. Different enemy types have different callbacks that are assigned when they are created.
* Added Scene reload command * Added Scene reload command
* Introduced fixed time step interval which can be configured and be used for movement and other physics related updates * Introduced fixed time step interval which can be configured and be used for movement and other physics related updates
* Made movement framerate independent * Made movement framerate independent
* Implement turret state machine
Loading…
Cancel
Save