175 lines
5.0 KiB
GDScript
175 lines
5.0 KiB
GDScript
extends CharacterBody2D
|
|
|
|
|
|
enum States {
|
|
WALKING,
|
|
PANIC,
|
|
WAITING
|
|
}
|
|
|
|
@export var min_state_dur: float
|
|
@export var max_state_dur: float
|
|
@export var min_time_till_attack: float
|
|
@export var max_time_till_attack: float
|
|
@export var min_attack_duration: float
|
|
@export var max_attack_duration: float
|
|
@export var walk_speed: float
|
|
@export var panic_speed: float
|
|
@export var seagull_speed: float
|
|
|
|
@onready var is_attacked: bool = false # I shouldve made these an enum tbh
|
|
@onready var attack_approaching: bool = false
|
|
@onready var is_retreating: bool = false
|
|
@onready var walk_dir = Vector2.ZERO
|
|
@onready var is_flipped: bool = false
|
|
@onready var seagull_is_flipped: bool = false
|
|
@onready var seagull_dir = Vector2.ZERO
|
|
@onready var seagull_home_pos = Vector2.ZERO
|
|
@onready var received_biscuit: bool = false
|
|
|
|
var time_till_attacked: float
|
|
var time_till_abducted: float
|
|
var current_state: States
|
|
var state_duration: float
|
|
|
|
|
|
func _ready():
|
|
time_till_attacked = randf_range(min_time_till_attack, max_time_till_attack)
|
|
change_walk_dir()
|
|
new_state()
|
|
|
|
|
|
func _physics_process(delta: float):
|
|
if !is_attacked:
|
|
match current_state:
|
|
States.WALKING: act_walking(delta)
|
|
States.PANIC: act_walking(delta, true)
|
|
States.WAITING:
|
|
if !$PigAnimations.current_animation == "flip":
|
|
$PigAnimations.stop()
|
|
else:
|
|
if time_till_abducted > 0: act_walking(delta, true)
|
|
else: pass
|
|
|
|
attack_logic(delta)
|
|
|
|
if walk_dir.x < 0 && !is_flipped:
|
|
$PigAnimations.play("flip")
|
|
is_flipped = true
|
|
elif walk_dir.x > 0 && is_flipped:
|
|
$PigAnimations.play_backwards("flip")
|
|
is_flipped = false
|
|
|
|
state_duration -= delta
|
|
if time_till_attacked > 0: time_till_attacked -= delta
|
|
if state_duration <= 0.0: new_state()
|
|
|
|
|
|
func new_state():
|
|
state_duration = randf_range(min_state_dur, max_state_dur)
|
|
var next_state = randi_range(0, States.size() - 1)
|
|
|
|
if next_state == States.PANIC && randf() < 0.95:
|
|
next_state = States.WALKING if randi_range(0, 1) == 0 else States.WAITING
|
|
|
|
current_state = States.values()[next_state]
|
|
|
|
|
|
func act_walking(delta: float, panicked: bool = false):
|
|
var average_time_to_switch_dir: float = 2.0 if !panicked else 0.2
|
|
var should_switch_dir = randf() < delta / average_time_to_switch_dir
|
|
if should_switch_dir: change_walk_dir()
|
|
self.velocity = walk_dir * (walk_speed if !panicked else panic_speed)
|
|
self.move_and_slide()
|
|
if !$PigAnimations.current_animation == "flip":
|
|
$PigAnimations.play("walk")
|
|
|
|
|
|
func change_walk_dir():
|
|
walk_dir = Vector2(
|
|
randf_range(-1, 1),
|
|
randf_range(-1, 1)
|
|
).normalized()
|
|
|
|
|
|
func attack_logic(delta: float):
|
|
if time_till_attacked <= 0.0 && !(is_attacked || attack_approaching || is_retreating):
|
|
attack_approaching = true
|
|
seagull_home_pos = Vector2(
|
|
randf_range(-3000.0, 3000.0),
|
|
randf_range(-1920.0, -2500.0)
|
|
)
|
|
$Seagull.global_position = seagull_home_pos
|
|
$Seagull.visible = true
|
|
$Seagull.play("fly")
|
|
|
|
attack_approaching_logic(delta)
|
|
is_attacked_logic(delta)
|
|
retreating_logic(delta)
|
|
|
|
if seagull_dir.x < 0 && !seagull_is_flipped:
|
|
$SeagullAnimations.play("flip")
|
|
seagull_is_flipped = true
|
|
elif seagull_dir.x > 0 && seagull_is_flipped:
|
|
$SeagullAnimations.play_backwards("flip")
|
|
seagull_is_flipped = false
|
|
|
|
|
|
func attack_approaching_logic(delta: float):
|
|
if !attack_approaching: return
|
|
|
|
seagull_dir = ($PigSprite/SeagullAttackPos.global_position - $Seagull.global_position).normalized()
|
|
|
|
$Seagull.global_position += seagull_dir * seagull_speed * delta
|
|
|
|
var dist = $Seagull.global_position.distance_to($PigSprite/SeagullAttackPos.global_position)
|
|
if dist < 15.0:
|
|
$Seagull.global_position = $PigSprite/SeagullAttackPos.global_position
|
|
attack_approaching = false
|
|
is_attacked = true
|
|
$Seagull.play("attack")
|
|
if !$PigAnimations.current_animation == "flip": $PigAnimations.stop()
|
|
time_till_abducted = randf_range(min_attack_duration, max_attack_duration)
|
|
|
|
|
|
func is_attacked_logic(delta: float):
|
|
if !is_attacked: return
|
|
|
|
if time_till_abducted <= 0.0:
|
|
seagull_dir = (seagull_home_pos - $Seagull.global_position).normalized()
|
|
self.global_position += seagull_dir * seagull_speed * delta
|
|
$PigSprite.self_modulate.a = 0.5
|
|
$Collision.disabled = true
|
|
|
|
if self.global_position.y < -get_viewport_rect().size.y - 300.0:
|
|
get_tree().current_scene.pigs_abducted += 1
|
|
get_parent().remove_child(self)
|
|
|
|
if received_biscuit:
|
|
is_attacked = false
|
|
received_biscuit = false
|
|
is_retreating = true
|
|
get_tree().current_scene.pigs_saved += 1
|
|
|
|
time_till_abducted -= delta
|
|
|
|
|
|
func retreating_logic(delta: float):
|
|
if !is_retreating: return
|
|
|
|
seagull_dir = (seagull_home_pos - $Seagull.global_position).normalized()
|
|
$Seagull.global_position += seagull_dir * seagull_speed * delta
|
|
|
|
if $Seagull.global_position.y < -get_viewport_rect().size.y - 300.0:
|
|
is_retreating = false
|
|
$Seagull.global_position = seagull_home_pos
|
|
|
|
|
|
func _on_feed_zone_body_entered(body: Node2D):
|
|
if body is not CharacterBody2D: return
|
|
if body.name != "PlayerCharacter": return
|
|
|
|
if is_attacked && body.biscuit_count > 0 && time_till_abducted > 0.0:
|
|
received_biscuit = true
|
|
body.remove_biscuit()
|