GMS 2 (solved) Spine attacking is in track 1 how to code animation end (video)

maranpis

Member
Hello guys:

As you can see in the video if the enemy changes the state from attacking to chasing the attack animation doesn't finish and is been switched inmediately by the running animation.


This happens because the attack animation has two tracks: track 0 (running animation) and track 1 (attacking animation) when I use the animation ends event it refers to running animation. So I don't know how to code " when the attacking animation has finished and the enemy is in the green circle(chase state) then you can switch the animation to running"




STEP EVENT:
switch (Estate) {

case "enemy_idle" :
#region IDLE STATE

////**************** SETTING VARIABLES********************************////

var EPdist= point_distance(x,y,o_player.x,o_player.y);

////**************** CONDITIONS IN ORDER TO CHANGE TO OTHER STATES********************////

if (EPdist>view_range){ (green circle in the video)

if ( skeleton_animation_get() !=EAidle) { // set animation to idle
image_speed= 1; // normal speed
skeleton_animation_set(EAidle);
}


} else if ( EPdist <= view_range and EPdist >attack_range) { // set to chase

Estate_text= "CHASE";
Estate= "enemy_chase";


if ( skeleton_animation_get() !=EArun) { // chase animation
image_speed=5;
skeleton_animation_clear(1);
skeleton_animation_set(EArun);
}


}
break;
#endregion



case "enemy_chase" :
#region ENEMY CHASE

EB_idle=false // states for animation
EB_chase=true;
EB_attack=false;
var EPdist= point_distance(x,y,o_player.x,o_player.y);

Estate_text= "CHASE"; // change the state text to chase

if (EPdist >attack_range and EPdist<= view_range) {// move and chase
// movement
x+= ehs*sign(o_player.x-x);
// add horizontal speed to and multiply by 1 or -1 depending the players position
skeleton_animation_clear(1);
// skeleton animation clear works here

} else if ( EPdist<= attack_range) {// from chase to attack


Estate= "enemy_attack";
image_speed=5;
skeleton_animation_set_ext(EAattack,1); // mix two animations with tracks
skeleton_animation_set(EArun);
if (skeleton_animation_get()==EArun){

}
} else { // go back to idle

skeleton_animation_clear(1);
Estate= "enemy_idle";

}


// Scale enemy change
if ( sign(o_player.x -x) ==-1 ) {

image_xscale=1;

} else { image_xscale=-1}





break;
#endregion

case "enemy_attack" :
#region ENEMY ATTACK


var EPdist= point_distance(x,y,o_player.x,o_player.y);
Estate_text="ATTACK" // change state text
CONDITIONS****************************************///
if (EPdist>attack_range and EPdist <= view_range) {// from attack to chase


Estate="enemy_chase";

if ( skeleton_animation_get() !=EArun) { //change to run
image_speed=8;
skeleton_animation_set(EArun);
}

}


}








break;
#endregion
}


ANIMATION END EVENT:

Code:
if (skeleton_animation_get()== EArun) {
    
    image_speed=4;
    skeleton_animation_set(EAupsw);
    
    
}
// This code works for changing between when the enemy lift the sword the sword to when the enemy keep running with the sword.

I have read the documentation and i know there is this code: skeleton_animation_get_duration(animname);

But I don't understand the examples given:

Example1:
time += delta_time / 1000000;
var duration = skeleton_animation_get_duration(skeleton_animation_get());
var frame = floor((image_number * (mTime / duration)) + 0.5) % image_number;
image_index = frame;
draw_self();

The above code will set the image_index to the correct value for the currently assigned skeletal animation sprite.

Example2:
time += delta_time / 1000000;
var d = skeleton_animation_get_duration("walk");
if time > d time -= d;
draw_skeleton_time(sprite_index, "walk", "skin1", time, x, y, image_xscale, image_yscale, image_angle, c_white);

The above code will draw the given skeletal animation sprite using delta-time to set the frame being drawn.

Any idea of how to get the track 1 duration?

thanks guys!
 

maranpis

Member
Hello guys:

I have found a solution:

The best solution is to use the track 0 for things that needs to be checked and the track 1 for animations that can be consider secondaries.

If you code something in the animation end event you will be able to check if the attack has finished.

cheers! ;)
 

rIKmAN

Member
Hello guys:

I have found a solution:

The best solution is to use the track 0 for things that needs to be checked and the track 1 for animations that can be consider secondaries.

