Implemented state machine & added NPC ship template

This commit is contained in:
2ndbeam 2024-05-01 17:45:17 +03:00
commit bda9232e72
15 changed files with 284 additions and 22 deletions

View file

@ -0,0 +1,16 @@
[gd_scene load_steps=3 format=3 uid="uid://bkd4gyhlota7l"]
[ext_resource type="PackedScene" uid="uid://bsu4eqwdfewwi" path="res://scenes/Ships/Modules/Hulls/hull.tscn" id="1_l56rl"]
[ext_resource type="Texture2D" uid="uid://bchkncbniclhh" path="res://sprites/kamikaze.png" id="2_8ba3c"]
[node name="Hull" instance=ExtResource("1_l56rl")]
max_hp = 10.0
velocity_collision_treshold = 150.0
collision_damage = 10.0
[node name="Sprite" parent="." index="0"]
position = Vector2(0.5, 0.5)
texture = ExtResource("2_8ba3c")
[node name="Collision" parent="." index="1"]
polygon = PackedVector2Array(-69.5, 21, -69.5, 66, -68.5, 66, -57.5, 55, -57.5, 65, -56.5, 65, 70.5, 1, 70.5, 0, -56.5, -64, -57.5, -64, -57.5, -54, -68.5, -65, -69.5, -65, -69.5, -20, -68.5, -20, -57.5, -31, -57.5, -23, -32.5, -10, -32.5, 11, -57.5, 24, -57.5, 32, -68.5, 21)

View file

@ -0,0 +1,35 @@
[gd_scene load_steps=7 format=3 uid="uid://pev6k21vqaem"]
[ext_resource type="Script" path="res://scripts/Ship/ship.gd" id="1_82bba"]
[ext_resource type="PackedScene" uid="uid://bkd4gyhlota7l" path="res://scenes/Ships/Modules/Hulls/kamikaze_hull.tscn" id="2_165nu"]
[ext_resource type="PackedScene" uid="uid://mw4kwxoeqch3" path="res://scenes/Ships/Modules/Engines/engine.tscn" id="3_plu72"]
[ext_resource type="PackedScene" uid="uid://bunboi5ouscw8" path="res://scenes/Ships/Modules/Shields/shield.tscn" id="4_aos8x"]
[ext_resource type="Script" path="res://scripts/State Machine/tree.gd" id="5_m8m3f"]
[ext_resource type="Script" path="res://scripts/State Machine/Kamikaze/WanderingState.gd" id="6_emcj1"]
[node name="KamikazeShip" type="Node2D"]
script = ExtResource("1_82bba")
[node name="HullHolder" type="Node" parent="."]
[node name="Hull" parent="HullHolder" instance=ExtResource("2_165nu")]
collision_damage = 15.0
[node name="Engine" parent="." instance=ExtResource("3_plu72")]
[node name="Shield" parent="." instance=ExtResource("4_aos8x")]
max_capacity = 5
[node name="Weapons" type="Node2D" parent="."]
[node name="StateTree" type="Node" parent="." node_paths=PackedStringArray("state")]
script = ExtResource("5_m8m3f")
state = NodePath("WanderingState")
[node name="WanderingState" type="Node" parent="StateTree"]
script = ExtResource("6_emcj1")
[node name="UpdateDestination" type="Timer" parent="StateTree/WanderingState"]
wait_time = 10.0
[connection signal="timeout" from="StateTree/WanderingState/UpdateDestination" to="StateTree/WanderingState" method="update_destination"]

View file

