mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-16 05:20:06 +01:00
86 lines
2.5 KiB
GDScript
86 lines
2.5 KiB
GDScript
extends RigidBody3D
|
|
|
|
|
|
const ACCEL: float = 5.0
|
|
const DEACCEL: float = 20.0
|
|
const MAX_SPEED: float = 2.0
|
|
const ROT_SPEED: float = 1.0
|
|
|
|
var prev_advance: bool = false
|
|
var dying: bool = false
|
|
var rot_dir: float = 4.0
|
|
|
|
@onready var gravity := Vector3(
|
|
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) -> void:
|
|
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 = 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: bool = _ray_floor.is_colliding() and not _ray_wall.is_colliding()
|
|
|
|
var dir: Vector3 = ($Enemy/Skeleton as Node3D).get_transform().basis.z.normalized()
|
|
var deaccel_dir: Vector3 = 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: float = 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() -> void:
|
|
queue_free()
|