123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- extends RigidBody3D
- const ACCEL = 5.0
- const DEACCEL = 20.0
- const MAX_SPEED = 2.0
- const ROT_SPEED = 1.0
- var prev_advance := false
- var dying := false
- var rot_dir = 4
- @onready var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") \
- * ProjectSettings.get_setting("physics/3d/default_gravity_vector")
- @onready var _animation_player := $Enemy/AnimationPlayer as AnimationPlayer
- @onready var _ray_floor := $Enemy/Skeleton/RayFloor as RayCast3D
- @onready var _ray_wall := $Enemy/Skeleton/RayWall as RayCast3D
- func _integrate_forces(state: PhysicsDirectBodyState3D):
- var delta := state.get_step()
- var lin_velocity := state.get_linear_velocity()
- var grav := state.get_total_gravity()
- # get_total_gravity returns zero for the first few frames, leading to errors.
- if grav.is_zero_approx():
- grav = self.gravity
- lin_velocity += grav * delta # Apply gravity.
- var up := -grav.normalized()
- if dying:
- state.set_linear_velocity(lin_velocity)
- return
- for i in state.get_contact_count():
- var contact_collider := state.get_contact_collider_object(i)
- var contact_normal := state.get_contact_local_normal(i)
- if is_instance_valid(contact_collider):
- if contact_collider is Bullet and contact_collider.enabled:
- dying = true
- axis_lock_angular_x = false
- axis_lock_angular_y = false
- axis_lock_angular_z = false
- collision_layer = 0
- state.set_angular_velocity(-contact_normal.cross(up).normalized() * 33.0)
- _animation_player.play(&"impact")
- _animation_player.queue(&"extra/explode")
- contact_collider.enabled = false
- $SoundWalkLoop.stop()
- $SoundHit.play()
- return
- var advance := _ray_floor.is_colliding() and not _ray_wall.is_colliding()
- var dir := ($Enemy/Skeleton as Node3D).get_transform().basis[2].normalized()
- var deaccel_dir := dir
- if advance:
- if dir.dot(lin_velocity) < MAX_SPEED:
- lin_velocity += dir * ACCEL * delta
- deaccel_dir = dir.cross(gravity).normalized()
- else:
- if prev_advance:
- rot_dir = 1
- dir = Basis(up, rot_dir * ROT_SPEED * (delta)) * dir
- $Enemy/Skeleton.set_transform(Transform3D().looking_at(-dir, up))
- var dspeed := deaccel_dir.dot(lin_velocity)
- dspeed -= DEACCEL * delta
- if dspeed < 0:
- dspeed = 0
- lin_velocity = lin_velocity - deaccel_dir * deaccel_dir.dot(lin_velocity) \
- + deaccel_dir * dspeed
- state.set_linear_velocity(lin_velocity)
- prev_advance = advance
- func _die():
- queue_free()
|