@ -1,10 +1,13 @@
[gd_scene load_steps=11 format=3 uid="uid://dok3i8u5t1ka4"] [gd_scene load_steps=14 format=3 uid="uid://dok3i8u5t1ka4"]
[ext_resource type="PackedScene" uid="uid://bjkshql8ut6hk" path="res://scenes/Ships/ship.tscn" id="1_6x7bu"]
[ext_resource type="Script" path="res://scripts/Ship/player_ship.gd" id="2_oqdd7"] [ext_resource type="Script" path="res://scripts/Ship/player_ship.gd" id="2_oqdd7"]
[ext_resource type="Script" path="res://scripts/Ship/player_input_controller.gd" id="3_0e84a"] [ext_resource type="Script" path="res://scripts/Ship/player_input_controller.gd" id="3_0e84a"]
[ext_resource type="PackedScene" uid="uid://bsu4eqwdfewwi" path="res://scenes/Ships/Modules/Hulls/hull.tscn" id="3_ku5af"]
[ext_resource type="PackedScene" uid="uid://ryy1tdrxmjav" path="res://scenes/Ships/Modules/Weapons/weapon.tscn" id="4_fy1be"] [ext_resource type="PackedScene" uid="uid://ryy1tdrxmjav" path="res://scenes/Ships/Modules/Weapons/weapon.tscn" id="4_fy1be"]
[ext_resource type="PackedScene" uid="uid://mw4kwxoeqch3" path="res://scenes/Ships/Modules/Engines/engine.tscn" id="4_pmbbn"]
[ext_resource type="PackedScene" uid="uid://bunboi5ouscw8" path="res://scenes/Ships/Modules/Shields/shield.tscn" id="5_7fjpq"]
[ext_resource type="Script" path="res://scripts/Ship/player_camera.gd" id="5_rclap"] [ext_resource type="Script" path="res://scripts/Ship/player_camera.gd" id="5_rclap"]
[ext_resource type="Script" path="res://scripts/Ship/weapons.gd" id="6_f6fm2"]
[sub_resource type="GDScript" id="GDScript_ry4sc"] [sub_resource type="GDScript" id="GDScript_ry4sc"]
resource_name = "money_counter" resource_name = "money_counter"
@ -77,20 +80,35 @@ func _process(_delta):
text = unformatted_text.format(format) text = unformatted_text.format(format)
" "
[node name="PlayerShip" instance=ExtResource("1_6x7bu")] [node name="PlayerShip" type="Node2D"]
process_mode = 1
script = ExtResource("2_oqdd7") script = ExtResource("2_oqdd7")
[node name="InputController" type="Node2D" parent="." index="0"] [node name="InputController" type="Node2D" parent="."]
script = ExtResource("3_0e84a") script = ExtResource("3_0e84a")
[node name="Weapon" parent="Weapons" index="0" instance=ExtResource("4_fy1be")] [node name="HullHolder" type="Node" parent="."]
[node name="Hull" parent="HullHolder" instance=ExtResource("3_ku5af")]
collision_mask = 3
max_contacts_reported = 1
contact_monitor = true
[node name="Engine" parent="." instance=ExtResource("4_pmbbn")]
[node name="Shield" parent="." instance=ExtResource("5_7fjpq")]
[node name="Weapons" type="Node2D" parent="."]
script = ExtResource("6_f6fm2")
[node name="Weapon" parent="Weapons" instance=ExtResource("4_fy1be")]
action_id = "primary" action_id = "primary"
ammo_type = "Laser Energy" ammo_type = "Laser Energy"
ammo_consumption = 1.0 ammo_consumption = 1.0
[node name="ColorableGUI" type="CanvasLayer" parent="." index="5"] [node name="ColorableGUI" type="CanvasLayer" parent="."]
[node name="Money" type="Label" parent="ColorableGUI" index="0"] [node name="Money" type="Label" parent="ColorableGUI"]
offset_left = 7.0 offset_left = 7.0
offset_top = 611.0 offset_top = 611.0
offset_right = 92.0 offset_right = 92.0
@ -98,7 +116,7 @@ offset_bottom = 634.0
text = "Money: %d" text = "Money: %d"
script = SubResource("GDScript_ry4sc") script = SubResource("GDScript_ry4sc")
[node name="Velocity" type="Label" parent="ColorableGUI" index="1"] [node name="Velocity" type="Label" parent="ColorableGUI"]
offset_left = 7.0 offset_left = 7.0
offset_top = 688.0 offset_top = 688.0
offset_right = 137.0 offset_right = 137.0
@ -106,7 +124,7 @@ offset_bottom = 711.0
text = "Velocity: %d px/s" text = "Velocity: %d px/s"
script = SubResource("GDScript_vko7a") script = SubResource("GDScript_vko7a")
[node name="Health" type="Label" parent="ColorableGUI" index="2"] [node name="Health" type="Label" parent="ColorableGUI"]
offset_left = 7.0 offset_left = 7.0
offset_top = 663.0 offset_top = 663.0
offset_right = 168.0 offset_right = 168.0
@ -114,7 +132,7 @@ offset_bottom = 686.0
text = "Health: {0} / {1} units" text = "Health: {0} / {1} units"
script = SubResource("GDScript_uoaip") script = SubResource("GDScript_uoaip")
[node name="Shield" type="Label" parent="ColorableGUI" index="3"] [node name="Shield" type="Label" parent="ColorableGUI"]
offset_left = 8.0 offset_left = 8.0
offset_top = 638.0 offset_top = 638.0
offset_right = 164.0 offset_right = 164.0
@ -122,7 +140,7 @@ offset_bottom = 661.0
text = "Shield: {0} / {1} units" text = "Shield: {0} / {1} units"
script = SubResource("GDScript_q1sx2") script = SubResource("GDScript_q1sx2")
[node name="Ammunition" type="Label" parent="ColorableGUI" index="4"] [node name="Ammunition" type="Label" parent="ColorableGUI"]
offset_left = 1060.0 offset_left = 1060.0
offset_top = 638.0 offset_top = 638.0
offset_right = 1273.0 offset_right = 1273.0
@ -133,8 +151,8 @@ Rockets: {2} / {3}"
horizontal_alignment = 2 horizontal_alignment = 2
script = SubResource("GDScript_rrgab") script = SubResource("GDScript_rrgab")
[node name="NonColorableGUI" type="CanvasLayer" parent="." index="6"] [node name="NonColorableGUI" type="CanvasLayer" parent="."]
[node name="Camera" type="Camera2D" parent="." index="7"] [node name="Camera" type="Camera2D" parent="."]
zoom = Vector2(0.5, 0.5) zoom = Vector2(0.5, 0.5)
script = ExtResource("5_rclap") script = ExtResource("5_rclap")

