![]() |
Attention | Topic was automatically imported from the old Question2Answer platform. |
![]() |
Asked By | gmichael27 |
Hello,
I’m attempting to set up some “static” / hard-coded objects that can be referenced throughout the code in an attempt to keep things DRY.
My goal is to have an enumerated class which encapsulates some common properties that can be used across multiple classes, but can also be specified by an export variable. In this case, “Alignment” contains information for good/evil/neutral entities’ UI color, collision layer bits for various physics bodies, and more down the road I’m sure.
Previously I used a simple enum enum Alignment { GOOD, EVIL, NEUTRAL }
which allowed both referencing constants AND exporting them for easy drop-down selection in the editor, but I found myself writing very similar conditional statements against these values such as:
Old Character.gd:
extends Spatial
class_name Character
enum Alignment { GOOD, EVIL, NEUTRAL }
onready var hitbox = $Hitbox
onready var box: CSGBox = $Box
export (Alignment) var alignment = Alignment.EVIL setget set_alignment;
func set_alignment(val):
alignment = val
if (alignment == Alignment.GOOD):
box.material.albedo_color = Color( 0.25, 1, 1, 0.25)
hitbox.set_collision_layer_bit(2, true)
hitbox.set_collision_mask_bit(7, true)
elif (alignment == Alignment.EVIL):
box.material.albedo_color = Color( 1, 0.25, 0.25, 0.25)
hitbox.set_collision_layer_bit(5, true)
hitbox.set_collision_mask_bit(8, true)
else:
# etc
After doing this in a few different places, I wanted to move certain properties to a class and define some hard-coded instances of that class. I’ve come up with a solution that doesn’t feel very clean, but am wondering if there is a better approach to a scenario like this.
Globals.gd (autoloaded singleton):
extends Node
enum AlignmentKeys {
GOOD,
EVIL,
NEUTRAL
}
var Alignments = {
AlignmentKeys.GOOD: {
"description": "Good",
"color": Color(0.25, 1, 1, 0.25),
"collision_layer": 0,
"movebox_layer": 1,
"hitbox_layer": 2,
"hitbox_mask": 7,
"hurtbox_layer": 3
},
AlignmentKeys.EVIL: {
"description": "Evil",
"color": Color(1, 0.25, 0.25, 0.25),
"collision_layer": 4,
"movebox_layer": 5,
"hitbox_layer": 6,
"hitbox_mask": 3,
"hurtbox_layer": 7
},
AlignmentKeys.NEUTRAL: {
# ...
}
}
Basically the enum AlignmentKeys
are the possible keys for the dictionary Alignments
, which contains all the static data defined for each alignment. To handle exports as well as referencing those “constants”, it looks something like this:
Revised Character.gd:
extends Spatial
class_name Character
onready var hitbox = $Hitbox
onready var box: CSGBox = $Box
export (Globals.AlignmentKeys) var alignment_key = Globals.AlignmentKeys.EVIL;
var alignment = Globals.Alignments[alignment_key] setget set_alignment;
func set_alignment(val):
alignment = val
box.material.albedo_color = alignment.color
hitbox.set_collision_layer_bit(alignment.hitbox_layer, true)
hitbox.set_collision_mask_bit(alignment.hitbox_mask, true)
Again, this works and has cleaned up the amount of conditionals but I can’t help but feel there’s a cleaner way. I was also hoping to use some static typing with a class such as:
class Alignment extends Node:
var description: String;
var color: Color;
var collision_layer: int;
var movebox_layer: int;
var hurtbox_layer: int;
var hitbox_layer: int;
…but I understand that arrays and dictionaries cannot be staticly typed, so I’m not sure if that would be possible.
In short, I am wondering if there’s any way to reference staticly-typed, predefined variables by name across classes in general, but also a strategy to export a possible set of those objects.
Put another way, I can express this pretty easily in Java enum terms and am curious to know if there’s some sort of analog in gdscript.
Alignment.java:
public enum Alignment {
GOOD("Good", Color.BLUE, 0, 1, 2, 7, 3),
EVIL("Evil", Color.RED, 4, 5, 6, 3, 7);
public final String description;
public final Color color;
public final int collisionLayer;
public final int moveboxLayer;
public final int hitboxLayer;
public final int hitboxMask;
public final int hurtboxLayer;
private Alignment(String description, Color color, int collisionLayer, int moveboxLayer, int hitboxLayer, int hitboxMask, int hurtboxLayer) {
this.description = description;
this.color = color;
this.collisionLayer = collisionLayer;
this.moveboxLayer = moveboxLayer;
this.hitboxLayer = hitboxLayer;
this.hitboxMask = hitboxMask;
this.hurtboxLayer = hurtboxLayer;
}
// getters for each property
}
Thanks for any advice! I’ve had trouble finding other Q&A’s about this topic, so I hope it all makes sense.