New inherited scene template based on Actor.
This commit is contained in:
parent
66a0de16bb
commit
46c1063d8d
10
Main.tscn
10
Main.tscn
|
|
@ -1,10 +1,12 @@
|
|||
[gd_scene load_steps=19 format=2]
|
||||
[gd_scene load_steps=21 format=2]
|
||||
|
||||
[ext_resource path="res://assets/Backgrounds/bgmuck.png" type="Texture" id=1]
|
||||
[ext_resource path="res://src/playerC/Player.tscn" type="PackedScene" id=2]
|
||||
[ext_resource path="res://assets/Tiles/Assets/Assets.png" type="Texture" id=3]
|
||||
[ext_resource path="res://assets/Music/platformer_level03_loop.ogg" type="AudioStream" id=4]
|
||||
[ext_resource path="res://src/CameraControl-Position2D.gd" type="Script" id=5]
|
||||
[ext_resource path="res://src/templates/Actor/ActorTemplate.tscn" type="PackedScene" id=6]
|
||||
[ext_resource path="res://src/enemyC/EnemyC.tscn" type="PackedScene" id=7]
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=2]
|
||||
points = PoolVector2Array( 16, 16, 0, 16, 0, 0, 16, 0 )
|
||||
|
|
@ -204,3 +206,9 @@ shape = SubResource( 13 )
|
|||
|
||||
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
|
||||
stream = ExtResource( 4 )
|
||||
|
||||
[node name="EnemyC" parent="." instance=ExtResource( 7 )]
|
||||
position = Vector2( 394, 47 )
|
||||
|
||||
[node name="ActorTemplate" parent="." instance=ExtResource( 6 )]
|
||||
position = Vector2( 262, 44 )
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ export(Array, Resource) var SoundEffects
|
|||
|
||||
onready var movement_animations: AnimatedSprite = $AnimatedSprite
|
||||
|
||||
onready var sound_effect_player = $SE_Player
|
||||
onready var sound_effect_player: AudioStreamPlayer = $SE_Player
|
||||
|
||||
onready var movement_component: MovementComponent = $Controllers/move_component
|
||||
|
||||
onready var movement_state_machine: StateMachineAnimatedActor = $Controllers/state_machine
|
||||
|
||||
onready var movement_component = $Controllers/move_component
|
||||
|
||||
var sound_effects_dict: Dictionary
|
||||
|
||||
##TODO:
|
||||
|
|
|
|||
141
src/enemyC/EnemyC.tscn
Normal file
141
src/enemyC/EnemyC.tscn
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
[gd_scene load_steps=23 format=2]
|
||||
|
||||
[ext_resource path="res://src/templates/Actor/ActorTemplate.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://src/enemyC/idle.gd" type="Script" id=2]
|
||||
|
||||
[sub_resource type="StreamTexture" id=1]
|
||||
load_path = "res://.import/botEnemy.png-46efd539a38730ff15fb4ddb087329c6.stex"
|
||||
|
||||
[sub_resource type="AtlasTexture" id=2]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 192, 48, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=3]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 0, 96, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=4]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 48, 96, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=5]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 96, 96, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=6]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 144, 96, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=7]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 0, 144, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=8]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 48, 144, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=9]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 96, 144, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=10]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 192, 96, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=11]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 0, 0, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=12]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 48, 0, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=13]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 96, 0, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=14]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 144, 0, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=15]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 192, 0, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=16]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 0, 48, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=17]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 48, 48, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=18]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 96, 48, 48, 48 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=19]
|
||||
atlas = SubResource( 1 )
|
||||
region = Rect2( 144, 48, 48, 48 )
|
||||
|
||||
[sub_resource type="SpriteFrames" id=20]
|
||||
animations = [ {
|
||||
"frames": [ SubResource( 2 ), SubResource( 3 ), SubResource( 4 ), SubResource( 5 ), SubResource( 6 ) ],
|
||||
"loop": true,
|
||||
"name": "attack",
|
||||
"speed": 10.0
|
||||
}, {
|
||||
"frames": [ SubResource( 7 ), SubResource( 8 ), SubResource( 9 ) ],
|
||||
"loop": true,
|
||||
"name": "death",
|
||||
"speed": 10.0
|
||||
}, {
|
||||
"frames": [ SubResource( 10 ) ],
|
||||
"loop": true,
|
||||
"name": "hurt",
|
||||
"speed": 10.0
|
||||
}, {
|
||||
"frames": [ SubResource( 11 ), SubResource( 12 ), SubResource( 13 ) ],
|
||||
"loop": true,
|
||||
"name": "idle",
|
||||
"speed": 10.0
|
||||
}, {
|
||||
"frames": [ SubResource( 14 ), SubResource( 15 ), SubResource( 16 ), SubResource( 17 ), SubResource( 18 ), SubResource( 19 ) ],
|
||||
"loop": true,
|
||||
"name": "walk",
|
||||
"speed": 10.0
|
||||
} ]
|
||||
|
||||
[node name="EnemyC" instance=ExtResource( 1 )]
|
||||
|
||||
[node name="AnimatedSprite" parent="." index="0"]
|
||||
position = Vector2( 11, -7 )
|
||||
frames = SubResource( 20 )
|
||||
animation = "idle"
|
||||
frame = 0
|
||||
__meta__ = {
|
||||
"_aseprite_wizard_config_": {
|
||||
"layer": "",
|
||||
"o_ex_p": "",
|
||||
"o_folder": "res://assets",
|
||||
"o_name": "",
|
||||
"only_visible": true,
|
||||
"op_exp": false,
|
||||
"slice": "",
|
||||
"source": "E:/Godot/Art/botEnemy.aseprite"
|
||||
}
|
||||
}
|
||||
|
||||
[node name="CollisionShape2D" parent="." index="1"]
|
||||
position = Vector2( -0.5, -2 )
|
||||
|
||||
[node name="idle" parent="Controllers/state_machine" index="0"]
|
||||
script = ExtResource( 2 )
|
||||
animation_sequence = [ ]
|
||||
fall_node = NodePath("")
|
||||
jump_node = NodePath("")
|
||||
move_node = NodePath("")
|
||||
fire_node = NodePath("")
|
||||
|
||||
[node name="fall" parent="Controllers/state_machine" index="1"]
|
||||
animation_sequence = [ "idle" ]
|
||||
54
src/enemyC/idle.gd
Normal file
54
src/enemyC/idle.gd
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
extends "res://src/templates/Actor/states/idle.gd"
|
||||
|
||||
|
||||
var debugTimeTracker := 0.0
|
||||
|
||||
export (NodePath) var jump_node
|
||||
export (NodePath) var move_node
|
||||
export (NodePath) var fire_node
|
||||
|
||||
onready var jump_state: State = get_node(jump_node)
|
||||
onready var move_state: State = get_node(move_node)
|
||||
onready var fire_state: State = get_node(fire_node)
|
||||
|
||||
func enter() -> void:
|
||||
.enter()
|
||||
parent.set_hurtbox(true)
|
||||
parent.velocity.x = 0
|
||||
|
||||
func process_input(_event: InputEvent) -> State:
|
||||
# if get_jump() and parent.is_on_floor():
|
||||
# return jump_state
|
||||
|
||||
if move_component.wants_jump() and parent.is_on_floor():
|
||||
return jump_state
|
||||
|
||||
# if move_component.get_movement_direction() != 0.0:
|
||||
# return move_state
|
||||
if move_component.wants_shoot():
|
||||
return fire_state
|
||||
|
||||
# move_component.wants_jump()
|
||||
move_component.get_movement_direction()
|
||||
|
||||
# if Input.is_action_just_pressed('dash'):
|
||||
# return dash_state
|
||||
return null
|
||||
|
||||
func process_physics(delta: float) -> State:
|
||||
debugTimeTracker += delta
|
||||
if debugTimeTracker > 2:
|
||||
debugTimeTracker = 0.0
|
||||
print("DEBUG TRANSFORM:", parent.transform)
|
||||
|
||||
parent.velocity.y += gravity * delta
|
||||
#parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
|
||||
parent.velocity.x = move_component.desired_movement_vector.x * move_speed
|
||||
parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
|
||||
|
||||
if parent.velocity.x != 0.0:
|
||||
return move_state
|
||||
|
||||
if !parent.is_on_floor():
|
||||
return fall_state
|
||||
return null
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
class_name MovementComponent
|
||||
extends Node
|
||||
|
||||
var desired_movement_vector: Vector2
|
||||
onready var desired_movement_vector: Vector2 = Vector2(0,0)
|
||||
|
||||
# Return the desired direction of movement for the character
|
||||
# in the range [-1, 1], where positive values indicate a desire
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ var animation_suffix: String = '';
|
|||
var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity")
|
||||
|
||||
var animations: AnimatedSprite
|
||||
var move_component: Node
|
||||
var move_component: MovementComponent
|
||||
var parent: KinematicBody2D
|
||||
|
||||
#var animation_sequence_timer: Timer
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ class_name StateMachineAnimatedActor extends StateMachine
|
|||
|
||||
# Initialize the state machine by giving each child state a reference to the
|
||||
# parent object it belongs to and enter the default starting_state.
|
||||
func init_animated_actor(parent: KinematicBody2D, animations: AnimatedSprite, move_component) -> void:
|
||||
func init_animated_actor(parent: KinematicBody2D, animations: AnimatedSprite, move_component: MovementComponent) -> void:
|
||||
animations.connect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
|
||||
for child in get_children():
|
||||
if child is StateAnimatedActor:
|
||||
|
|
|
|||
2
src/templates/Actor/ActorMovementComponent.gd
Normal file
2
src/templates/Actor/ActorMovementComponent.gd
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
extends MovementComponent
|
||||
|
||||
2
src/templates/Actor/ActorStateMachineAnimatedActor.gd
Normal file
2
src/templates/Actor/ActorStateMachineAnimatedActor.gd
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
extends StateMachineAnimatedActor
|
||||
|
||||
64
src/templates/Actor/ActorTemplate.gd
Normal file
64
src/templates/Actor/ActorTemplate.gd
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
extends Actor
|
||||
|
||||
onready var actor_hurtbox = $Hurtbox_Component/CollisionShape2D
|
||||
|
||||
|
||||
#var sound_effects = preload("res://src/playerC/resources/sound_effects.tres")
|
||||
|
||||
func _ready() -> void:
|
||||
movement_state_machine.init_animated_actor(self, movement_animations, movement_component)
|
||||
|
||||
# Experimenting with sound based resources I did this and it worked
|
||||
#sound_effect_player.stream = sound_effects.sounds["pew"]
|
||||
#print(sounds.sounds["pew"])
|
||||
#sound_effects.play()
|
||||
|
||||
# Trying something new with a custom resourse.
|
||||
for i in SoundEffects:
|
||||
sound_effects_dict[i.animation_name + str(i.frame_number)] = i.sound
|
||||
print (sound_effects_dict)
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
movement_state_machine.process_input(event)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
movement_state_machine.process_physics(delta)
|
||||
# #TODO: So much hack
|
||||
# if direction.x != 0:
|
||||
# gun.set_scale( Vector2(direction.x,1))
|
||||
|
||||
# Commented out to try parent transforms instead
|
||||
# if direction.x < 0:
|
||||
# var t = Transform2D()
|
||||
# # Translation
|
||||
# t.origin = Vector2(gun.offset_position.x * -1, gun.offset_position.y)
|
||||
# gun.transform = t
|
||||
# elif direction.x > 0:
|
||||
# var t = Transform2D()
|
||||
# # Translation
|
||||
# t.origin = Vector2(gun.offset_position.x, gun.offset_position.y)
|
||||
# gun.transform = t
|
||||
|
||||
# Attempting a Kinematic2D level scale for flip operations instead.
|
||||
#self.transform
|
||||
#self.scale.x = -1
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
movement_state_machine.process_frame(delta)
|
||||
play_sound_frame(movement_animations.animation , movement_animations.frame)
|
||||
|
||||
|
||||
##TODO: I don't like player class having do do this.
|
||||
## Figure out how to programatically signal subscribe
|
||||
#func _on_AnimatedSprite_animation_finished():
|
||||
# if movement_animations.frames.get_animation_loop(movement_animations.animation) == false:
|
||||
# movement_state_machine.current_state.animation_index += 1
|
||||
|
||||
func _on_Hurtbox_area_entered(area):
|
||||
print("Ouch.",area)
|
||||
movement_state_machine.change_state($Controllers/state_machine/hurt)
|
||||
|
||||
func set_hurtbox(enabled: bool):
|
||||
actor_hurtbox.set_deferred("disabled", !enabled) #WTF Apparently this is how to do it
|
||||
|
||||
|
||||
93
src/templates/Actor/ActorTemplate.tscn
Normal file
93
src/templates/Actor/ActorTemplate.tscn
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
[gd_scene load_steps=16 format=2]
|
||||
|
||||
[ext_resource path="res://src/components/Hurtbox_Component.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://src/templates/Actor/ActorStateMachineAnimatedActor.gd" type="Script" id=2]
|
||||
[ext_resource path="res://src/templates/Actor/states/fall.gd" type="Script" id=3]
|
||||
[ext_resource path="res://src/templates/Actor/states/idle.gd" type="Script" id=4]
|
||||
[ext_resource path="res://src/templates/Actor/ActorMovementComponent.gd" type="Script" id=5]
|
||||
[ext_resource path="res://src/templates/Actor/resources/Smiley.png" type="Texture" id=6]
|
||||
[ext_resource path="res://src/templates/Actor/ActorTemplate.gd" type="Script" id=12]
|
||||
|
||||
[sub_resource type="AtlasTexture" id=76]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 0, 0, 32, 32 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=77]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 32, 0, 32, 32 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=78]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 64, 0, 32, 32 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=79]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 0, 32, 32, 32 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=80]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 32, 32, 32, 32 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=81]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 64, 32, 32, 32 )
|
||||
|
||||
[sub_resource type="SpriteFrames" id=75]
|
||||
animations = [ {
|
||||
"frames": [ SubResource( 76 ), SubResource( 77 ), SubResource( 78 ), SubResource( 79 ), SubResource( 80 ), SubResource( 81 ) ],
|
||||
"loop": true,
|
||||
"name": "default",
|
||||
"speed": 5.0
|
||||
} ]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=74]
|
||||
extents = Vector2( 14, 18.5 )
|
||||
|
||||
[node name="ActorTemplate" type="KinematicBody2D"]
|
||||
collision_layer = 2
|
||||
script = ExtResource( 12 )
|
||||
|
||||
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
|
||||
frames = SubResource( 75 )
|
||||
frame = 2
|
||||
playing = true
|
||||
flip_h = true
|
||||
__meta__ = {
|
||||
"_aseprite_wizard_config_": {
|
||||
"layer": "",
|
||||
"o_ex_p": "",
|
||||
"o_folder": "res://assets",
|
||||
"o_name": "",
|
||||
"only_visible": true,
|
||||
"op_exp": false,
|
||||
"slice": "",
|
||||
"source": "E:/Godot/Art/MegaMan.aseprite"
|
||||
}
|
||||
}
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
position = Vector2( 0, -3.5 )
|
||||
shape = SubResource( 74 )
|
||||
|
||||
[node name="Controllers" type="Node" parent="."]
|
||||
|
||||
[node name="state_machine" type="Node" parent="Controllers"]
|
||||
script = ExtResource( 2 )
|
||||
starting_state = NodePath("idle")
|
||||
|
||||
[node name="idle" type="Node" parent="Controllers/state_machine"]
|
||||
script = ExtResource( 4 )
|
||||
animation_sequence = [ "default" ]
|
||||
fall_node = NodePath("../fall")
|
||||
|
||||
[node name="fall" type="Node" parent="Controllers/state_machine"]
|
||||
script = ExtResource( 3 )
|
||||
animation_sequence = [ "default" ]
|
||||
idle_node = NodePath("../idle")
|
||||
|
||||
[node name="move_component" type="Node" parent="Controllers"]
|
||||
script = ExtResource( 5 )
|
||||
|
||||
[node name="Hurtbox_Component" parent="." instance=ExtResource( 1 )]
|
||||
|
||||
[node name="SE_Player" type="AudioStreamPlayer" parent="."]
|
||||
BIN
src/templates/Actor/resources/Smiley.png
Normal file
BIN
src/templates/Actor/resources/Smiley.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 508 B |
35
src/templates/Actor/resources/Smiley.png.import
Normal file
35
src/templates/Actor/resources/Smiley.png.import
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/Smiley.png-8c81e651641e7afc57c144693e5c2423.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/templates/Actor/resources/Smiley.png"
|
||||
dest_files=[ "res://.import/Smiley.png-8c81e651641e7afc57c144693e5c2423.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=false
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
process/normal_map_invert_y=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
||||
22
src/templates/Actor/states/fall.gd
Normal file
22
src/templates/Actor/states/fall.gd
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
extends StateAnimatedActor
|
||||
|
||||
export (NodePath) var idle_node
|
||||
|
||||
onready var idle_state: State = get_node(idle_node)
|
||||
|
||||
func process_physics(delta: float) -> State:
|
||||
parent.velocity.y += gravity * delta
|
||||
|
||||
parent.velocity.x = move_component.desired_movement_vector.x * move_speed
|
||||
parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
|
||||
|
||||
if parent.velocity.x > 0:
|
||||
parent.direction.x = 1
|
||||
elif parent.velocity.x < 0:
|
||||
parent.direction.x = -1
|
||||
|
||||
parent.transform.x.x = parent.direction.x
|
||||
|
||||
if parent.is_on_floor():
|
||||
return idle_state
|
||||
return null
|
||||
22
src/templates/Actor/states/idle.gd
Normal file
22
src/templates/Actor/states/idle.gd
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
extends StateAnimatedActor
|
||||
|
||||
export (NodePath) var fall_node
|
||||
|
||||
onready var fall_state: State = get_node(fall_node)
|
||||
|
||||
func enter() -> void:
|
||||
.enter()
|
||||
parent.set_hurtbox(true)
|
||||
parent.velocity.x = 0
|
||||
print("Move Component: ", move_component.desired_movement_vector.x)
|
||||
|
||||
func process_physics(delta: float) -> State:
|
||||
|
||||
parent.velocity.y += gravity * delta
|
||||
#parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
|
||||
parent.velocity.x = move_component.desired_movement_vector.x * move_speed
|
||||
parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
|
||||
|
||||
if !parent.is_on_floor():
|
||||
return fall_state
|
||||
return null
|
||||
Loading…
Reference in New Issue
Block a user