Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | equus |
Hello!
I’m developing a 2d top-down game and I’m having a problem with position, movement and vectors. I created 2 images to illustrate my problem. The player can move and rotate freely and shoot bullets forward. The enemy always rotates to face the player and moves freely regardless of rotation. What I want to do is move the enemy perpendicular to the bullet (when a bullet is near the enemy). I don’t have good math skills so until now I made only enemy movement, rotation and area2d to detect bullet collision. With the current code the enemy sometimes move correctly and sometimes he doesn’t.
My code for the enemy movement (only the parts needed to illustrate my problem):
func _fixed_process(delta):
_rotate_to_target(delta, _player1.get_global_pos())
if _override_direction:
if not _direction_sign_assigned:
# here is my stupid trying to make it works
_direction = Vector2(_area_pos.y, -_area_pos.x)
var right = globals.angle_left_right_or_aligned_to(get_global_pos(), _area_pos)
if right > 0:
_direction_sign = 1
elif right < 0:
_direction_sign = -1
else:
_direction_sign = -1
_direction *= _direction_sign
_direction_sign_assigned = true
velocity = _direction.normalized() * self.max_acceleration
else:
velocity = (target_position - my_pos).normalized() * self.max_acceleration
_acceleration = velocity
_acceleration = _acceleration.clamped(self.max_acceleration)
current_velocity += _acceleration / mass
current_velocity -= current_velocity * friction
current_velocity = current_velocity.clamped(self.max_velocity)
var old_pos = get_pos()
var new_pos = get_pos()
new_pos += current_velocity
set_pos(old_pos.linear_interpolate(new_pos, delta))
# Timer to set movement back to normal behaviour
func _timer_flee_on_timeout():
_override_direction = false
_direction_sign_assigned = false
_timer_flee.stop()
Code for enemy rotation (got from godot answers):
func _rotate_to_target(p_delta, p_target_pos):
var ang = get_angle_to(p_target_pos)
var s = sign(ang)
ang = abs(ang)
var ang_deg = rad2deg(ang)
ang_deg += 10
ang = deg2rad(ang_deg)
rotate(min(ang, rotation_velocity * p_delta) * s)
Code for area2d bullet signal:
func _on_enemy_ship_emergency_flee(p_area):
if not _override_direction:
_area_pos = p_area.get_global_pos()
_enemy_shot = p_area
_override_direction = true
_timer_flee.start()
Code for the function angle_left_right_or_aligned_to (obtained from the web, I don’t remember the source):
# Return:
# negative number if B is left of A
# positive if right of A
# 0 if they are aligned.
func angle_left_right_or_aligned_to(p_va, p_vb):
return -p_va.x * p_vb.y + p_va.y * p_vb.x
PS 1: I’m using Godot 2.1.4.
PS 2: I did a LOT of google search but I couldn’t understand how to solve the problem.
Edit: fixed a bad indentation only in the code here, not in the actual code.
I don’t know about GDscript, but in C# Vector2 has a function called Tangent() which is what you want.
anonymous | 2018-04-02 19:57
Weird. I tested before using that function but it was not working. I must have made a mistake. I rewrote the code as below and it’s working now. Thank you aaronfranke and Warlaan.
var to_bullet = e_shot.get_global_pos() - get_global_pos()
var to_bullet_dir = to_bullet.tangent().normalized()
_direction = to_bullet_dir
velocity = _direction * self.max_acceleration
equus | 2018-04-04 15:51