enemy.gd 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. extends RigidBody3D
  2. const ACCEL = 5.0
  3. const DEACCEL = 20.0
  4. const MAX_SPEED = 2.0
  5. const ROT_SPEED = 1.0
  6. var prev_advance := false
  7. var dying := false
  8. var rot_dir = 4
  9. @onready var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") \
  10. * ProjectSettings.get_setting("physics/3d/default_gravity_vector")
  11. @onready var _animation_player := $Enemy/AnimationPlayer as AnimationPlayer
  12. @onready var _ray_floor := $Enemy/Skeleton/RayFloor as RayCast3D
  13. @onready var _ray_wall := $Enemy/Skeleton/RayWall as RayCast3D
  14. func _integrate_forces(state: PhysicsDirectBodyState3D):
  15. var delta := state.get_step()
  16. var lin_velocity := state.get_linear_velocity()
  17. var grav := state.get_total_gravity()
  18. # get_total_gravity returns zero for the first few frames, leading to errors.
  19. if grav.is_zero_approx():
  20. grav = self.gravity
  21. lin_velocity += grav * delta # Apply gravity.
  22. var up := -grav.normalized()
  23. if dying:
  24. state.set_linear_velocity(lin_velocity)
  25. return
  26. for i in state.get_contact_count():
  27. var contact_collider := state.get_contact_collider_object(i)
  28. var contact_normal := state.get_contact_local_normal(i)
  29. if is_instance_valid(contact_collider):
  30. if contact_collider is Bullet and contact_collider.enabled:
  31. dying = true
  32. axis_lock_angular_x = false
  33. axis_lock_angular_y = false
  34. axis_lock_angular_z = false
  35. collision_layer = 0
  36. state.set_angular_velocity(-contact_normal.cross(up).normalized() * 33.0)
  37. _animation_player.play(&"impact")
  38. _animation_player.queue(&"extra/explode")
  39. contact_collider.enabled = false
  40. $SoundWalkLoop.stop()
  41. $SoundHit.play()
  42. return
  43. var advance := _ray_floor.is_colliding() and not _ray_wall.is_colliding()
  44. var dir := ($Enemy/Skeleton as Node3D).get_transform().basis[2].normalized()
  45. var deaccel_dir := dir
  46. if advance:
  47. if dir.dot(lin_velocity) < MAX_SPEED:
  48. lin_velocity += dir * ACCEL * delta
  49. deaccel_dir = dir.cross(gravity).normalized()
  50. else:
  51. if prev_advance:
  52. rot_dir = 1
  53. dir = Basis(up, rot_dir * ROT_SPEED * (delta)) * dir
  54. $Enemy/Skeleton.set_transform(Transform3D().looking_at(-dir, up))
  55. var dspeed := deaccel_dir.dot(lin_velocity)
  56. dspeed -= DEACCEL * delta
  57. if dspeed < 0:
  58. dspeed = 0
  59. lin_velocity = lin_velocity - deaccel_dir * deaccel_dir.dot(lin_velocity) \
  60. + deaccel_dir * dspeed
  61. state.set_linear_velocity(lin_velocity)
  62. prev_advance = advance
  63. func _die():
  64. queue_free()