Working Slopes 😌🎉

This commit is contained in:
Jakob Feldmann 2022-11-01 20:01:40 +01:00
parent 7c423e7fc9
commit 5df4df667b
7 changed files with 145 additions and 154 deletions

View File

@ -14,6 +14,8 @@ var wall_touch_direction = 1
var stomping = false
var floor_angle = Vector2(0,0)
var previous_rotation = 0
var snap_possible = true
# When the Enemy stomp AREA enters the enemy collision area -> stomp
func _on_BlobbySkin_area_entered(area: Area2D) -> void:
@ -108,6 +110,7 @@ func calculate_duck_velocity(
Input.is_action_just_pressed("jump")
|| (jump_buffer_filled && is_on_floor())
):
snap_possible = false
return calculate_jump_velocity(velocity, delta, direction)
elif player_state_machine.coyote_hanging:
@ -183,6 +186,7 @@ func calculate_grounded_velocity(
Input.is_action_just_pressed("jump")
|| (jump_buffer_filled && is_on_floor())
):
snap_possible = false
return calculate_jump_velocity(velocity, delta, direction)
elif player_state_machine.coyote_hanging:
@ -327,7 +331,7 @@ func calculate_wallslide_velocity(
linear_velocity.y*0.94, _gravity * mass, mass, delta
)
air_strafe_charges = 1
return linear_velocity
return linear_velocity.rotated(rotation)
func execute_airstrafe(
@ -354,85 +358,59 @@ func execute_airstrafe(
air_strafe_charges -= 1
return linear_velocity
var snapped = false
func execute_movement() -> void:
if(GlobalState.is_dead):
return
var snap = Vector2.DOWN * 128
var center_floor_rot = 0
var floor_rot = 0
var onfloor = is_on_floor()
# get rotation of floor, compare collided floor with floor under center
if is_on_floor():
if onfloor:
# TODO: Problem when correctly rotating?
center_floor_rot = $SlopeRaycast.get_collision_normal().angle() + PI/2
floor_rot = get_floor_normal().angle() + PI/2
center_floor_rot = $SlopeRaycast.get_collision_normal().rotated(PI/2).angle()
floor_rot = get_floor_normal().rotated(PI/2).angle()
if(abs(center_floor_rot) > PI/4+0.1):
center_floor_rot = floor_rot
# snap when on slopes
if(abs(floor_rot) > 0.1 || abs(center_floor_rot) > 0.1):
velocity = move_and_slide_with_snap(velocity.rotated(floor_rot),
if((abs(floor_rot) > 0.1 || abs(center_floor_rot) > 0.1) && snap_possible):
velocity = move_and_slide_with_snap(velocity.rotated(floor_rot*1.1),
snap, FLOOR_NORMAL, true)
snapped = true
# normal slide on flat floor
else:
if snapped == true:
print("unsnapped")
velocity = move_and_slide(velocity.rotated(floor_rot),FLOOR_NORMAL)
snapped = false
rotation = 0
if($SlopeRaycastLeft.is_colliding() && $SlopeRaycastRight.is_colliding() && $SlopeRaycast.is_colliding()):
rotation = calculate_slope_rotation(onfloor)
# rotate related to floor slope
var rot = calculate_slope_rotation(center_floor_rot)
# Convert velocity back to local space.
velocity = velocity.rotated(-floor_rot)
velocity = velocity.rotated(-floor_rot*1.1) if snap_possible else velocity
func calculate_slope_rotation(center_floor_rot: float) -> float:
func calculate_slope_rotation(onfloor: bool) -> float:
var angle = 0
# var distance_to_slope_left = abs($SlopeRaycastLeft.global_position.distance_to($SlopeRaycastLeft.get_collision_point()))
# var distance_to_slope_right = abs($SlopeRaycastRight.global_position.distance_to($SlopeRaycastRight.get_collision_point()))
# var slope_angle_left = rad2deg($SlopeRaycastLeft.get_collision_normal().rotated(PI/2).angle())
# var slope_angle_right = rad2deg($SlopeRaycastRight.get_collision_normal().rotated(PI/2).angle())
# if(abs(slope_angle_left - slope_angle_right) < 5):
# print("on slope")
# elif(abs(slope_angle_left) > 0 && distance_to_slope_left < distance_to_slope_right ||
# abs(slope_angle_right) > 0 && distance_to_slope_right < distance_to_slope_left):
# print("upturn")
# var length_vector: Vector2 = $SlopeRaycastRight.get_collision_point() - $SlopeRaycastLeft.get_collision_point()
# angle = length_vector.angle()
# print(rad2deg(angle))
# else:
# print("downturn")
# var length_vector: Vector2 = $SlopeRaycastRight.get_collision_point() - $SlopeRaycastLeft.get_collision_point()
# angle = length_vector.angle()
# # angle = center_floor_rot * min(1, 1.3*overhang(distance_to_slope_left, distance_to_slope_right)/$BlobbyBody.shape.extents.x)
if(player_state_machine.facing == 1):
var slope_angle_left = $SlopeRaycastLeft.get_collision_normal().rotated(PI/2).angle()
var slope_angle_right = $SlopeRaycastRight.get_collision_normal().rotated(PI/2).angle()
# avoid invalid angles and stay in rotation when touching ground completely
if(!(-PI/2 <= slope_angle_left && slope_angle_left <= PI/2)
|| !(-PI/2 <= slope_angle_right && slope_angle_right <= PI/2)
|| (abs(slope_angle_left) - abs(slope_angle_right) == 0 && onfloor)):
return previous_rotation if abs(previous_rotation) > 0.1 else 0.0
# downturn
# print(abs(slope_angle_left) > abs(slope_angle_right) && distance_to_slope_right > distance_to_slope_left)
if(abs(slope_angle_left) > abs(slope_angle_right) ||
abs(slope_angle_right) > abs(slope_angle_left)):
var length_vector: Vector2 = $SlopeRaycastRight.get_collision_point() - $SlopeRaycastLeft.get_collision_point()
angle = length_vector.angle()
print(rad2deg(angle))
angle = length_vector.angle()
# upturn
else:
var length_vector: Vector2 = $SlopeRaycastLeft.get_collision_point() - $SlopeRaycastRight.get_collision_point()
angle = length_vector.angle() - PI
previous_rotation = angle
return angle
# When Blobby is going over an edge,
# This function returns how many pixels he has gone over that edge, measured from his center
func overhang(distance_to_slope_left, distance_to_slope_right) -> float:
var distance_to_slope = abs($SlopeRaycast.global_position.distance_to($SlopeRaycast.get_collision_point()))
if(!(abs(distance_to_slope_left) > 1 || abs(distance_to_slope_right) > 1)):
distance_to_slope = max(1,distance_to_slope)
var hitbox_to_slope_vector = (global_position - $SlopeRaycast.get_collision_point()).normalized()
var angle = min(PI/2,abs(hitbox_to_slope_vector.angle_to($SlopeRaycast.get_collision_normal().rotated(PI/2))))
var overhang = distance_to_slope * tan(angle)
overhang = $BlobbyBody.shape.extents.x if abs(overhang) > $BlobbyBody.shape.extents.x else overhang
# if(overhang < 0.6):
# print("dist to slope:")
# print(distance_to_slope)
# print("hitbox to slope vec:")
# print(hitbox_to_slope_vector)
# print("angle:")
# print(rad2deg(angle))
# print("tan(angle):")
# print(tan(angle))
# print("overhang:")
# print(overhang)
return abs(overhang)
func die() -> void:
z_index = 1
GlobalState.is_dead = true
@ -449,6 +427,7 @@ func respawn() -> void:
# TODO Setting y velocity this way stopped is_on_floor() from working correctly
func _on_Blobby_got_grounded() -> void:
velocity.x -= get_floor_velocity().x
snap_possible = true
var floor_object = get_last_slide_collision().collider.get_parent()
#TODO There is already a friction property in engine
if "slide_friction" in floor_object:

View File

@ -682,7 +682,7 @@ tracks/3/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 14.9752, 6.02764 ) ]
"values": [ Vector2( 13, 6.02764 ) ]
}
tracks/4/type = "value"
tracks/4/path = NodePath("../BlobbyBody:position")
@ -806,7 +806,7 @@ tracks/1/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 14.9752, 6.02764 ) ]
"values": [ Vector2( 13, 6.02764 ) ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("../BlobbySkin/CollisionPolygon2D:position")
@ -955,7 +955,7 @@ tracks/1/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 14.9752, 6.02764 ) ]
"values": [ Vector2( 13, 6.02764 ) ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("../BlobbySkin/CollisionPolygon2D:position")
@ -1481,7 +1481,7 @@ tracks/4/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 12.971, 8.99662 ) ]
"values": [ Vector2( 12, 8.99662 ) ]
}
tracks/5/type = "value"
tracks/5/path = NodePath("../WallRaycasts/LeftWallRaycast/Left_Wallcast1:position")
@ -1593,7 +1593,7 @@ tracks/1/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 12.971, 8.99662 ) ]
"values": [ Vector2( 12, 8.99662 ) ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("../BlobbyBody:position")
@ -1742,7 +1742,7 @@ tracks/1/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 12.971, 8.99662 ) ]
"values": [ Vector2( 12, 8.99662 ) ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("../BlobbyBody:position")
@ -2783,7 +2783,7 @@ tracks/1/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 12.4831, 8.99662 ) ]
"values": [ Vector2( 11.5, 8.99662 ) ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("../BlobbyBody:position")
@ -2969,7 +2969,7 @@ tracks/1/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 12.4831, 8.99662 ) ]
"values": [ Vector2( 11.5, 8.99662 ) ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("../BlobbyBody:position")
@ -3213,7 +3213,7 @@ tracks/6/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 11.9898, 8.99662 ) ]
"values": [ Vector2( 11, 8.99662 ) ]
}
tracks/7/type = "value"
tracks/7/path = NodePath("../BlobbySkin/CollisionPolygon2D:shape:extents")
@ -3362,7 +3362,7 @@ tracks/6/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 11.9898, 8.99662 ) ]
"values": [ Vector2( 11, 8.99662 ) ]
}
tracks/7/type = "value"
tracks/7/path = NodePath("../BlobbySkin/CollisionPolygon2D:shape:extents")
@ -3498,7 +3498,7 @@ tracks/5/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 12.971, 8.99662 ) ]
"values": [ Vector2( 12, 8.99662 ) ]
}
tracks/6/type = "value"
tracks/6/path = NodePath("../BlobbyBody:position")
@ -3647,7 +3647,7 @@ tracks/5/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 12.971, 8.99662 ) ]
"values": [ Vector2( 12, 8.99662 ) ]
}
tracks/6/type = "value"
tracks/6/path = NodePath("../BlobbyBody:position")
@ -4601,19 +4601,20 @@ collision_mask = 56
[node name="SlopeRaycastLeft" type="RayCast2D" parent="."]
position = Vector2( -9, 0 )
enabled = true
cast_to = Vector2( 0, 32 )
collision_mask = 56
cast_to = Vector2( 0, 24 )
collision_mask = 8
[node name="SlopeRaycast" type="RayCast2D" parent="."]
unique_name_in_owner = true
enabled = true
cast_to = Vector2( 0, 16 )
collision_mask = 56
collision_mask = 8
[node name="SlopeRaycastRight" type="RayCast2D" parent="."]
position = Vector2( 10, 0 )
enabled = true
cast_to = Vector2( 0, 32 )
collision_mask = 56
cast_to = Vector2( 0, 24 )
collision_mask = 8
[connection signal="area_entered" from="BlobbySkin" to="." method="_on_BlobbySkin_area_entered"]
[connection signal="body_entered" from="BlobbySkin" to="." method="_on_BlobbySkin_body_entered"]

