Added swinging and wrapping rope

Signed-off-by: Ethan Wellenreiter <ewellenreiter@gmail.com>
This commit is contained in:
Ethan Wellenreiter 2025-01-03 23:15:54 -05:00
parent 786637cdfa
commit 8ef0094818
12 changed files with 406 additions and 87 deletions

4
assets/normal_shape.tres Normal file
View File

@ -0,0 +1,4 @@
[gd_resource type="RectangleShape2D" format=3 uid="uid://bgprpaxew08jq"]
[resource]
size = Vector2(101, 149)

BIN
assets/rope.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

18
assets/rope_segment.tscn Normal file
View File

@ -0,0 +1,18 @@
[gd_scene load_steps=3 format=3 uid="uid://b5i7mo2ti3n4o"]
[ext_resource type="Script" path="res://player/rope_segments.gd" id="1_p3r4l"]
[ext_resource type="Texture2D" uid="uid://d3s8xygckp34r" path="res://assets/rope.png" id="2_ar47d"]
[node name="RopeSegment" type="Node2D"]
script = ExtResource("1_p3r4l")
[node name="RayCast2D" type="RayCast2D" parent="."]
target_position = Vector2(1e+06, 0)
[node name="Sprites" type="Node2D" parent="."]
scale = Vector2(0.05, 0.05)
[node name="Sprite2D" type="Sprite2D" parent="Sprites"]
rotation = 1.5708
texture = ExtResource("2_ar47d")
offset = Vector2(0, -200)

BIN
assets/swing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

4
assets/swing_shape.tres Normal file
View File

@ -0,0 +1,4 @@
[gd_resource type="RectangleShape2D" format=3 uid="uid://bx8h1vfaumcxm"]
[resource]
size = Vector2(129, 100)

View File

@ -7,7 +7,7 @@ extends RayCast2D
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
var aim_dir : Vector2 = player.position
var aim_dir : Vector2 = player.global_position
if player.MK:
aim_dir = get_global_mouse_position()
else:
@ -26,12 +26,13 @@ func _process(delta: float) -> void:
if is_colliding(): # process the swing
#print("shooting")
var col_point : Vector2 = get_collision_point()
var dist : float = player.position.distance_to(col_point)
print(col_point," ", dist," ", fire_range)
var dist : float = player.global_position.distance_to(col_point)
print(col_point," ", dist," ", fire_range, " ", player.global_position)
if dist < fire_range:
player.connection_points.append(col_point)
player.connection_point = col_point
player.rope_length = dist
player.on_rope = true
player.rope.add_rope_seg(col_point)
@ -44,7 +45,8 @@ func _process(delta: float) -> void:
elif player.on_rope:
print("was_on_rope")
player.on_rope = false
player.connection_points.clear()
player.connection_point = Vector2.ZERO
player.rope.clear_rope()
# release rope
pass

View File