View file

@ -1,7 +1,8 @@
[gd_scene load_steps=4 format=3 uid="uid://crneq2enhxsw5"] [gd_scene load_steps=5 format=3 uid="uid://crneq2enhxsw5"]
[ext_resource type="PackedScene" uid="uid://bsnrcw64qr2hr" path="res://scenes/Star Systems/star_system_template.tscn" id="1_2ai1l"] [ext_resource type="PackedScene" uid="uid://bsnrcw64qr2hr" path="res://scenes/Star Systems/star_system_template.tscn" id="1_2ai1l"]
[ext_resource type="PackedScene" uid="uid://dk3nvl8f0v24e" path="res://scenes/base_template.tscn" id="3_m5ica"] [ext_resource type="PackedScene" uid="uid://dk3nvl8f0v24e" path="res://scenes/base_template.tscn" id="3_m5ica"]
[ext_resource type="PackedScene" uid="uid://pev6k21vqaem" path="res://scenes/Ships/NPC Ships/kamikaze_ship.tscn" id="4_i6rbg"]
[ext_resource type="PackedScene" uid="uid://dok3i8u5t1ka4" path="res://scenes/Ships/player_ship.tscn" id="7_jyplv"] [ext_resource type="PackedScene" uid="uid://dok3i8u5t1ka4" path="res://scenes/Ships/player_ship.tscn" id="7_jyplv"]
[node name="StarSystem" instance=ExtResource("1_2ai1l")] [node name="StarSystem" instance=ExtResource("1_2ai1l")]
@ -12,13 +13,16 @@ height = 16384
scroll_offset = Vector2(681.667, 317.783) scroll_offset = Vector2(681.667, 317.783)
stars_amount = 4000 stars_amount = 4000
[node name="PlayerShip" parent="." index="3" instance=ExtResource("7_jyplv")] [node name="Nebula" parent="Background" index="0" node_paths=PackedStringArray("tracked_node")]
tracked_node = NodePath("../../FactionPlayer/PlayerShip")
color_background = Color(0.276474, 0.0962249, 0.200656, 1)
[node name="PlayerShip" parent="FactionPlayer" index="0" instance=ExtResource("7_jyplv")]
process_mode = 0 process_mode = 0
position = Vector2(19, 10) position = Vector2(19, 10)
[node name="Base" parent="." index="4" instance=ExtResource("3_m5ica")] [node name="Base" parent="FactionPeaceful" index="0" instance=ExtResource("3_m5ica")]
position = Vector2(7171, -28) position = Vector2(7171, -28)
[node name="Nebula" parent="Background" index="0" node_paths=PackedStringArray("tracked_node")] [node name="KamikazeShip" parent="FactionAggressive" index="0" instance=ExtResource("4_i6rbg")]
tracked_node = NodePath("../../PlayerShip") position = Vector2(687, -302)
color_background = Color(0.276474, 0.0962249, 0.200656, 1)

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=8 format=3 uid="uid://bsnrcw64qr2hr"] [gd_scene load_steps=9 format=3 uid="uid://bsnrcw64qr2hr"]
[ext_resource type="Script" path="res://scripts/star_system.gd" id="1_xx8w2"] [ext_resource type="Script" path="res://scripts/star_system.gd" id="1_xx8w2"]
[ext_resource type="PackedScene" uid="uid://dpggye27ln436" path="res://scenes/Star Systems/Required Scenes/star_generator.tscn" id="2_iqrn0"] [ext_resource type="PackedScene" uid="uid://dpggye27ln436" path="res://scenes/Star Systems/Required Scenes/star_generator.tscn" id="2_iqrn0"]
@ -6,6 +6,7 @@
[ext_resource type="Material" uid="uid://bawhivm5cr2w" path="res://shaders/materials/nebula_shader.tres" id="4_o0ld7"] [ext_resource type="Material" uid="uid://bawhivm5cr2w" path="res://shaders/materials/nebula_shader.tres" id="4_o0ld7"]
[ext_resource type="Script" path="res://scripts/nebula.gd" id="5_la84n"] [ext_resource type="Script" path="res://scripts/nebula.gd" id="5_la84n"]
[ext_resource type="PackedScene" uid="uid://c7is7y341f6wa" path="res://scenes/Star Systems/Required Scenes/pause_controller.tscn" id="6_61vq5"] [ext_resource type="PackedScene" uid="uid://c7is7y341f6wa" path="res://scenes/Star Systems/Required Scenes/pause_controller.tscn" id="6_61vq5"]
[ext_resource type="Script" path="res://scripts/faction.gd" id="7_wm3vi"]
[sub_resource type="GDScript" id="GDScript_4yoh5"] [sub_resource type="GDScript" id="GDScript_4yoh5"]
resource_name = "version_label" resource_name = "version_label"
@ -57,3 +58,19 @@ grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
script = ExtResource("5_la84n") script = ExtResource("5_la84n")
color_background = Color(0.36, 0.18612, 0.1116, 1) color_background = Color(0.36, 0.18612, 0.1116, 1)
[node name="FactionPlayer" type="Node" parent="."]
script = ExtResource("7_wm3vi")
faction = 1
[node name="FactionPeaceful" type="Node" parent="."]
script = ExtResource("7_wm3vi")
faction = 2
[node name="FactionNeutral" type="Node" parent="."]
script = ExtResource("7_wm3vi")
faction = 3
[node name="FactionAggressive" type="Node" parent="."]
script = ExtResource("7_wm3vi")
faction = 4

