Godot Version
v4.6.stable.official [89cea1439]
Question
My CharacterBody2D objects each contain a number of Bodypart objects that inherit from Node2D. The Bodypart contains its Sprite2D. Some Bodypart belong to other Bodyparts, so that they inherit behaviours and positions :
|- CharacterBody2D
|- Bodypart
|- Sprite2D
|- Bodypart
|- Sprite2D
|- Bodypart
|- Sprite2D
|- Bodypart
|- Sprite2D
|- Bodypart
|- Sprite2D
Each Bodypart is associated with a region in the spritesheet AtlasTexture.atlas, and also needs its default position relative to its parents, so the head sits atop the torso and the hand at the end of the arm.
Each Bodypart also carries an int related to its health, and another int related to hit localization.
Now, the trick is that everything spawns at runtime, from the code. Nothing is set in the Editor, and it’s the way I prefer to work.
The way that I go about this business so far is a Dictionary like so :
- a “spritesheet” key with the resource path to its .png image as value
- a “bodyparts” key with a
Dictionaryof all bodyparts-Stringas keys and their parent as values - a key for each bodypart-
Stringwith aRect2telling theregionin the .png image they are drawn from - a key for each bodypart-
String+”_position” telling their default position - and so forth
D_spriteSheet[“spritesheet”] = ResourceLoader.load(“res://assets/sprites/image.png”,“image”,ResourceLoader.CACHE_MODE_REPLACE)
D_spriteSheet[“bodyparts”] = {“leg_right”:“root”,“leg_left”:“root”,“torso”:“root”,“head”:“torso”,“arm_right”:“torso”,“arm_left”:“torso”,“hand_right”:“arm_right”,“hand_left”:“arm_left”}
D_spriteSheet[“head”] = Rect2(32,16,4,6)
D_spriteSheet[“torso”] = Rect2(16,16,8,11)
D_spriteSheet[“leg_right”] = Rect2(48,16,6,10)
D_spriteSheet[“leg_left”] = Rect2(16,32,6,10)
D_spriteSheet[“arm_right”] = Rect2(32,32,4,8)
D_spriteSheet[“arm_left”] = Rect2(48,32,5,6)
D_spriteSheet[“hand_right”] = Rect2(16,48,3,3)
D_spriteSheet[“hand_left”] = Rect2(32,48,3,3)
D_spriteSheet["torso_position"] = Vector2(0,0)
D_spriteSheet["head_position"] = Vector2(0,-9)
D_spriteSheet["leg_right_position"] = Vector2(-2,9)
D_spriteSheet["leg_left_position"] = Vector2(2,9)
D_spriteSheet["arm_right_position"] = Vector2(-6,0)
D_spriteSheet["arm_left_position"] = Vector2(7,-1)
D_spriteSheet["hand_right_position"] = Vector2(-1,4)
D_spriteSheet["hand_left_position"] = Vector2(2,4)
[...]
This Dictionary is passed to the CharacterBody _ready() to create its child-Bodyparts:
var D_bodyparts : Dictionary = D_spriteSheet[“bodyparts”]
for bodypartString in D_bodyparts.keys() :
atlas = AtlasTexture.new()
atlas.atlas = D_spriteSheet["spritesheet"]
atlas.region = D_spriteSheet[bodypartString]
texture = atlas
var parent : Node2D = find_child(D_bodyparts[bodypartString],true,false)
if D_bodyparts[bodypartString] == "root":
parent = bodyCanvas
parent.add_child(bodypart)
[...]
This allows me to switch spritesheets, positions, health… for any Bodypart in a CharacterBody2D quite easily, by editing the D_spritesheet Dictionary without changing the CharacterBody2D code.
Nowadays, the D_spritesheet Dictionary is entirely written in a spawner method, and I move this spawner code around as I go along and think of better places to put it in (in the main Node, in a map Node, in an container Node wrapping the CharacterBody2D…).
My problem :
I would like to store this D_spritesheet Dictionary in an inert Resource that I could access from anywhere.
The D_spritesheets are a finite number, and many CharacterBody2D reuse them, so it seemed like a good idea to create them through a custom Resource… Plus, the setup code in the CharacterBody2D would fit nicely in the Resource script _ready().
But I can’t seem to see how to do it, since
- I don’t have a fixed number of
Bodyparts (aCharacterBody2Dcould have four hands, another two heads…). I would have to create aResourcescript for each, then create oneResourcefrom this script, all to get the same as now… seems overly complicated. - The number of keys in the
Dictionarydepends on the number ofBodyparts. - as for the nested
DictionaryD_spriteSheet[“bodyparts”] : to be able to create such aResourcein the Editor, I would have to be able to select a bodypart-Stringin a field then select another bodypart-Stringfrom the sameResourceto set as its parent. Which, AFAIK, isn’t possible - the sheer number of entries I would have to edit through fields if I created
Resourcesthat only allow for 1-key-1-value associations would be huge. MyDictionaryalready has at most 50 one-to-one associations in it, and it’s set to grow even bigger (as I create models with moreBodyparts in the spritesheet, withRemoteTransform2Dand whatnot). I wouldn’t even know how to putRect2coordinates in there
I tried to look into .res (as opposed to .tres), but I can’t seem to see where they’re going. I have checked a number of videos about the subject, but all I can get from them is the same tired pictures of Resource with two int attributes and a simple _ready(). I believe I’m missing something that could turn Resources in what I’m looking for.
The alternative is JSON files. But at this rate, I’d rather keep it all in GDscript.