@ -8,20 +8,26 @@ class_name Player
@export var DASH_DISTANCE : float = 5
@export var DASH_TIME_LENGTH : float = 1
@export var SWING_SWAY : float = 100.0
@export var ROPE_MAX_DISTANCE : float = 10000
var connection_points : PackedVector2Array = PackedVector2Array()
var rope_length : float = -1
@export var SWING_SWAY : float = 200.0
@export var DAMPENING : float = 0.8
@export var MID_AIR_MOVEMENT_SPEED : float = 300.0
const MOVEMENT_MARGIN : float = 0.01
var DASH_SPEED = DASH_DISTANCE/DASH_TIME_LENGTH
var MK : bool = true # mouse and keyboard or controller mode
var connection_point : Vector2 = Vector2.ZERO
var rope_length : float = -1
var on_rope : bool = false
@onready var rope : Rope = %Rope
@onready var sprite : AnimatedSprite2D = $AnimatedSprite2D
func add_gravity(delta: float) -> void:
@ -36,31 +42,15 @@ func _physics_process(delta: float) -> void:
if on_rope: # handle the stuff here with if it's hanging at the time
#print("point: ", connection_points[-1], " ", position)
var conn_dir : Vector2 = connection_points[-1] - position
#var y_dir = self.up_direction * (1 if (self.up_direction.dot(conn_dir) > 0) else -1)
#var angle : float = y_dir.angle_to(connection_points[-1] - position)
var conn_dir : Vector2 = connection_point - global_position
var angle : float = (-self.up_direction).angle_to(conn_dir)
#print(angle)
#general tangential
var tangential_direction : Vector2 = Vector2(-conn_dir.y, conn_dir.x) # clockwise tangential
## tangential pointing down
#var tangential_direction : Vector2 = Vector2.ZERO
#if conn_dir.x > 0:
##print("c")
#tangential_direction = Vector2(-conn_dir.y, conn_dir.x) # clockwise tangential
#else:
##print("cc")
#tangential_direction = Vector2(conn_dir.y, -conn_dir.x) # counter-clockwise tangential
#tangential_direction = tangential_direction.normalized()
velocity = velocity.project(tangential_direction) # takes the part of the velocity that is tangent the the swing arc
#print(tangential_direction)
#print(velocity)
#print(pow(DAMPENING, delta))
if velocity.dot(up_direction) > 0:
velocity *= pow(DAMPENING, delta)
@ -70,28 +60,62 @@ func _physics_process(delta: float) -> void:
velocity += delta*SWING_SWAY*(tangential_direction* (1 if direction > 0 else -1)).normalized()
move_and_slide()
if position.distance_to(connection_points[-1]) != rope_length:
var diff :float = rope_length - position.distance_to(connection_points[-1]) # negative if farther
#print(diff)
#print(conn_dir.normalized())
position -= conn_dir.normalized()*diff
if global_position.distance_to(connection_point) != rope_length: # correct the player position to onto the rope length position of the pendulum
var diff :float = rope_length - global_position.distance_to(connection_point) # negative if farther
global_position -= conn_dir.normalized()*diff
sprite.play("swing")
$CollisionShape2D.shape = load("res://assets/swing_shape.tres")
if velocity.x > MOVEMENT_MARGIN:
sprite.flip_h = true
elif velocity.x < -MOVEMENT_MARGIN:
sprite.flip_h = false
#print(position.distance_to(connection_points[-1]), " ", rope_length)
sprite.rotation = angle + PI
$CollisionShape2D.transform = Transform2D(0,Vector2(-3,18))
$CollisionShape2D.rotate(angle + PI)
#print(position.distance_to(connection_point), " ", rope_length)
pass
else:
#reset sprite orientation here
$CollisionShape2D.shape = load("res://assets/normal_shape.tres")
sprite.rotation = 0
$CollisionShape2D.transform = Transform2D(0,Vector2(-1.5,-0.5))
# Handle jump.
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
var direction := Input.get_axis("move_left", "move_right") ## walking left and right
if direction:
var acting_speed : float = WALK_SPEED
if direction * velocity.x < 0:
acting_speed *= SLOW_SPEED_MULTIPLIER
velocity.x = clamp(velocity.x + (direction*delta*acting_speed), -WALK_SPEED, WALK_SPEED)
if is_on_floor():
if direction:
var acting_speed : float = WALK_SPEED
if direction * velocity.x < 0:
acting_speed *= SLOW_SPEED_MULTIPLIER
velocity.x = clamp(velocity.x + (direction*delta*acting_speed), -WALK_SPEED, WALK_SPEED)
if direction > MOVEMENT_MARGIN:
sprite.play("run")
sprite.flip_h = false
elif direction < -MOVEMENT_MARGIN:
sprite.play("run")
sprite.flip_h = true
else:
velocity.x = move_toward(velocity.x, 0, SLOW_SPEED_MULTIPLIER*WALK_SPEED*delta)
else:
velocity.x = move_toward(velocity.x, 0, SLOW_SPEED_MULTIPLIER*WALK_SPEED*delta)
if direction:
var acting_speed : float = MID_AIR_MOVEMENT_SPEED
if direction * velocity.x < 0:
acting_speed *= SLOW_SPEED_MULTIPLIER
if abs(velocity.x + (direction * delta * acting_speed)) < MID_AIR_MOVEMENT_SPEED:
velocity.x = clamp(velocity.x + (direction*delta*acting_speed), -MID_AIR_MOVEMENT_SPEED, MID_AIR_MOVEMENT_SPEED)
move_and_slide()
if (velocity == Vector2.ZERO):
sprite.play("idle")
#print("v3: ", velocity)