View file

@ -43,8 +43,9 @@ animations = [{
}] }]
[node name="Star" type="AnimatedSprite2D"] [node name="Star" type="AnimatedSprite2D"]
self_modulate = Color(1, 1, 1, 0.501961)
z_index = -19 z_index = -19
sprite_frames = SubResource("SpriteFrames_oggfj") sprite_frames = SubResource("SpriteFrames_oggfj")
autoplay = "default" autoplay = "default"
frame = 1
frame_progress = 0.66336
script = ExtResource("9_kew3k") script = ExtResource("9_kew3k")

View file

@ -19,6 +19,8 @@ class_name Hull
} }
## How much speed should ship have before collision to take damage ## How much speed should ship have before collision to take damage
@export var velocity_collision_treshold: float = 200.0 @export var velocity_collision_treshold: float = 200.0
## How much damage should ship take when its velocity equals to treshold
@export var collision_damage: float = 20.0
## Current ammunition. Change this with set_ammunition ## Current ammunition. Change this with set_ammunition
@onready var ammunition: Dictionary = max_ammunition.duplicate() @onready var ammunition: Dictionary = max_ammunition.duplicate()

View file

@ -17,7 +17,7 @@ signal destroyed
@onready var spawn_position: Vector2 = global_position @onready var spawn_position: Vector2 = global_position
## Faction which this ship belongs to ## Faction which this ship belongs to
var faction : Game.Faction = Game.Faction.Player var faction : Game.Faction
func _ready() -> void: func _ready() -> void:
hull.global_position = global_position hull.global_position = global_position

