muffunny написавWhat I am trying to do is fairly simple. A top animation of a blinking eye in a loop mode, and a button animation in not loop mode of a kid picking up something.
Take a look at this:
viewtopic.php?f=7&t=2594&p=12691&hilit=addAnimation#p12691
The post uses the same idea you had about using an event to generate a random blink. I would say to do this on track 1 and your kid picking something up on track 0 (or vice versa). That would be a cool way to do it in order to randomize the blinking time. (although a Fourier Series might be a little overboard).
muffunny написавIn the top animation (eyes blinking) I toggle on and off the eyes closed image) and the rest off the images I set it off. But I have to do unclick the image itself, if I do unclick the slot, then all the images disappear also on the lower animations. This way it also creates a bunch of keyframes on frame one "Attach:Head ->off. Is this the right way to do it?
I have no idea about the editor stuff. I'm literally just on the programming end. What I did was opened up the globin example and created a duplicate of the "walk" animation and named it "blink". Then I deleted all the keyframes for everything except the blinking on the head (just the keyframes, not the bones) and exported the JSON. It exported two animations, one of which only toggles the blinking eyes attachment.
If you generate a keyframe for "Turn all other images off" then that will be applied to the animation. You want the "blink" animation to only generate frames for the eyes and nothing else.
muffunny написавSo in order to connect part one and two, do I need to set en event at the end of part1 (the one that doesn't loop) and then part 2 the once that will be looping, so when the animation 1 is finished the 2 can start, or can it be set up in cocos2dx without the need for en event?.
Personally, I have a wrapper controller class for the animation/skeleton. That wrapper allows me to chain animations using the setAnimation and addAnimation functions:
std::vector<SceneChain>::iterator itr = mSceneChains[aSequenceID].begin(), end = mSceneChains[aSequenceID].end();
if(itr != end) // set the first animation
{
spAnimationState_setAnimationByName(pAnimationState, track, itr->mSceneName.c_str(), itr->bLoop);
++itr;
mCurrentSequence = aSequenceID; //
}
for (; itr != end; ++itr) // add the rest into the animation queue
{
spAnimationState_addAnimationByName(pAnimationState, track, itr->mSceneName.c_str(), itr->bLoop, itr->mDelay);
}
Looking through my code and stuff, it looks like 'mDelay' is space between animations and not an absolute time.
A sample XML for a chain is :
<Chain name="chain1">
<Scene name="walk" loop="true" delay="0.0f" />
<Scene name="jump" loop="false" delay="0" />
<Scene name="run" loop="true" delay="0" />
<Scene name="jump" loop="false" delay="3" />
<Scene name="walk" loop="true" delay="0" />
<Scene name="idle" loop="true" delay="1" />
</Chain>
You're probably going to want to look into mixing/blending parameters to blend animations together. My XML looks something like:
<DefaultBlend duration="0.2f" /> <!
---
Default must be first
---
<Blend from="jump" to="walk" duration="0.4" />
<Blend from="jump" to="run" duration="0.4" />
Setting the default blend between animations looks something like:
if(pSpineData->skeletonData && pSpineData->animationData){
int aCount = pSpineData->skeletonData->animationsCount;
std::vector<spAnimation*> anims;
for(int i = 0; i < aCount; ++i){
anims.push_back(pSpineData->skeletonData->animations[i]);
}
for (int i = 0; i < aCount; ++i)
{
spAnimation* from = anims[i];
for (int j = 0; j < aCount; ++j)
{
if(j != i)
spAnimationStateData_setMix(pSpineData->animationData, from, anims[j], duration);
}
}
}
While individual blending is done with:
if(pSpineData->animationData != NULL)
{
std::string to;
std::string from;
float duration = 0.0f; // in seconds
pugi::xml_attribute_iterator a_itr = theNode.attributes_begin(), a_end = theNode.attributes_end();
for (; a_itr != a_end; ++a_itr)
{
if (CompareNoCase(a_itr->name(), _STR("to")) == 0)
to = SexyStringToString(a_itr->value());
else if (CompareNoCase(a_itr->name(), _STR("from")) == 0)
from = SexyStringToString(a_itr->value());
else if (CompareNoCase(a_itr->name(), _STR("duration")) == 0)
duration = a_itr->as_float();
}
if(!to.empty() && !from.empty())
spAnimationStateData_setMixByName(pSpineData->animationData, from.c_str(), to.c_str(), duration);
}