View File

@ -1,32 +1,108 @@
[gd_scene load_steps=6 format=3 uid="uid://brhc07imuholv"]
[gd_scene load_steps=19 format=3 uid="uid://brhc07imuholv"]
[ext_resource type="Texture2D" uid="uid://87gegwimvax2" path="res://assets/test_player.png" id="1_0ushe"]
[ext_resource type="Script" path="res://player/player.gd" id="1_x227h"]
[ext_resource type="Texture2D" uid="uid://dn6r0pyadv8ah" path="res://assets/idle-1.png" id="2_6w7jv"]
[ext_resource type="Script" path="res://player/looking.gd" id="3_n7yd4"]
[ext_resource type="Texture2D" uid="uid://ce2w78k77ugei" path="res://assets/pngtree-arrow-shape-red-simple-direction-png-image_5215909.png" id="4_3fyds"]
[ext_resource type="Texture2D" uid="uid://cj1qn8wk1oicx" path="res://assets/idle-2.png" id="3_sv1xb"]
[ext_resource type="Texture2D" uid="uid://dvsb8vc8f86w1" path="res://assets/idle-3.png" id="4_1fo7r"]
[ext_resource type="Texture2D" uid="uid://dcjmkr3lhxwi5" path="res://assets/arrow.tres" id="4_c2t2l"]
[ext_resource type="Texture2D" uid="uid://d3vp3c8nqktx7" path="res://assets/run-1.png" id="5_00etc"]
[ext_resource type="Script" path="res://player/rope.gd" id="5_thjoo"]
[ext_resource type="Texture2D" uid="uid://brwxhphgmui7h" path="res://assets/idle-4.png" id="5_y7yb1"]
[ext_resource type="Texture2D" uid="uid://dmsx3wyah7tqv" path="res://assets/run-2.png" id="6_fq4sj"]
[ext_resource type="Texture2D" uid="uid://besblp1nasfcg" path="res://assets/idle-5.png" id="6_rcurq"]
[ext_resource type="Texture2D" uid="uid://dekab4yvffotr" path="res://assets/run-3.png" id="7_gyyvx"]
[ext_resource type="Texture2D" uid="uid://ca8fxmbredrie" path="res://assets/run-4.png" id="8_0s8qb"]
[ext_resource type="Texture2D" uid="uid://cyfnxnbpgw3ig" path="res://assets/run-5.png" id="9_k0qre"]
[ext_resource type="Texture2D" uid="uid://bkaop26r76o40" path="res://assets/swing.png" id="12_dxoth"]
[ext_resource type="Shape2D" uid="uid://bgprpaxew08jq" path="res://assets/normal_shape.tres" id="14_fhcn0"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_fbsbu"]
size = Vector2(96, 306)
[sub_resource type="SpriteFrames" id="SpriteFrames_1bpu4"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": ExtResource("2_6w7jv")
}, {
"duration": 1.0,
"texture": ExtResource("3_sv1xb")
}, {
"duration": 1.0,
"texture": ExtResource("4_1fo7r")
}, {
"duration": 1.0,
"texture": ExtResource("5_y7yb1")
}, {
"duration": 1.0,
"texture": ExtResource("6_rcurq")
}],
"loop": true,
"name": &"idle",
"speed": 5.0
}, {
"frames": [{
"duration": 1.0,
"texture": ExtResource("5_00etc")
}, {
"duration": 1.0,
"texture": ExtResource("6_fq4sj")
}, {
"duration": 1.0,
"texture": ExtResource("7_gyyvx")
}, {
"duration": 1.0,
"texture": ExtResource("8_0s8qb")
}, {
"duration": 1.0,
"texture": ExtResource("9_k0qre")
}],
"loop": true,
"name": &"run",
"speed": 10.0
}, {
"frames": [{
"duration": 1.0,
"texture": ExtResource("12_dxoth")
}],
"loop": true,
"name": &"swing",
"speed": 5.0
}]
[node name="CharacterBody2D" type="CharacterBody2D"]
[node name="Node2D" type="Node2D"]
[node name="Player" type="CharacterBody2D" parent="."]
unique_name_in_owner = true
script = ExtResource("1_x227h")
[node name="Sprite2D" type="Sprite2D" parent="."]
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="Player"]
scale = Vector2(0.0729065, 0.0729065)
sprite_frames = SubResource("SpriteFrames_1bpu4")
animation = &"idle"
[node name="Sprite2D" type="Sprite2D" parent="Player"]
visible = false
scale = Vector2(0.25, 0.25)
texture = ExtResource("1_0ushe")
[node name="Camera2D" type="Camera2D" parent="."]
[node name="Camera2D" type="Camera2D" parent="Player"]
zoom = Vector2(0.5, 0.5)
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(-2, 0)
shape = SubResource("RectangleShape2D_fbsbu")
[node name="CollisionShape2D" type="CollisionShape2D" parent="Player"]
position = Vector2(-1.5, -0.5)
shape = ExtResource("14_fhcn0")
[node name="RayCast2D" type="RayCast2D" parent="."]
[node name="RayCast2D" type="RayCast2D" parent="Player"]
target_position = Vector2(1e+06, 0)
collide_with_areas = true
script = ExtResource("3_n7yd4")
[node name="Sprite2D" type="Sprite2D" parent="RayCast2D"]
[node name="Sprite2D" type="Sprite2D" parent="Player/RayCast2D"]
visible = false
position = Vector2(83, 0)
scale = Vector2(0.266667, 0.266667)
texture = ExtResource("4_3fyds")
texture = ExtResource("4_c2t2l")
[node name="Rope" type="Node2D" parent="."]
unique_name_in_owner = true
script = ExtResource("5_thjoo")

