Changing the Default Animation property in a GO Sprite from a script (SOLVED)

I have a GO that has a factory component that uses a sprite and I would like to dynamically change the Default Animation property from a script. The script is in the GO that contains the factory component. Currently I have a separate factory component for each sprite and it seems like there would be a better way to change the animation being used but I am new to Defold so I am kind of stuck.

I think you could use the “play_animation” from the sprite component… You would just have to put the id of the image you want to show (assuming that the atlas you’re using contains the image).

I thing that the magic link tutorial uses something like that, you could check it check it out.

Assuming that there a sprite element called sprite and there is an atlas element called foo1, the code would be something like:

msg.post("#sprite", "play_animation", {id = hash("foo1")})
2 Likes

That works great. I put that line of code into the init function of the object that contains the sprite and now each of the instances of the spawned sprite are of sprite “z”. However by changing the id value in the code it will spawn a different sprite each time. The source of my sprites is a tilesource, not an atlas - hopefully that doesn’t make a difference.

Here is the current code from my spawner script. It launches a different factory object for each sprite. I would like to do this with one factory by just changing the id as you showed above:

    local keys = {"#a","#b","#c","#m","#n","#v","#x","#z"}
    local f = keys[math.random(1,8)]
    local id = factory.create(f, pos) 
    go.animate(id, "position", go.PLAYBACK_ONCE_FORWARD, dir, go.EASING_LINEAR, 5) 

I am not clear on how to indicate to the sprite object which image (anim) id to use from this point of the code. I assume I would use a msg.post but am not sure how to reference the receiver in this hierarchy.

You have a two options:

1] Use msg.post() from the same place as where you spawned the game object using the factory. Like this:

local id = factory.create(f, pos)
-- assuming that the sprite component on the spawned game object has id "sprite"
msg.post(msg.url(nil, id, "sprite"), "play_animation", { id = hash("anim_to_play") })

2] Use a go.property() on the spawned game object to indicate which animation to use and send that to the game object when creating it:

-- spawner.script
local id = factory.create(f, pos, nil, { anim_to_play = hash("anim_to_play") })

-- spawned_go.script:
go.property("anim_to_play", hash(""))

function init(self)
    msg.post("#sprite", "play_animation", { id = self.anim_to_play })
end
2 Likes

I tried option 1 and it did not change the animation selection. The following error was shown in the console:

ERROR:GAMEOBJECT: Component '/instance2##sprite' could not be found when dispatching message 'play_animation' sent from main:/launcher#script

Here is the launcher function:

local keys = {"#a","#b","#c","#m","#n","#v","#x","#z"}

function launchletter()
     local dir = vmath.vector3(math.random(pos.x - halfwidth, pos.x + halfwidth)>,pos.y - 1200,0)
     local f = ">#factory-a"
     local id = factory.create(f, pos) 
     msg.post(msg.url(nil, id, "#sprite"), "play_animation", { id = hash(keys[math.random(1,8)]) })
     go.animate(id, "position", go.PLAYBACK_ONCE_FORWARD, dir, go.EASING_LINEAR, 5) 
 end

Here is how the GOs are constructed:

The launcher.go

I am only using the first factory object. My goal is to get rid of the others.

Here is the letter.go

Hopefully that makes my situation more clear. Thanks for your help.

There’s an extra “#” in the url, which you can blame Britzl for. :stuck_out_tongue: It should be:

msg.url(nil, id, "sprite")

(no hash mark in front of the component)

[Edit] I’m not sure if you changed things by mistake while posting here, but there are other typos in your function code. Two “>” symbols crept in there. Near the end of the first line of the function, “halfwidth)>,pos.y - 1200,0)” and the second line, "local f = “>#factory-a”.

1 Like

No, the > chars were paste errors and are not in the original code.

I thought the extra # might be incorrect and tried it without it but I get the following error:

ERROR:GAMESYS: Unable to play animation ‘#x’ since it could not be found.

Well that seems like a pretty clear error message. You need an image or animation in the atlas (or tilesource) that your sprite is using, named “#x”. Or you need to adjust those keys to match the actual animation names.

And I just tested, you’ll also get that error if you’re trying to use an animation group that has no images in it.

1 Like

Yup, that was it. I forgot to remove the # prefix for each anim identifier in the table. Rookie mistake, but I’m getting there. Thanks to everyone for your help.

Yep, sorry about that. Fixed in my post now. Thanks for pointing it out.