Why can't we reposition a sprite in the script logic?

I’m reading the post here: Access to sprite position property and it seems like positioning sprites is not planned but scaling them via logic is. Why is this? It would be extremely convenient to be able to reposition a sprite within a game object via the logic itself without having to create another game object and deal with parenting, etc.

EDIT: The reason I’m asking: I’d like to create an HP bar to float over my enemies. The HP bar consists of a bar outline and a bar progress sprite which should scale and move to the left as the HP depletes (to avoid drawing primitives each frame.) To do this using the current implementation it seems I would have to create an XP bar object and parent it to the enemy, then create an XP bar progress object and parent that to the XP bar object. This creates what seems like a ton of bloat when I could just set the XP bar progress position to account for the scale change as the HP bar reduces.

Scaling them wasn’t really planned, it was an undocumented feature that for some reason got out.

The main idea is that a gameobject is really cheap to use.
Use the game object to scale and position the sprite, and use multiple game objects if you need to separate the scaling parameters.

(note, I also added the “Questions” category to your posts)

1 Like

Is it really cheaper than just setting the position of a sprite though? It would be pretty powerful to be able to reposition/rescale sprites directly as part of a game object since the ids are easily retrievable in the logic and wouldn’t require inter-object communication then. Or is there a convenient way to access a parent’s variables from within a child object to avoid messaging?

You can move the child game object from the parent object. The object containing the sprite to be moved doesn’t need a script of its own.

1 Like

Here’s the setup I have now:

And here is how it looks in-game with setting the hp bar scaling as the HP diminishes:

hp_bar_enemies

As shown, the HP bar shrinks within the hp_bar sprite but stays centered. I’d like to simply move it to the left to account for the lost HP but there’s no simple way to do so. The example shown here: https://defold.com/examples/basics/parent_child/ only demonstrates a basic animation which is inter-dependent of the parent variables.

EDIT: Also another minor thing: How come if I set the Z position of a sprite in a game object with a higher Z level only the sprite with the lowest Z level is rendered? It would be nice to have some sprites “float” at a higher plane than others. I.e. if I have all my game entities at Z-level 1 then I could have UI related information float at Z-level 2 when desired. Obviously for complex enough UIs it would make more sense for a separate game object and pairing as a child but I’m still wondering why they won’t render if higher Z level.

Are you using a custom render script (if so this might not apply)? In the default render script, only sprites with a z value in the range between -1 and 1 are rendered. Z values are cumulative, so if your game object is sitting at z 0.75 and a sprite within this object is sitting at 0.5, the sprite’s z position will be 1.25 and it will not be rendered.

1 Like

Ah thanks I hadn’t realized the range was between -1 and 1. I’ll try adjusting things to see if this fixes some of the sorting issues. Thanks :slight_smile:

EDIT: Cool, I now have my entity objects at 0.5 and the UI objects at +0.1 from there. This fixes the HP bars appearing behind other enemies.

I’ve done something similar once and remember moving the health bar to a GUI node and using one of Britlz examples to have them follow the game object.

You should switch to using collections + collection factories (not proxies that’s for other uses) as prefab containers instead of raw GOs. It is better in nearly every way. You can have multiple GOs in a collection, and they can reference each other with messages more directly.

1 Like

:+1:

I’ve got a similar bar in my current project, so let me show you how I’ve got it set up:

The “hack_bar_frame” sprite is a static picture of a black frame with white inside.

The “hack_bar” game object has position X -120 relative to the frame. Inside there is a sprite “hack_bar_fill”. It’s just a white bar, same as the one in the middle of the frame. It has position X 120, so it appears centered over the frame. You can see this in the screenshot.
By setting it up like this, I only have to scale the object, no need to change its position.

The label is obviously the big “HACKING…”, the rest of the components are not relevant to the bar.

The code is simple:

function init(self)
  msg.post("hack_bar", hash("disable"))
  msg.post("#hack_bar_frame", hash("disable"))
  msg.post("#label", hash("disable"))
  go.set("hack_bar#hack_bar_fill", "tint", COL.node[self.auth])
  go.set("hack_bar", "scale.x", 0)
end

This hides the bar, sets the progress (scale) of the bar to zero and colours the bar according to the authorisation level of the computer (you can ignore this).

When the player interacts with the computer, this code runs:

msg.post("hack_bar", hash("enable"))
msg.post("#hack_bar_frame", hash("enable"))
msg.post("#label", hash("enable"))
-- this shows the bar
sound.play("main:/sfx#computer_hack") -- sound of keyboard being abused
go.animate("hack_bar", "scale.x", go.PLAYBACK_ONCE_FORWARD, 1, go.EASING_LINEAR, self.hack_time, 0, function()
	INTER.scripts[self.script]() -- This points towards a script I want to run when a hack is compete
	msg.post("hack_bar", hash("disable"))
	msg.post("#hack_bar_frame", hash("disable"))
	msg.post("#label", hash("disable"))
    -- hide the bar again
end)

Edit: And here’s what it looks like in action:

Hope this helps!

3 Likes