View File

@ -1,40 +1,140 @@
extends Node2D
class_name Rope
@onready var player : Player = get_parent()
@onready var rope_seg_scene : PackedScene = preload("res://assets/rope_segment.tscn")
@onready var player : Player = %Player
@export var DIST_MARGIN : float = 0.01
var rope_segments : Array[RopeSegment] = []
func add_rope_seg(conn_point : Vector2) -> void:
var rope_seg : RopeSegment = rope_seg_scene.instantiate()
add_child(rope_seg)
rope_seg.set_conn_point(conn_point)
rope_seg.update_sprite_heading(player.global_position)
rope_seg.update_ray_heading(player.global_position)
rope_segments.append(rope_seg)
func shift_add_rope_seg(conn_point : Vector2) -> void:
add_rope_seg(rope_segments[-1].conn_point)
rope_segments[-2].conn_point = conn_point
var t1 = rope_segments[-2]
rope_segments[-2] = rope_segments[-1]
rope_segments[-1] = t1
rope_segments[-2].update_sprite_heading(conn_point)
rope_segments[-2].update_ray_heading(player.global_position)
rope_segments[-1].update_sprite_heading(player.global_position)
rope_segments[-1].update_ray_heading(player.global_position)
func pop_rope_seg() -> void:
if (rope_segments.size() == 0):
print("ERROR: popping from empty rope")
else:
var rope_seg : RopeSegment = rope_segments[-1]
remove_child(rope_seg)
rope_segments.remove_at(rope_segments.size()-1)
rope_seg.safe_destroy()
func shift_pop_rope_seg() -> void:
if (rope_segments.size() == 0):
print("ERROR: popping from empty rope")
else:
var t1 = rope_segments[-2]
rope_segments[-2] = rope_segments[-1]
rope_segments[-1] = t1
rope_segments[-2].conn_point = rope_segments[-1].conn_point
rope_segments[-2].update_sprite_heading(player.global_position)
rope_segments[-2].update_ray_heading(player.global_position)
pop_rope_seg()
func clear_rope() -> void:
while not rope_segments.is_empty():
pop_rope_seg()
func check_new_coll():
var cur_rope = rope_segments[-1]
if cur_rope.rope_ray.is_colliding():
var col_point : Vector2 = cur_rope.rope_ray.get_collision_point()
var dist : float = player.global_position.distance_to(col_point)
#print(player.rope_length, " ", dist)
if player.rope_length - dist > DIST_MARGIN:
#if (rope_segments.size() <= 1):
#print("adding rope_seg ", player.rope_length, " " ,dist, " ", player.rope_length - dist)
shift_add_rope_seg(col_point)
rope_segments[-2].connection_angle = rope_segments[-2].conn_point.angle_to_point(player.global_position)
var tangent : Vector2 = col_point - player.global_position
tangent = Vector2(-tangent.y, tangent.x)
rope_segments[-2].clockwise = player.velocity.dot(tangent) > 0
#cur_rope.update_sprite_heading(col_point)
player.rope_length = dist
player.connection_point = col_point
else:
var counter : int = rope_segments.size() - 2
var pop : bool = false
while counter >= 0:
if rope_segments[counter].rope_ray.is_colliding(): # safety check
var temp_col_point : Vector2 = rope_segments[counter].rope_ray.get_collision_point()
#var temp_dist : float = player.global_position.distance_to(temp_col_point)
if rope_segments[counter].conn_point.distance_to(rope_segments[counter].rope_ray.get_collision_point()) < DIST_MARGIN and \
(rope_segments[counter].conn_point.angle_to_point(player.global_position) - rope_segments[counter].connection_angle) * (1 if rope_segments[counter].clockwise else -1) > 0: # if the collision of the other ray is longer (so it can see the earlier connection point)
print("removing ",counter, " ", rope_segments[counter].conn_point.distance_to(rope_segments[counter].rope_ray.get_collision_point()))
player.connection_point = rope_segments[counter].conn_point
player.rope_length = player.global_position.distance_to(player.connection_point)
shift_pop_rope_seg()
counter -= 1
else:
break
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta: float) -> void:
func _process(delta: float) -> void:
#print(global_position)
if player.on_rope:
var aim_dir : Vector2 = player.connection_points[-1]
if player.on_rope and rope_segments.size() >= 1:
#print("hi")
rope_segments[-1].update_sprite_heading(player.global_position)
for i in range(rope_segments.size()):
rope_segments[i].update_ray_heading(player.global_position)
#print("aim_dir ", aim_dir)
look_at(aim_dir)
#look_at(aim_dir)
if is_colliding(): # safety if statement. should always be true realistically
#print("passive")
var col_point : Vector2 = get_collision_point()
var dist : float = player.position.distance_to(col_point)
#print(col_point," ", player.connection_points[-1])
#if dist < fire_range:
#print(dist, " ", player.position.distance_to(player.connection_points[-1]))
#
while dist - player.position.distance_to(player.connection_points[-1]) > 10: #margin of 10
print("yowdy")
if (player.connection_points.size() > 1):
print(player.connection_points)
print("hi")
player.connection_points.remove_at(player.connection_points.size()-1)
player.rope_length = dist
print("bye")
else:
break
#while player.connection_points[-1].distance_to(col_point) > 5: # margin
#
if player.rope_length - dist > 10:
print("add")
player.connection_points.append(col_point)
player.rope_length = dist
check_new_coll()
#if is_colliding(): # safety if statement. should always be true realistically
##print("passive")
#var col_point : Vector2 = get_collision_point()
#var dist : float = player.position.distance_to(col_point)
##print(col_point," ", player.connection_points[-1])
##if dist < fire_range:
##print(dist, " ", player.position.distance_to(player.connection_points[-1]))
##
#while dist - player.position.distance_to(player.connection_points[-1]) > 10: #margin of 10
#print("yowdy")
#if (player.connection_points.size() > 1):
#print(player.connection_points)
#print("hi")
#player.connection_points.remove_at(player.connection_points.size()-1)
#player.rope_length = dist
#print("bye")
#else:
#break
##while player.connection_points[-1].distance_to(col_point) > 5: # margin
##
#if player.rope_length - dist > 10:
#print("add")
#player.connection_points.append(col_point)
#player.rope_length = dist
pass

66
player/rope_segments.gd Normal file
View File

@ -0,0 +1,66 @@
extends Node2D
class_name RopeSegment
var tileSize = 8.9
## Called when the node enters the scene tree for the first time.
#func _ready() -> void:
#pass # Replace with function body.
#
#
## Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta: float) -> void:
#pass
var conn_point : Vector2
var rope_sprite : Node2D
var rope_ray : RayCast2D
var connection_angle : float
var clockwise : bool
func _ready() -> void:
rope_sprite = $Sprites
rope_ray = $RayCast2D
func set_conn_point(connection_point : Vector2):
conn_point = connection_point
func update_ray_heading(player_global_pos: Vector2) -> void:
rope_ray.global_position = player_global_pos
rope_ray.look_at(conn_point)
func update_sprite_heading(global_pos: Vector2) -> void:
rope_sprite.global_position = global_pos
rope_sprite.look_at(conn_point)
var distance = rope_sprite.global_position.distance_to(conn_point)
var tile_count = int(distance/tileSize)+1
#print(distance, " ", tile_count)
var child_count : int = rope_sprite.get_child_count()
var count : int = 0
if child_count > tile_count:
for i in range(child_count-1,tile_count,-1):
var child : Sprite2D = rope_sprite.get_child(i)
if child == $Sprites/Sprite2D:
continue
else:
rope_sprite.remove_child(child)
child.queue_free()
#for child in rope_sprite.get_child()
else:
for i in range(child_count, tile_count):
var newRopeTile = $Sprites/Sprite2D.duplicate()
rope_sprite.add_child(newRopeTile)
newRopeTile.owner = rope_sprite
newRopeTile.position = Vector2((i * 175), 0)
func safe_destroy() -> void:
rope_sprite.queue_free()
remove_child(rope_sprite)
rope_ray.queue_free()
remove_child(rope_ray)
queue_free()

