-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #291 from GTcreyon/refactor-generalize-solids
Generalize solid-object scripts
- Loading branch information
Showing
6 changed files
with
120 additions
and
30 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |