ft: nucleotide prey FSM
This commit is contained in:
parent
c11afd9ddd
commit
adf1438bc8
|
|
@ -63,7 +63,7 @@ func _on_attack_hit(body: Node2D) -> void:
|
|||
var hit_hittable = false
|
||||
if body.is_in_group("prey") or body.is_in_group("predators"):
|
||||
if body.has_method("handle_damage"):
|
||||
body.handle_damage(damage)
|
||||
body.handle_damage(damage, self)
|
||||
hit_hittable = true
|
||||
elif body.is_in_group("resources"):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
[ext_resource type="Texture2D" uid="uid://c3cuhrmulyy1s" path="res://molecular/assets/background/bg-near.png" id="4_b1jr0"]
|
||||
[ext_resource type="Script" uid="uid://ceut2lrvkns75" path="res://debug_label.gd" id="4_mys4o"]
|
||||
[ext_resource type="Script" uid="uid://umx4w11edif" path="res://molecular/prey_manager.gd" id="5_cthuy"]
|
||||
[ext_resource type="PackedScene" uid="uid://c3iw2v3x6ngrb" path="res://molecular/nucleotide_prey.tscn" id="6_a5cls"]
|
||||
[ext_resource type="PackedScene" uid="uid://c3iw2v3x6ngrb" path="res://molecular/prey/nucleotide_prey.tscn" id="6_a5cls"]
|
||||
|
||||
[sub_resource type="TileMapPattern" id="TileMapPattern_a5cls"]
|
||||
tile_data = PackedInt32Array(0, 65536, 2, 65536, 65536, 3, 1, 131072, 2, 65537, 131072, 3)
|
||||
|
|
@ -108,9 +108,8 @@ text = "Debug: You made it into the game!
|
|||
This is running from C++: "
|
||||
script = ExtResource("4_mys4o")
|
||||
|
||||
[node name="PreyManager" type="Node" parent="." node_paths=PackedStringArray("cam")]
|
||||
[node name="PreyManager" type="Node" parent="."]
|
||||
script = ExtResource("5_cthuy")
|
||||
cam = NodePath("../player/Camera2D")
|
||||
scene = ExtResource("6_a5cls")
|
||||
minCount = 100
|
||||
maxCount = 300
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
extends NucleotidePreyState
|
||||
|
||||
@onready var timer = $Timer
|
||||
var dir: float = 0.0
|
||||
|
||||
func enter(previous_state_path: String, data := {}) -> void:
|
||||
timer.start(randi() % 5)
|
||||
dir = randi() % 360
|
||||
|
||||
func physics_update(_delta: float) -> void:
|
||||
# TODO: move in direction of dir
|
||||
pass
|
||||
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
dir = randi() % 360
|
||||
timer.start(randi() % 5)
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
class_name NucleotidePreyState extends State
|
||||
|
||||
enum State {IDLE, FORAGING, FEEDING, FLEEING}
|
||||
|
||||
func _ready() -> void:
|
||||
await owner.ready
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://c7o7sp02u0wkv
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
extends AbstractPrey2D
|
||||
|
||||
@onready var sprite = get_node("AnimatedSprite2D")
|
||||
@onready var fsm = $StateMachine
|
||||
|
||||
# Mirroed sprites for periodic boundary
|
||||
var mirrorSprite1: Node2D
|
||||
|
|
@ -29,6 +30,7 @@ func _process(delta: float) -> void:
|
|||
|
||||
func _physics_process(delta: float) -> void:
|
||||
#self.move(Vector3(randfn(0, 1), randfn(0, 1), 0))
|
||||
# TODO: state transition logic (bot controller code)
|
||||
pass
|
||||
|
||||
func move(motion: Vector3) -> void:
|
||||
|
|
@ -37,13 +39,14 @@ func move(motion: Vector3) -> void:
|
|||
# Apply boundary to new position
|
||||
position = GameManager.get_boundaried_position(position)
|
||||
|
||||
func handle_damage(dmg: int) -> void:
|
||||
func handle_damage(dmg: int, src: Node) -> void:
|
||||
health = max(0, health-dmg)
|
||||
if health == 0:
|
||||
die()
|
||||
if health < maxHealth:
|
||||
become_injured()
|
||||
|
||||
fsm.transition_to_next_state(fsm.States.FLEEING, {"threat": src})
|
||||
|
||||
func die() -> void:
|
||||
sprite.play("Dying")
|
||||
super.die()
|
||||
|
|
@ -143,3 +146,7 @@ func _handle_wrapping():
|
|||
mirrorSprite3.position = Vector2(0, - GameManager.screen_size.y)
|
||||
|
||||
|
||||
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
pass # Replace with function body.
|
||||
|
|
@ -1,15 +1,17 @@
|
|||
[gd_scene load_steps=12 format=3 uid="uid://c3iw2v3x6ngrb"]
|
||||
[gd_scene load_steps=14 format=3 uid="uid://c3iw2v3x6ngrb"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bvsdg1v3ksixy" path="res://shared/npc/prey2D.tscn" id="1_qvulj"]
|
||||
[ext_resource type="Script" uid="uid://bgossk6xo31gi" path="res://molecular/nucleotide_prey.gd" id="2_0227s"]
|
||||
[ext_resource type="Script" uid="uid://bgossk6xo31gi" path="res://molecular/prey/nucleotide_prey.gd" id="2_0227s"]
|
||||
[ext_resource type="Texture2D" uid="uid://bhcb5g7g7um8" path="res://molecular/assets/prey/prey-dying-frame0.png" id="2_lkj7f"]
|
||||
[ext_resource type="Texture2D" uid="uid://bxn11avw7dykl" path="res://molecular/assets/prey/prey-dying-frame1.png" id="3_svqyr"]
|
||||
[ext_resource type="Texture2D" uid="uid://ctkehsavw6ghx" path="res://molecular/assets/prey/prey-healthy-frame0.png" id="4_ee1gb"]
|
||||
[ext_resource type="Texture2D" uid="uid://uy28y3mkk6nt" path="res://molecular/assets/prey/prey-healthy-frame1.png" id="5_ae5nf"]
|
||||
[ext_resource type="Texture2D" uid="uid://btnyajci8ptb2" path="res://molecular/assets/prey/prey-injured-frame0.png" id="6_0f87h"]
|
||||
[ext_resource type="Texture2D" uid="uid://bqll8ge4cr2uf" path="res://molecular/assets/prey/prey-injured-frame1.png" id="7_w7inl"]
|
||||
[ext_resource type="Script" uid="uid://c7o7sp02u0wkv" path="res://molecular/nucleotide_prey_state.gd" id="9_guu3v"]
|
||||
[ext_resource type="Script" uid="uid://ubcu8fdfxxj1" path="res://molecular/nucleotide_prey_foraging.gd" id="10_rgguv"]
|
||||
[ext_resource type="Script" uid="uid://0vwv2nt16gpv" path="res://molecular/prey/nucleotide_prey_state_machine.gd" id="9_xxtgy"]
|
||||
[ext_resource type="Script" uid="uid://ubcu8fdfxxj1" path="res://molecular/prey/nucleotide_prey_random_movement.gd" id="10_rgguv"]
|
||||
[ext_resource type="Script" uid="uid://xbiqj7ubmj7d" path="res://molecular/prey/nucleotide_prey_idle.gd" id="12_ubfhk"]
|
||||
[ext_resource type="Script" uid="uid://dlw7inlh6asvu" path="res://molecular/prey/nucleotide_prey_fleeing.gd" id="12_xxtgy"]
|
||||
|
||||
[sub_resource type="SpriteFrames" id="SpriteFrames_66x8p"]
|
||||
animations = [{
|
||||
|
|
@ -58,15 +60,26 @@ scale = Vector2(0.1, 0.1)
|
|||
sprite_frames = SubResource("SpriteFrames_66x8p")
|
||||
animation = &"Injured"
|
||||
|
||||
[node name="State" type="Node" parent="." index="2"]
|
||||
script = ExtResource("9_guu3v")
|
||||
metadata/_custom_type_script = "uid://co2xp7gauamql"
|
||||
[node name="StateMachine" type="Node" parent="." index="2" node_paths=PackedStringArray("initial_state")]
|
||||
script = ExtResource("9_xxtgy")
|
||||
initial_state = NodePath("Idle")
|
||||
metadata/_custom_type_script = "uid://ck7k8ht54snsy"
|
||||
|
||||
[node name="Foraging" type="Node" parent="State" index="0"]
|
||||
[node name="RandomMovement" type="Node" parent="StateMachine" index="0"]
|
||||
script = ExtResource("10_rgguv")
|
||||
metadata/_custom_type_script = "uid://c7o7sp02u0wkv"
|
||||
|
||||
[node name="Timer" type="Timer" parent="State/Foraging" index="0"]
|
||||
[node name="Timer" type="Timer" parent="StateMachine/RandomMovement" index="0"]
|
||||
one_shot = true
|
||||
|
||||
[connection signal="timeout" from="State/Foraging/Timer" to="State/Foraging" method="_on_timer_timeout"]
|
||||
[node name="Fleeing" type="Node" parent="StateMachine" index="1"]
|
||||
script = ExtResource("12_xxtgy")
|
||||
|
||||
[node name="Idle" type="Node" parent="StateMachine" index="2"]
|
||||
script = ExtResource("12_ubfhk")
|
||||
metadata/_custom_type_script = "uid://co2xp7gauamql"
|
||||
|
||||
[node name="Timer" type="Timer" parent="StateMachine/Idle" index="0"]
|
||||
one_shot = true
|
||||
|
||||
[connection signal="timeout" from="StateMachine/RandomMovement/Timer" to="StateMachine/RandomMovement" method="_on_timer_timeout"]
|
||||
[connection signal="timeout" from="StateMachine/Idle/Timer" to="StateMachine/Idle" method="_on_timer_timeout"]
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
extends State
|
||||
|
||||
var threat: Node2D
|
||||
var threshold: float = 100
|
||||
|
||||
func enter(previous_state_path: String, data := {}) -> void:
|
||||
if data.has("threat"):
|
||||
threat = data["threat"]
|
||||
else:
|
||||
# default behaviour; do nothing
|
||||
threat = owner
|
||||
|
||||
func physics_update(_delta: float) -> void:
|
||||
if owner.position.distance_to(threat.position) > threshold:
|
||||
finished.emit(owner.fsm.States.IDLE, {})
|
||||
return
|
||||
owner.move(flee_from(threat.position))
|
||||
|
||||
func flee_from(pos: Vector2) -> Vector3:
|
||||
var diff = threat.position - owner.position
|
||||
diff = diff.normalized() * -1
|
||||
return Vector3(diff.x, diff.y ,0)
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://dlw7inlh6asvu
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
extends State
|
||||
|
||||
@onready var timer = $Timer
|
||||
|
||||
|
||||
func enter(previous_state_path: String, data := {}) -> void:
|
||||
timer.start((float)(randi() % 5)/5)
|
||||
|
||||
func physics_update(_delta: float) -> void:
|
||||
owner.move(Vector3(randfn(0, 1), randfn(0, 1), 0))
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
if (randi() % 4 != 0):
|
||||
finished.emit(owner.fsm.States.RANDOMMOVEMENT, {})
|
||||
else:
|
||||
finished.emit(owner.fsm.States.IDLE, {})
|
||||
|
||||
func exit() -> void:
|
||||
timer.stop()
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://xbiqj7ubmj7d
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
extends State
|
||||
|
||||
@onready var timer = $Timer
|
||||
var dir: Vector3 = Vector3(0,0,0);
|
||||
|
||||
func enter(previous_state_path: String, data := {}) -> void:
|
||||
timer.start((float)(randi() % 10)/20)
|
||||
dir = calc_dir(randi() % 360)
|
||||
|
||||
func physics_update(_delta: float) -> void:
|
||||
owner.move(dir)
|
||||
|
||||
func calc_dir(angle: float) -> Vector3:
|
||||
return Vector3(cos(angle), sin(angle), 0)
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
finished.emit(owner.fsm.States.IDLE, {})
|
||||
|
||||
func exit() -> void:
|
||||
timer.stop()
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
extends StateMachine
|
||||
|
||||
enum States {IDLE, RANDOMMOVEMENT, FEEDING, FLEEING}
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
super()
|
||||
await owner.ready
|
||||
|
||||
|
||||
func transition_to_next_state(target: int, data: Dictionary = {}) -> void:
|
||||
match target:
|
||||
States.IDLE: _transition_to_next_state("Idle", data)
|
||||
States.RANDOMMOVEMENT: _transition_to_next_state("RandomMovement", data)
|
||||
States.FEEDING: _transition_to_next_state("Feeding", data)
|
||||
States.FLEEING: _transition_to_next_state("Fleeing", data)
|
||||
_: push_error("Trying to transition to unknown state {target}")
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://0vwv2nt16gpv
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
extends NPC2D
|
||||
class_name AbstractPrey2D
|
||||
|
||||
enum States {IDLE, FORAGING, FLEEING}
|
||||
var state = States.IDLE
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class_name StateMachine extends Node
|
|||
# Connect states on ready, then wait.
|
||||
func _ready() -> void:
|
||||
for node: State in find_children("*", "State"):
|
||||
node.finished.connect(_transition_to_next_state)
|
||||
node.finished.connect(transition_to_next_state)
|
||||
|
||||
await owner.ready
|
||||
state.enter("")
|
||||
|
|
@ -37,3 +37,6 @@ func _transition_to_next_state(target_path: String, data: Dictionary = {}) -> vo
|
|||
state.exit()
|
||||
state = get_node(target_path)
|
||||
state.enter(previous_state_path, data)
|
||||
|
||||
func transition_to_next_state(target: int, data: Dictionary = {}) -> void:
|
||||
push_error("Child FSM failed to implement transition function.")
|
||||
|
|
|
|||
Loading…
Reference in New Issue