View File

@ -19,6 +19,12 @@ config/icon="res://icon.svg"
Universe="*res://world/universe/universe.gd"
[display]
window/size/viewport_width=1920
window/size/viewport_height=1080
window/stretch/mode="canvas_items"
[input]
ui_left={

View File

@ -1,11 +1,11 @@
[gd_scene load_steps=7 format=3 uid="uid://dojvn2guqhhel"]
[gd_scene load_steps=9 format=3 uid="uid://dojvn2guqhhel"]
[ext_resource type="Texture2D" uid="uid://b48bhtfvrv7rc" path="res://assets/background.png" id="1_t0pgr"]
[ext_resource type="PackedScene" uid="uid://brhc07imuholv" path="res://player/player.tscn" id="2_fpbhy"]
[ext_resource type="Texture2D" uid="uid://d0oq3rgb204fl" path="res://assets/ground.png" id="3_rvbjd"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_ptfhu"]
size = Vector2(1980, 598)
size = Vector2(1980, 26)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_aqnnp"]
size = Vector2(1980, 621)
@ -13,6 +13,12 @@ size = Vector2(1980, 621)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_1iolf"]
size = Vector2(1965, 598)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_1q5cw"]
size = Vector2(1974, 298.559)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_d8lc8"]
size = Vector2(243.5, 11.0001)
[node name="Level" type="Node2D"]
[node name="Background" type="TextureRect" parent="."]
@ -31,7 +37,7 @@ position = Vector2(397, -187)
position = Vector2(574.5, 200.5)
[node name="CollisionShape2D" type="CollisionShape2D" parent="Walls_and_ground"]
position = Vector2(-44.5, 88.5)
position = Vector2(-44.5, -197.5)
shape = SubResource("RectangleShape2D_ptfhu")
[node name="TextureRect" type="TextureRect" parent="Walls_and_ground"]
@ -74,8 +80,21 @@ texture = ExtResource("3_rvbjd")
position = Vector2(-1062.73, -746.059)
[node name="CollisionShape2D" type="CollisionShape2D" parent="Walls_and_ground4"]
shape = SubResource("RectangleShape2D_1iolf")
position = Vector2(-3.27148, 143.78)
shape = SubResource("RectangleShape2D_1q5cw")
[node name="Sprite2D" type="Sprite2D" parent="Walls_and_ground4"]
position = Vector2(1.5, 290.5)
texture = ExtResource("3_rvbjd")
[node name="Walls_and_ground5" type="StaticBody2D" parent="."]
position = Vector2(-216, -320)
[node name="CollisionShape2D" type="CollisionShape2D" parent="Walls_and_ground5"]
position = Vector2(137.979, 875.559)
shape = SubResource("RectangleShape2D_d8lc8")
[node name="Sprite2D" type="Sprite2D" parent="Walls_and_ground5"]
position = Vector2(137.479, 875.059)
scale = Vector2(0.122864, 1)
texture = ExtResource("3_rvbjd")