Skip to content

Commit

Permalink
Merge pull request #291 from GTcreyon/refactor-generalize-solids
Browse files Browse the repository at this point in the history
Generalize solid-object scripts
  • Loading branch information
GTcreyon authored Mar 6, 2024
2 parents ec35a34 + 0cfd03c commit 0befeed
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 30 deletions.
8 changes: 0 additions & 8 deletions classes/solid/log/log.gd

This file was deleted.

4 changes: 2 additions & 2 deletions classes/solid/log/log.tscn
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
[gd_scene load_steps=5 format=3 uid="uid://ckc4syjyp8xrq"]

[ext_resource type="Texture2D" uid="uid://s3jueu7q0hyf" path="res://classes/solid/log/log.png" id="1"]
[ext_resource type="Script" path="res://classes/solid/solid_object.gd" id="1_ana6i"]
[ext_resource type="Material" uid="uid://bneuwo0j5ktnl" path="res://shaders/aa.tres" id="2"]
[ext_resource type="Script" path="res://classes/solid/log/log.gd" id="3"]

[sub_resource type="RectangleShape2D" id="1"]
size = Vector2(16, 19)

[node name="Log" type="StaticBody2D"]
z_index = -1
collision_mask = 0
script = ExtResource("3")
script = ExtResource("1_ana6i")

[node name="Sprite2D" type="Sprite2D" parent="."]
material = ExtResource("2")
Expand Down
14 changes: 0 additions & 14 deletions classes/solid/rocks/big_rock/big_rock.gd

This file was deleted.

12 changes: 6 additions & 6 deletions classes/solid/rocks/big_rock/big_rock.tscn
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[gd_scene load_steps=3 format=2]
[gd_scene load_steps=3 format=3 uid="uid://bhiyyqle055lo"]

[ext_resource path="res://classes/solid/rocks/big_rock/big_rock.png" type="Texture2D" id=1]
[ext_resource path="res://classes/solid/rocks/big_rock/big_rock.gd" type="Script" id=2]
[ext_resource type="Texture2D" uid="uid://dq4ylqrb3vjk6" path="res://classes/solid/rocks/big_rock/big_rock.png" id="1"]
[ext_resource type="Script" path="res://classes/solid/solid_object_mirrorable.gd" id="1_47710"]

[node name="BigRock" type="StaticBody2D"]
script = ExtResource( 2 )
script = ExtResource("1_47710")

[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource( 1 )
texture = ExtResource("1")

[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."]
polygon = PackedVector2Array( -40, 32, -14, -22, -4, -29, 24, -15, 24, -2, 40, 32 )
polygon = PackedVector2Array(-40, 32, -14, -22, -4, -29, 24, -15, 24, -2, 40, 32)
22 changes: 22 additions & 0 deletions classes/solid/solid_object.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class_name SolidObject
extends StaticBody2D
## A StaticBody2D which can be disabled in the level designer.
##
## The meaning of "disabled" depends on the value of disable_mode.
## If disable_mode is set to DISABLE_MODE_REMOVE, a disabled object will become
## non-solid (it will be "removed" from the physics simulation). Otherwise,
## the object will remain solid no matter what.

@export var disabled = false: set = set_disabled


func set_disabled(val):
disabled = val

# Set the object's process mode as appropriate.
# When disable_mode = DISABLE_MODE_REMOVE, this makes the object
# non-solid when disabled.
if disabled:
process_mode = Node.PROCESS_MODE_DISABLED
else:
process_mode = Node.PROCESS_MODE_INHERIT
90 changes: 90 additions & 0 deletions classes/solid/solid_object_mirrorable.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
class_name SolidObjectMirrorable
extends SolidObject
## A StaticBody2D which can be both disabled or mirrored in the level designer.

static var mirrored_shapes: Dictionary = {}
static var unmirrored_shapes: Dictionary = {}

@export var mirror = false: set = set_mirror


func set_mirror(val):
# Store whether the new value is DIFFERENT from the old.
# This allows several things to flip correctly without storing their
# old positions.
var changed = val != mirror

# Write to the mirroring value itself.
mirror = val

# If mirroring didn't change, no child nodes need to be processed. Abort.
if !changed:
return

# If mirroring did change, flip all children.
for child in get_children():
# Flip any child's transformation.
if child is Node2D:
(child as Node2D).position.x *= -1
(child as Node2D).rotation *= -1

# Type-specific mirroring logic may also be needed.

# If the child has its own mirroring logic, fall through into that.
if child.has_method("set_mirror"):
child.set_mirror(mirror)

# Flip sprites.
elif child is Sprite2D or child is AnimatedSprite2D:
child.flip_h = !child.flip_h if changed else child.flip_h

# Flip polygons and collision polygons, which conveniently share an
# interface as of Godot 4.1.
elif child is Polygon2D or child is CollisionPolygon2D:
child.polygon = flip_points(child.polygon)

# Flip collision shapes that can flip.
elif child is CollisionShape2D:
var shape := (child as CollisionShape2D).shape
if changed and mirror:
# On becoming mirrored, make a copy of the shape resource
# so we can mirror its data without messing up any other users
# of the shape resource (yes, the shapes are resources!).
shape = shape.duplicate() # Make and store the duplicate...
child.shape = shape # ...then give it to the collider.
# Resources are reference-counted, and theoretically every
# duplicate is unique to the object that created it--meaning
# old duplicates should automatically be deleted and it
# shouldn't become a memory leak.
# If that's not the case (or having a separate mirrored copy
# for every mirrored solid becomes a problem), a more complex
# solution involving static dictionaries may be in order.
# Admittedly, the current solution was chosen for its simplicity
# more than its optimalcy.

# Line segment with two points. Invert X of both points.
if shape is SegmentShape2D:
(shape as SegmentShape2D).a.x *= -1
(shape as SegmentShape2D).b.x *= -1
# Infinite boundary. Invert the normal on the X axis.
elif shape is WorldBoundaryShape2D:
(shape as WorldBoundaryShape2D).normal.x *= -1
# Convex polygon. Invert all points' X.
elif shape is ConvexPolygonShape2D:
var polygon := shape as ConvexPolygonShape2D
polygon.points = flip_points(polygon.points)
# Concave polygon. Invert all points' X.
elif shape is ConcavePolygonShape2D:
var polygon := shape as ConcavePolygonShape2D
polygon.segments = flip_points(polygon.segments)
# No other collision shape has information which needs flipping.

# That should cover all types of nodes that a solid object is likely
# to contain.


func flip_points(points: PackedVector2Array) -> PackedVector2Array:
# Invert X of all points.
for i in points.size():
points[i].x *= -1
return points

0 comments on commit 0befeed

Please sign in to comment.