Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | equus |
Edit 2: I noticed I forgot an operator that I put in the actual code of enemy, when calculating the angle, but I did not put it here in the question. I updated the line now.
Edit: added code of ai_controller.gd, enemy shoot code and methods used in shoot code.
Hello!
I’m making a shooter game and I want to enemies fire bullets at a predicted player position. The enemies need to rotate to that position. My code was working when I made it for 2d, but I changed the game to a 3D view. I still using 2d for all the calculations. My approach was to keep z positions locked in -10 for all the objects that need calculations. So, I’m using only x and y to make the calculations and ignoring z positions (because all z positions are the same). I’m keeping the rotations only in z axis. After doing all this, the enemy started to miss the target. I researched a lot but I did not find an answer.
I’m using Godot 2.1.5
Here is the code:
------------ Code in ai_controller.gd------------
func _fixed_process(p_delta):
ai_movement_process(_enemies_type_1)
for enemy1 in _enemies_type_1:
var current_enemy = enemy1.get_ref()
if current_enemy:
# This is the only method that changes rotation
current_enemy.update_rotation(p_delta)
```
current_enemy.check_player_distance_to_shoot()
if current_enemy.Fa != null:
current_enemy.update_ship_velocity()
current_enemy.reduce_player_speed_if_close_to()
var new_pos = current_enemy.get_global_2d_pos() + current_enemy.current_velocity * p_delta
if new_pos.x < 0:
new_pos.x = 0
elif new_pos.x > 5000:
new_pos.x = 5000
if new_pos.y < 0:
new_pos.y = 0
elif new_pos.y > 5000:
new_pos.y = 5000
current_enemy.set_global_2d_pos(new_pos)
```
------------Code in enemy.gd------------
extends Spatial
func _rotate_to_target(p_delta, p_target_player):
if p_target_player == null:
return
var the_tplayer = p_target_player.get_ref()
if !the_tplayer:
return
target_p_pos = _global_node.get_projectile_future_point(_shoot_from_node.get_global_2d_pos(), \
laser_shot_speed, the_tplayer.get_global_2d_pos(), the_tplayer.current_velocity)
var my_pos = get_global_2d_pos()
var ang = -(target_p_pos - my_pos).angle()
# Now I'm setting the angle straight
set_2d_rot(ang)
# I was using interpolation but it didn't worked either
set_2d_rot(lerp_angle(get_2d_rot(), ang, rotation_velocity * p_delta))
func shoot(p_weapon):
var the_laser = _laser_scn.instance()
the_laser.w_damage = laser_shot_damage
the_laser.w_fire_rate = laser_shot_fire_rate
the_laser.w_speed = laser_shot_speed
the_laser.w_range = laser_shot_range
_node_to_attach_weapons_node.add_child(the_laser)
var start_pos = _shoot_from_node.get_global_3d_pos()
the_laser.set_global_3d_pos(start_pos)
the_laser.start_position = Vector2(start_pos.x, start_pos.y)
the_laser.set_2d_rot(get_2d_rot())
_can_shoot_laser = false
_timer_laser_fire_rate.start()
------------https://forum.godotengine.org-28776/rotate-kinematicbody2d-based-mouse-position-varying-rate------------
func lerp_angle(p_start, p_end, p_delta): #In radians
if abs(p_start - p_end) >= PI:
if p_start > p_end:
p_end += 2 * PI
else:
p_start += 2 * PI
return lerp(p_start, p_end, p_delta)
------------Code in player.gd and enemy.gd and all objects that need position and rotation calculations in 2d------------
func get_global_2d_pos():
var pos = get_global_transform().origin
return Vector2(pos.x, pos.y)
func get_global_3d_pos():
return get_global_transform().origin
func set_global_3d_pos(p_position):
set_global_transform(Transform(get_global_transform().basis, p_position))
func get_2d_rot():
return get_rotation().z
func set_2d_rot(p_rotation):
set_rotation(Vector3(get_rotation().x, get_rotation().y, p_rotation))
------------Code in _global_node------------
func get_projectile_future_point(p_my_position, p_projectile_velocity, p_target_position, p_target_velocity):
var target_dir = (p_target_position - p_my_position).normalized()
var target_vel_ortho = p_target_velocity.dot(target_dir) * target_dir
var target_vel_tang = p_target_velocity - target_vel_ortho
var shot_vel_tang = target_vel_tang
var shot_speed = shot_vel_tang.length()
var direction = Vector2()
if shot_speed > p_projectile_velocity.length():
direction = p_target_velocity.normalized() * shot_speed
else:
var shot_speed_ortho = sqrt(p_projectile_velocity.length() * p_projectile_velocity.length() - shot_speed * shot_speed)
var shot_vel_ortho = target_dir * shot_speed_ortho
direction = shot_vel_ortho + shot_vel_tang
var pos_norm = (p_my_position - p_target_position).length()
var time_to_collision = pos_norm
if p_projectile_velocity.length() > p_target_velocity.length():
time_to_collision /= (p_projectile_velocity.length() - p_target_velocity.length())
else:
time_to_collision /= p_projectile_velocity.length()
var shot_velocity = direction
var collision_point = p_my_position + shot_velocity * time_to_collision
return collision_point
Thanks in advance! =)
Edit: the code is not working after I changed some parameters. I don’t know why.
It is working now. I think I modified some code and forgot that I had modified. I’m seeing the spaceships hitting the player most of times. I remember it was little different when I was using 2d but it is working pretty close of what I wanted to it works. I changed some parameters when I started using 3d and I think the difference I’m seeing now is because of this.
Thanks for the people who helped in facebook group.
equus | 2018-12-13 18:44