View file

@ -0,0 +1,52 @@
extends State
@onready var ship = get_parent().get_parent()
@onready var star_system = get_tree().current_scene
@onready var update_timer = $UpdateDestination
## Ship will strive to achieve this angle
var destination_degrees: float = 0:
set(value):
if value > 180:
destination_degrees = value - 360
elif value < -180:
destination_degrees = 360 + value
else:
destination_degrees = value
## Delta to destination_degrees
var destination_difference: float = 15.0
## available map bounds (use with absolute position)
var available_bounds: Vector2
func _ready():
available_bounds = Vector2(star_system.width / 2, star_system.height / 2)
randomize()
func enter(_message):
update_timer.start()
update_destination()
func process(_delta):
# checking if need to apply torque
var current_destination_difference = destination_degrees - ship.hull.global_rotation_degrees
var rotation_sign = sign(current_destination_difference)
if current_destination_difference < 0:
current_destination_difference = 180 - current_destination_difference
if current_destination_difference > 180:
current_destination_difference -= 180
if abs(current_destination_difference) > destination_difference:
ship.engine.rotation_axis = rotation_sign * (current_destination_difference / 180)
else:
ship.engine.rotation_axis = 0.0
# making ship always accelerate
ship.engine.acceleration_axis = 1.0
# if ship is out of star system bounds, set destination angle to center
if abs(ship.global_position.x) > available_bounds.x or abs(ship.global_position.y) > available_bounds.y:
destination_degrees = rad_to_deg(ship.global_position.angle_to_point(Vector2.ZERO))
func exit():
update_timer.stop()
## Set new random direction
func update_destination():
destination_degrees += randi_range(-180, 180)

View file

@ -0,0 +1,20 @@
extends Node
class_name State
var tree : StateTree
func enter(_message : Dictionary):
pass
func exit():
pass
func process(_delta):
pass
func physics_process(_delta):
pass
func input(_message : Dictionary):
pass

View file

@ -0,0 +1,51 @@
extends Node
class_name StateTree
## Emitted when active state is transitioned
signal transitioned(to_state)
## Active state
@export var state : State
## Dictionary of all states
var cached_states = {}
func _ready():
for child in get_children():
child.tree = self
cached_states[child.name] = child
state.enter({})
## Make another state active. Optionally, properties can be provided with message
func transit(to : String, message : Dictionary = {}):
state.exit()
state = cached_states[to]
state.enter(message)
transitioned.emit(to)
## Provides properties to active state
func send_input(message : Dictionary = {}):
state.input(message)
## Provides properties to all states
func send_input_to_system(message : Dictionary = {}):
for state in cached_states.values():
state.input(message)
## Returns state with provided name
func get_state(state_name) -> State:
return cached_states[state_name]
#region Перегруженные виртуальные функции гойды
func _process(delta) -> void:
state.process(delta)
func _physics_process(delta) -> void:
state.physics_process(delta)
#endregion

11
scripts/faction.gd Normal file
View file

@ -0,0 +1,11 @@
extends Node
class_name FactionNode
## Faction that is represented with this node
@export var faction: Game.Faction
func _ready():
for child in get_children():
if "faction" in child:
child.faction = faction

View file

@ -8,3 +8,4 @@ func _ready():
speed_scale = randf_range(0, 2) speed_scale = randf_range(0, 2)
var colors = [Color.LIGHT_BLUE, Color.WHITE, Color.LIGHT_GOLDENROD, Color.YELLOW, Color.ORANGE, Color.ORANGE_RED, Color.RED] var colors = [Color.LIGHT_BLUE, Color.WHITE, Color.LIGHT_GOLDENROD, Color.YELLOW, Color.ORANGE, Color.ORANGE_RED, Color.RED]
modulate = colors.pick_random() modulate = colors.pick_random()
modulate.a = randf_range(0.5, 1)

BIN
sprites/kamikaze.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bchkncbniclhh"
path="res://.godot/imported/kamikaze.png-a9865d0191d172f866fc5dbf442fac7a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://sprites/kamikaze.png"
dest_files=["res://.godot/imported/kamikaze.png-a9865d0191d172f866fc5dbf442fac7a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1