View File

@ -11,6 +11,7 @@ onready var anim_player = parent.get_node("BlobbySprite/BlobbymationPlayer")
onready var anim_state_playback = parent.get_node("BlobbySprite/AnimationTree").get("parameters/playback")
onready var anim_tree = parent.get_node("BlobbySprite/AnimationTree")
onready var sprite = parent.get_node("BlobbySprite")
onready var slope_raycast = get_node("%SlopeRaycast")
var facing = 1
var didTurn
@ -160,7 +161,7 @@ func _get_transition(_delta):
if coyote_hanging:
new_state = self.state
elif parent.velocity.x != 0:
elif abs(parent.velocity.x) > 5:
if Input.is_action_pressed("boost_move"):
new_state = states.run
# TODO Walking when stopping and not pressing anything?
@ -206,9 +207,11 @@ func _enter_state(new_state, old_state):
# TODO HA! H! HAAA!
anim_state_playback.travel("ducking")
states.jump:
anim_state_playback.travel("jumping")
if(parent.rotation == 0):
anim_state_playback.travel("jumping")
states.fall:
anim_state_playback.travel("falling")
if(parent.rotation == 0):
anim_state_playback.travel("falling")
states.run:
anim_state_playback.travel("running")
states.wallslide:

View File

@ -105,7 +105,7 @@ shape = SubResource( 4 )
[node name="ButtonBody" type="StaticBody2D" parent="."]
unique_name_in_owner = true
position = Vector2( 0, -6 )
collision_layer = 24
collision_layer = 64
[node name="CollisionShape2D" type="CollisionShape2D" parent="ButtonBody"]
position = Vector2( 0, 5 )