If you code something in the animation end event you will be able to check if the attack has finished.

cheers! ;)
You're welcome! ;) :p

However it doesn't really matter which track you use as like we discussed via PM, each track will fire an Animation End Event when it's animation ends.

You can then check in here which animation is currently assigned (and has just ended) on a given track using skeleton_animation_get_ext(), and set the track to a new animation - making sure that you use skeleton_animation_set_ext() to set it for the individual track that fired the Animation End event rather than the entire skeleton using skeleton_animation_set().
 

maranpis

Member
You're welcome! ;) :p

However it doesn't really matter which track you use as like we discussed via PM, each track will fire an Animation End Event when it's animation ends.

You can then check in here which animation is currently assigned (and has just ended) on a given track using skeleton_animation_get_ext(), and set the track to a new animation - making sure that you use skeleton_animation_set_ext() to set it for the individual track that fired the Animation End event rather than the entire skeleton using skeleton_animation_set().
I think you mean to write down this code in the animation end event right?
Code:
if (skeleton_animation_get_ext(1)=EAattack){
    
show_message("hit");
}
EAattack= Attack animation
EArun=Run animation

I don't know why but if I change the animations between track 0 (legs) or track 1(torso) the message appears but in random moments but now if i put track0 (attack) and track 1 (legs) the message shows when the attack finishs(in a right way). (you can see both videos)
Working successfully

Not working

 

rIKmAN

Member
I think you mean to write down this code in the animation end event right?
Code:
if (skeleton_animation_get_ext(1)=EAattack){
 
show_message("hit");
}
Yeah that's pretty much it - check what animation is playing on a track and fire off a message to show you which track and animation it was that triggered the Animation End event.

I haven't tested it myself I'm just going off what you said in our PMs when I asked you to test if each track did fire it's own Animation End event.
You replied and said that each track does fire an Animation End event when the animation on that track ends.

If that is definitely the case then it should be pretty easy to manage different tracks animations using skeleton_animation_set_ext() and skeleton_animation_set_ext() so that your different body parts can all work together and play out their animations without overwriting one another like you were with your sword slash animation not finishing it's full swing.

Without testing it myself and going off what you have said re: each track firing it's own Animation End event, I would say it is more likely an error in your code and/or logic that is causing the issues.
 

jo-thijs

Member
You're welcome! ;) :p

However it doesn't really matter which track you use as like we discussed via PM, each track will fire an Animation End Event when it's animation ends.

You can then check in here which animation is currently assigned (and has just ended) on a given track using skeleton_animation_get_ext(), and set the track to a new animation - making sure that you use skeleton_animation_set_ext() to set it for the individual track that fired the Animation End event rather than the entire skeleton using skeleton_animation_set().
Yeah that's pretty much it - check what animation is playing on a track and fire off a message to show you which track and animation it was that triggered the Animation End event.

I haven't tested it myself I'm just going off what you said in our PMs when I asked you to test if each track did fire it's own Animation End event.
You replied and said that each track does fire an Animation End event when the animation on that track ends.

If that is definitely the case then it should be pretty easy to manage different tracks animations using skeleton_animation_set_ext() and skeleton_animation_set_ext() so that your different body parts can all work together and play out their animations without overwriting one another like you were with your sword slash animation not finishing it's full swing.

Without testing it myself and going off what you have said re: each track firing it's own Animation End event, I would say it is more likely an error in your code and/or logic that is causing the issues.
I just tested this in GM:S 1.4 and it's not the case.
The animation end event only triggers for track 0 for me.

EDIT: The manual says the "animation event" event should work for each track though.
 

rIKmAN

Member
I just tested this in GM:S 1.4 and it's not the case.
The animation end event only triggers for track 0 for me.

EDIT: The manual says the "animation event" event should work for each track though.
EDIT:
The Animation Event is for reading events that you setup inside Spine, where you set event keyframes and can pass data in along with the animation.
For example you could set event keyframes in Spine which would sync with a players feet hitting the ground in the animation, and then when that event was fired / read within GMS you could play a footstep sound.

It has no use in setting / getting bones data - the track data it provides in the event_data map would just be to read which track playing the animation had fired the event.

In the other thread you said Animation Event isn't working for you as expected in 1.4 though - what's the issue?
Answer in either thread, no need to have the same convo in both. :)
 
Top