gai-godot-games/state/scenes/state/SMCharacter.gd

110 lines
3.2 KiB
GDScript

extends CharacterBody2D
@onready var state_machine: StateMachine = $StateMachine
#
@onready var sprite: Node = $Sprite2D
#
const MAX_SPEED: float = 150.0
const MAX_ACCELERATION: float = 300.0
const SLOWING_RADIUS: float = 80.0
const SHAKE_INTENSITY: float = 8.0
const ROTATION_SPEED: float = 5.0 # adians per second
#
@onready var detection_area: Area2D = $VisionCone
signal waste_detected(waste)
#
var battery_charge: float = 100.0
const battery_charge_drain_per_second: float = 5.0
const battery_charge_recharge_per_second: float = 30.0
# carry item
var carry_item: Node2D = null
func _ready() -> void:
pass
# detection_area.body_entered.connect(Callable(self, "_on_body_entered"))
# detection_area.area_entered.connect(Callable(self, "_on_area_entered"))
# func _on_body_entered(body):
# if body.is_in_group("waste"):
# emit_signal("waste_detected", body)
# func _on_area_entered(area):
# if area.is_in_group("waste"):
# emit_signal("waste_detected", area)
func _draw() -> void:
if velocity.length() > 0.1:
var local_velocity: Vector2 = global_transform.basis_xform_inv(velocity.normalized() * 400)
draw_line(Vector2.ZERO, local_velocity, Color(1, 0, 0), 2)
func _process(delta: float) -> void:
battery_charge -= battery_charge_drain_per_second * delta
%StateMachineInfoPanel.values["battery_charge"] = battery_charge
if carry_item:
# put the carry_item on the character
carry_item.position = position
func _physics_process(delta: float) -> void:
rotate_towards_velocity(delta)
detect_waste()
queue_redraw()
func detect_waste() -> void:
var overlapping_bodies: Array[Node2D] = detection_area.get_overlapping_bodies()
for body in overlapping_bodies:
if body.is_in_group("waste"):
emit_signal("waste_detected", body)
func move_towards(target: Vector2, delta: float) -> void:
var to_target: Vector2 = target - position
var distance: float = to_target.length()
if distance < 5.0:
velocity = Vector2.ZERO
return
var desired_speed: float = MAX_SPEED
if distance < SLOWING_RADIUS:
desired_speed = lerp(0, int(MAX_SPEED), distance / SLOWING_RADIUS)
var desired_velocity: Vector2 = to_target.normalized() * desired_speed
var steering: Vector2 = desired_velocity - velocity
var steering_length: float = steering.length()
if steering_length > MAX_ACCELERATION * delta:
steering = steering.normalized() * MAX_ACCELERATION * delta
velocity += steering
if velocity.length() > 0.1:
var shake: Vector2 = Vector2(
rand_range(-SHAKE_INTENSITY, SHAKE_INTENSITY),
rand_range(-SHAKE_INTENSITY, SHAKE_INTENSITY)
)
velocity += shake
if velocity.length() > MAX_SPEED:
velocity = velocity.normalized() * MAX_SPEED
func rotate_towards_velocity(delta: float) -> void:
if velocity.length() > 0.1:
var target_angle: float = velocity.angle()
rotation = lerp_angle(rotation, target_angle, ROTATION_SPEED * delta)
sprite.rotation = -rotation
func rand_range(min: float, max: float) -> float:
return randf() * (max - min) + min