View File

@ -203,7 +203,7 @@ shape = SubResource( 4 )
[node name="ButtonBody" type="StaticBody2D" parent="."]
unique_name_in_owner = true
position = Vector2( 0, -6 )
collision_layer = 24
collision_layer = 64
[node name="CollisionShape2D" type="CollisionShape2D" parent="ButtonBody"]
position = Vector2( 0, 5 )

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=12 format=2]
[gd_scene load_steps=13 format=2]
[ext_resource path="res://src/Environment/AlienShipTileSet.tres" type="TileSet" id=1]
[ext_resource path="res://src/Utilities/GameplaySignalManager.gd" type="Script" id=2]
@ -10,6 +10,7 @@
[ext_resource path="res://src/Contraptions/Triggers/ElevatorButton.tscn" type="PackedScene" id=8]
[ext_resource path="res://src/Levels/Enemy Test Level.tscn" type="PackedScene" id=9]
[ext_resource path="res://src/Actors/Blobby/Blobby.tscn" type="PackedScene" id=10]
[ext_resource path="res://src/Actors/BlobbyCam.tscn" type="PackedScene" id=11]
[sub_resource type="AnimationNodeStateMachinePlayback" id=4]
@ -30,13 +31,27 @@ margin_top = 0.456848
margin_right = 3.15375
margin_bottom = 0.456848
[node name="BlobbyCam" parent="." instance=ExtResource( 11 )]
[node name="Blobby" parent="." instance=ExtResource( 10 )]
position = Vector2( 71.0069, 335.293 )
unique_name_in_owner = true
position = Vector2( -22, 8.00003 )
scale = Vector2( 0.878906, 0.936025 )
[node name="AnimationTree" parent="Blobby/BlobbySprite" index="0"]
parameters/playback = SubResource( 4 )
[node name="TileMap" type="TileMap" parent="."]
position = Vector2( -109, -327 )
tile_set = ExtResource( 1 )
cell_size = Vector2( 24, 24 )
cell_quadrant_size = 3
cell_custom_transform = Transform2D( 24, 0, 0, 24, 0, 0 )
collision_layer = 8
collision_mask = 8
format = 1
tile_data = PoolIntArray( 655360, 2, 0, 655361, 2, 0, 655362, 2, 0, 655363, 2, 0, 655364, 2, 0, 655365, 2, 0, 655366, 2, 0, 655367, 2, 0, 655368, 2, 0, 720896, 2, 0, 720904, 2, 0, 786432, 2, 0, 786440, 2, 0, 851968, 2, 0, 851976, 2, 0, 917504, 2, 0, 917505, 2, 0, 917506, 2, 0, 917507, 2, 0, 917508, 2, 0, 917509, 2, 0, 917510, 2, 0, 917511, 2, 0, 917512, 2, 0 )
[node name="Collectibles" type="Node2D" parent="."]
visible = false
@ -64,16 +79,6 @@ scale = Vector2( 0.133, 0.133 )
position = Vector2( 696, -48 )
scale = Vector2( 0.133, 0.133 )
[node name="TileMap" type="TileMap" parent="."]
tile_set = ExtResource( 1 )
cell_size = Vector2( 24, 24 )
cell_quadrant_size = 3
cell_custom_transform = Transform2D( 24, 0, 0, 24, 0, 0 )
collision_layer = 8
collision_mask = 8
format = 1
tile_data = PoolIntArray( 655360, 2, 0, 655361, 2, 0, 655362, 2, 0, 655363, 2, 0, 655364, 2, 0, 655365, 2, 0, 655366, 2, 0, 655367, 2, 0, 655368, 2, 0, 720896, 2, 0, 720904, 2, 0, 786432, 2, 0, 786440, 2, 0, 851968, 2, 0, 851976, 2, 0, 917504, 2, 0, 917505, 2, 0, 917506, 2, 0, 917507, 2, 0, 917508, 2, 0, 917509, 2, 0, 917510, 2, 0, 917511, 2, 0, 917512, 2, 0 )
[node name="TreeWhyButtons" parent="." instance=ExtResource( 3 )]
visible = false
position = Vector2( -108, -7 )
@ -104,220 +109,220 @@ next_scene = ExtResource( 9 )
script = ExtResource( 2 )
[node name="ShaderGrass" parent="." instance=ExtResource( 5 )]
position = Vector2( 94.3273, 323.897 )
position = Vector2( -14.913, -2.37698 )
z_index = -1
[node name="ShaderGrass2" parent="." instance=ExtResource( 5 )]
position = Vector2( 97.7583, 323.726 )
position = Vector2( -11.482, -2.54797 )
[node name="ShaderGrass3" parent="." instance=ExtResource( 5 )]
position = Vector2( 103.443, 323.813 )
position = Vector2( -5.7973, -2.461 )
[node name="ShaderGrass4" parent="." instance=ExtResource( 5 )]
position = Vector2( 99.556, 322.393 )
position = Vector2( -9.6843, -3.88098 )
z_index = -1
[node name="ShaderGrass5" parent="." instance=ExtResource( 5 )]
position = Vector2( 107.485, 323.87 )
position = Vector2( -1.7553, -2.40399 )
[node name="ShaderGrass6" parent="." instance=ExtResource( 5 )]
position = Vector2( 104.781, 322.084 )
position = Vector2( -4.4593, -4.18997 )
z_index = -1
[node name="ShaderGrass7" parent="." instance=ExtResource( 5 )]
position = Vector2( 118.829, 323.704 )
position = Vector2( 9.5887, -2.56998 )
[node name="ShaderGrass8" parent="." instance=ExtResource( 5 )]
position = Vector2( 112.732, 323.918 )
position = Vector2( 3.4917, -2.35599 )
[node name="ShaderGrass9" parent="." instance=ExtResource( 5 )]
position = Vector2( 110.33, 321.607 )
position = Vector2( 1.0897, -4.66699 )
z_index = -1
[node name="ShaderGrass10" parent="." instance=ExtResource( 5 )]
position = Vector2( 122.514, 323.848 )
position = Vector2( 13.2737, -2.42599 )
z_index = -1
[node name="ShaderGrass11" parent="." instance=ExtResource( 5 )]
position = Vector2( 125.945, 323.677 )
position = Vector2( 16.7047, -2.59698 )
[node name="ShaderGrass12" parent="." instance=ExtResource( 5 )]
position = Vector2( 131.629, 323.764 )
position = Vector2( 22.3887, -2.50998 )
[node name="ShaderGrass13" parent="." instance=ExtResource( 5 )]
position = Vector2( 127.742, 322.345 )
position = Vector2( 18.5017, -3.92899 )
z_index = -1
[node name="ShaderGrass14" parent="." instance=ExtResource( 5 )]
position = Vector2( 135.671, 323.821 )
position = Vector2( 26.4307, -2.45297 )
[node name="ShaderGrass15" parent="." instance=ExtResource( 5 )]
position = Vector2( 132.967, 322.035 )
position = Vector2( 23.7267, -4.23898 )
z_index = -1
[node name="ShaderGrass16" parent="." instance=ExtResource( 5 )]
position = Vector2( 147.015, 323.655 )
position = Vector2( 37.7747, -2.61899 )
[node name="ShaderGrass17" parent="." instance=ExtResource( 5 )]
position = Vector2( 140.918, 323.869 )
position = Vector2( 31.6777, -2.405 )
[node name="ShaderGrass18" parent="." instance=ExtResource( 5 )]
position = Vector2( 138.516, 321.559 )
position = Vector2( 29.2757, -4.715 )
z_index = -1
[node name="ShaderGrass19" parent="." instance=ExtResource( 5 )]
position = Vector2( 149.723, 323.897 )
position = Vector2( 40.4827, -2.37698 )
z_index = -1
[node name="ShaderGrass20" parent="." instance=ExtResource( 5 )]
position = Vector2( 153.154, 323.726 )
position = Vector2( 43.9137, -2.54797 )
[node name="ShaderGrass21" parent="." instance=ExtResource( 5 )]
position = Vector2( 158.839, 323.813 )
position = Vector2( 49.5987, -2.461 )
[node name="ShaderGrass22" parent="." instance=ExtResource( 5 )]
position = Vector2( 154.952, 322.393 )
position = Vector2( 45.7117, -3.88098 )
z_index = -1
[node name="ShaderGrass23" parent="." instance=ExtResource( 5 )]
position = Vector2( 162.881, 323.87 )
position = Vector2( 53.6407, -2.40399 )
[node name="ShaderGrass24" parent="." instance=ExtResource( 5 )]
position = Vector2( 160.177, 322.084 )
position = Vector2( 50.9367, -4.18997 )
z_index = -1
[node name="ShaderGrass25" parent="." instance=ExtResource( 5 )]
position = Vector2( 174.225, 323.704 )
position = Vector2( 64.9847, -2.56998 )
[node name="ShaderGrass26" parent="." instance=ExtResource( 5 )]
position = Vector2( 168.128, 323.918 )
position = Vector2( 58.8877, -2.35599 )
[node name="ShaderGrass27" parent="." instance=ExtResource( 5 )]
position = Vector2( 165.726, 321.607 )
position = Vector2( 56.4857, -4.66699 )
z_index = -1
[node name="ShaderGrass28" parent="." instance=ExtResource( 5 )]
position = Vector2( 64.794, 323.73 )
position = Vector2( -44.4463, -2.54398 )
z_index = -1
[node name="ShaderGrass29" parent="." instance=ExtResource( 5 )]
position = Vector2( 68.225, 323.559 )
position = Vector2( -41.0153, -2.715 )
[node name="ShaderGrass30" parent="." instance=ExtResource( 5 )]
position = Vector2( 73.9096, 323.646 )
position = Vector2( -35.3307, -2.62799 )
[node name="ShaderGrass31" parent="." instance=ExtResource( 5 )]
position = Vector2( 70.0227, 322.227 )
position = Vector2( -39.2176, -4.047 )
z_index = -1
[node name="ShaderGrass32" parent="." instance=ExtResource( 5 )]
position = Vector2( 77.9516, 323.703 )
position = Vector2( -31.2887, -2.57098 )
[node name="ShaderGrass33" parent="." instance=ExtResource( 5 )]
position = Vector2( 75.2476, 321.917 )
position = Vector2( -33.9927, -4.35699 )
z_index = -1
[node name="ShaderGrass34" parent="." instance=ExtResource( 5 )]
position = Vector2( 89.2956, 323.538 )
position = Vector2( -19.9447, -2.73599 )
[node name="ShaderGrass35" parent="." instance=ExtResource( 5 )]
position = Vector2( 83.1986, 323.751 )
position = Vector2( -26.0417, -2.52298 )
[node name="ShaderGrass36" parent="." instance=ExtResource( 5 )]
position = Vector2( 80.7966, 321.441 )
position = Vector2( -28.4437, -4.83298 )
z_index = -1
[node name="ShaderGrass37" parent="." instance=ExtResource( 5 )]
position = Vector2( 39.2652, 323.564 )
position = Vector2( -69.9751, -2.70999 )
z_index = -1
[node name="ShaderGrass38" parent="." instance=ExtResource( 5 )]
position = Vector2( 42.6962, 323.393 )
position = Vector2( -66.5441, -2.88098 )
[node name="ShaderGrass39" parent="." instance=ExtResource( 5 )]
position = Vector2( 48.3808, 323.48 )
position = Vector2( -60.8595, -2.79398 )
[node name="ShaderGrass40" parent="." instance=ExtResource( 5 )]
position = Vector2( 44.4939, 322.06 )
position = Vector2( -64.7464, -4.21399 )
z_index = -1
[node name="ShaderGrass41" parent="." instance=ExtResource( 5 )]
position = Vector2( 52.4228, 323.537 )
position = Vector2( -56.8175, -2.737 )
[node name="ShaderGrass42" parent="." instance=ExtResource( 5 )]
position = Vector2( 49.7188, 321.751 )
position = Vector2( -59.5215, -4.52298 )
z_index = -1
[node name="ShaderGrass43" parent="." instance=ExtResource( 5 )]
position = Vector2( 63.7668, 323.371 )
position = Vector2( -45.4735, -2.90298 )
[node name="ShaderGrass44" parent="." instance=ExtResource( 5 )]
position = Vector2( 57.6698, 323.585 )
position = Vector2( -51.5705, -2.689 )
[node name="ShaderGrass45" parent="." instance=ExtResource( 5 )]
position = Vector2( 55.2678, 321.274 )
position = Vector2( -53.9725, -5 )
z_index = -1
[node name="ShaderGrass46" parent="." instance=ExtResource( 5 )]
position = Vector2( 17.2403, 323.73 )
position = Vector2( -92, -2.54398 )
z_index = -1
[node name="ShaderGrass47" parent="." instance=ExtResource( 5 )]
position = Vector2( 20.6713, 323.559 )
position = Vector2( -88.569, -2.715 )
[node name="ShaderGrass48" parent="." instance=ExtResource( 5 )]
position = Vector2( 26.3559, 323.646 )
position = Vector2( -82.8844, -2.62799 )
[node name="ShaderGrass49" parent="." instance=ExtResource( 5 )]
position = Vector2( 22.469, 322.227 )
position = Vector2( -86.7713, -4.047 )
z_index = -1
[node name="ShaderGrass50" parent="." instance=ExtResource( 5 )]
position = Vector2( 30.3979, 323.703 )
position = Vector2( -78.8424, -2.57098 )
[node name="ShaderGrass51" parent="." instance=ExtResource( 5 )]
position = Vector2( 27.6939, 321.917 )
position = Vector2( -81.5464, -4.35699 )
z_index = -1
[node name="ShaderGrass52" parent="." instance=ExtResource( 5 )]
position = Vector2( 41.7419, 323.538 )
position = Vector2( -67.4984, -2.73599 )
[node name="ShaderGrass53" parent="." instance=ExtResource( 5 )]
position = Vector2( 35.6449, 323.751 )
position = Vector2( -73.5954, -2.52298 )
[node name="ShaderGrass54" parent="." instance=ExtResource( 5 )]
position = Vector2( 33.2429, 321.441 )
position = Vector2( -75.9974, -4.83298 )
z_index = -1
[node name="ShaderGrass55" parent="." instance=ExtResource( 5 )]
position = Vector2( 166.242, 323.73 )
position = Vector2( 57.0017, -2.54398 )
z_index = -1
[node name="ShaderGrass56" parent="." instance=ExtResource( 5 )]
position = Vector2( 169.673, 323.559 )
position = Vector2( 60.4327, -2.715 )
[node name="ShaderGrass57" parent="." instance=ExtResource( 5 )]
position = Vector2( 175.357, 323.646 )
position = Vector2( 66.1167, -2.62799 )
[node name="ShaderGrass58" parent="." instance=ExtResource( 5 )]
position = Vector2( 171.471, 322.227 )
position = Vector2( 62.2307, -4.047 )
z_index = -1
[node name="ShaderGrass59" parent="." instance=ExtResource( 5 )]
position = Vector2( 179.399, 323.703 )
position = Vector2( 70.1587, -2.57098 )
[node name="ShaderGrass60" parent="." instance=ExtResource( 5 )]
position = Vector2( 176.695, 321.917 )
position = Vector2( 67.4547, -4.35699 )
z_index = -1
[node name="ShaderGrass61" parent="." instance=ExtResource( 5 )]
position = Vector2( 190.743, 323.538 )
position = Vector2( 81.5027, -2.73599 )
[node name="ShaderGrass62" parent="." instance=ExtResource( 5 )]
position = Vector2( 184.646, 323.751 )
position = Vector2( 75.4057, -2.52298 )
[node name="ShaderGrass63" parent="." instance=ExtResource( 5 )]
position = Vector2( 182.244, 321.441 )
position = Vector2( 73.0037, -4.83298 )
z_index = -1
[connection signal="timeout" from="UserInterface/HUD/HUDOverlay/GetBackTimer/Timer" to="GameplaySignalManager" method="_on_Timer_timeout"]