Game Development Community

FxAnimatedSprite2D::onAnimationEnd()

by Matthew Langley · in Torque Game Builder · 04/21/2005 (12:54 pm) · 9 replies

Not sure if this is a bug yet, so posting it here

before the recent release the onAnimationEnd callback got called continuosly after it ended... now it doesn't do that anymore; however, in creating an animation queueing system it doesn't seem to do chain callbacks... it will only call the callback once, even if in the callback you have it play another animation, the callback wont get called then

heres what I tested it with (the same example I have in the Unofficial F.A.Q.)... I dumbed it down to a simple example (vs the queueing system)

$circleGuy = new fxAnimatedSprite2D() { scenegraph = t2dSceneGraph; };
        
        $circleGuy.setPosition("-35 0");
        $circleGuy.setSize( "10 7" );
        $circleGuy.playAnimation(circleGuyStandLeft);
	
$circleGuy.direc = "left";

function fxAnimatedSprite2D::onAnimationEnd(%this)
{
	echo("---onAnimationEnd---");
	if(%this.direc $= "right")
	{	
		$circleGuy.playAnimation(CircleGuyStandLeft);
		%this.direc = "left";
	} else
	{
		$circleGuy.playAnimation(CircleGuyStandRight);
		%this.direc = "right";
	}
}

maybe someone else can test this with their own example to see if its just me :)


In my console I only get one

---onAnimationEnd---

and it switches once

though even if the switching weren't working it should trigger the callback still

About the author

Was a GG Associate and then joined GG in 2005. Lead tool dev for T2D and T3D. In 2011 joined mobile company ngmoco/DeNA and spent about 4 years working game and server tech. 2014 joined startup Merigo Games developing server technology.


#1
04/21/2005 (1:41 pm)
I can confirm that this happens to me with a slightly different example:

datablocks.cs
//The famous circleGuy!
datablock fxImageMapDatablock2D(circleGuy)
    {
       mode = cell;
       cellWidth = 64;
       cellHeight = 64;   
       textureName = "~/client/images/circleGuy";
    };

datablock fxAnimationDatablock2D(test1)
    {
       imageMap = circleGuy;
            animationFrames = "1";
            animationTime = 2.25;
            animationCycle = 0;
            randomStart = 0;
    }; 
datablock fxAnimationDatablock2D(test2)
    {
       imageMap = circleGuy;
            animationFrames = "2";
            animationTime = 2.25;
            animationCycle = 0;
            randomStart = 0;
    };

clients.cs
function StartAnim()
{
    $testGuy = new fxAnimatedSprite2D() { scenegraph = t2dSceneGraph; };
    $testGuy.setPosition("-25 0");
    $testGuy.setSize( "7 10" );
    $testGuy.playAnimation(test1);
    $frame = 1;
}

function fxAnimatedSprite2D::onAnimationEnd(%self)
{
	echo("An animation has ended, starting a new one"); //Only happens once
	
	$testGuy.playAnimation(test2);
}
#2
04/21/2005 (2:04 pm)
Try replacing your animation calls with the following:

%this.schedule(0,"PlayAnimation","CircleGuyStandLeft");
#3
04/22/2005 (5:42 am)
Oops, my bad!

I haven't tried this yet because I'm at work but I think the following fix will solve it. Again, I've not tested this yet but I will do so this weekend.

Change your "fxAnimatedSprite2D::integrateObject" to the following...

//-----------------------------------------------------------------------------
// Integrate Object.
//-----------------------------------------------------------------------------
void fxAnimatedSprite2D::integrateObject( F32 sceneTime, F32 elapsedTime, CDebugStats* pDebugStats )
{
	// Has the Animation Finished?
	if ( mAnimationController.isAnimationFinished() )
	{
		// Yes, so is the animation callback complete?
		if ( !mAnimationCallbackComplete )
		{
			// No, so set Animation Callback Complete.
			mAnimationCallbackComplete = true;

			// Do script callback.
			Con::executef( this, 1, "onAnimationEnd" );
		}
	}
	else
	{
		// No, so update Animation.
		mAnimationController.updateAnimation( elapsedTime );
	}

	// Call Parent.
	Parent::integrateObject( sceneTime, elapsedTime, pDebugStats );
}

I incorrectly placed the flagging after the callback rather than before it.

Bugs in bug-fixes! Sorry everyone.

- Melv.
#4
05/29/2005 (3:37 pm)
Ah, maybe this explains the problem I'm having. I have an animated sprite mounted to the player. This sprite starts off as invisible, and is setVisible(1) when the player collides with something.

I then call onAnimationEnd to hide the sprite again. Unfortunately it doesn't hide, and I can't even use .setVisible(0) from the console to hide. It flicks off briefly and then appears again.

There are no suprious collisions going on, and I've just stuck the relevant bits of code into a blank example to make sure it's nothing else I'm doing that's causing the problem.

I can post my code it it helps, but it kind of sounds like the same problem. I'll try the schedule solution and see if it's a suitable work around.
#5
06/04/2005 (4:35 am)
Melv,

As discussed in another thread, here's the code from a blank T2D project. Just chuck all of this into the T2D\client\client.cs and hopefully you'll see the same problem.
function setupT2DScene()
{
	// Create fxSceneGraph2D.
	new fxSceneGraph2D(t2dSceneGraph);
	
	// Associate Scenegraph with Window.
	sceneWindow2D.setSceneGraph( t2dSceneGraph );
	
	// Set Camera Position to be centered on (0,0) with
	// view width/height of (100/80).
	sceneWindow2D.setCurrentCameraPosition( "0 0 100 75" );

	$playership = new fxStaticSprite2D() { scenegraph = t2dSceneGraph; };
	$playership.setPosition("-40 0");
	$playership.setSize( "12 12" );
	$playership.setImageMap( shipImageMap );

	$playership.setGroup(1);
	$playership.setLayer(15);
	$playership.setCollisionPolyCustom(6, "0.8281 0.1172 0.6172 0.0234 0.3828 0.0234 0.2578 0.0859 0.3906 0.1641 0.7500 

0.1563");
	$playership.setCollisionActive( true, false );
	$playership.setCollisionMasks( BIT(2), BIT(16) );
	$playership.setCollisionCallback( true );
	$playership.tag = "playership";

	$playerShield = new fxAnimatedSprite2D() { scenegraph = t2dSceneGraph; };
	$playerShield.setSize("12 8");
	$playerShield.tag = "playershield";
	$playerShield.mount ( $playership, "0 0.16", 0, false);
	$playerShield.setVisible(0);

	%nmefighter = new fxStaticSprite2D() { scenegraph = t2dSceneGraph; };
	%nmefighter.setImageMap("ggLogoImageMap");
	%nmefighter.tag = "enemy";
	
	%nmefighter.setSize( "6 6" );
	%nmefighter.setFlip(true, false);
	%nmefighter.setGroup( 2 );
	%nmefighter.setLayer( 16 );
	%nmefighter.setWorldLimit( kill, "-80 -80 80 80" );
	%nmefighter.setCollisionActive( true, true );
	%nmefighter.setCollisionMasks( BIT(1), BIT(15) );
	%nmefighter.setCollisionCallback( true );
	%nmefighter.setCollisionScale( "1 0.5" );
	%nmefighter.setLinearVelocityX(-20);
	%nmefighter.setPosition("0 0");
}

function updateShield()
{
	$playerShield.setVisible(1);
	$playerShield.playAnimation(lightningAnimation);
}

function fxSceneObject2D::onCollision( %srcObj, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contacts )
{
	if (%dstObj.tag $= "playership")
	{
		$playership.setCollisionSuppress(true);

		$playership.shield -= %srcObj.damageRating;
		updateShield();
	}
}

function fxAnimatedSprite2D::onAnimationEnd(%this)
{
echo("Animation Ended for object with tag:" SPC %this.tag);
	if(%this.tag $= "playershield")
	{
		echo("hiding");
		%this.setVisible(0);
		echo("should be hidden");
	}
}

It looks OK to me, but I may have missed something.
#6
06/04/2005 (4:42 am)
I'll check this out now...

- Melv.
#7
06/04/2005 (4:55 am)
Philip,

I think I know what you're seeing here. There was a problem reported (that has now been fixed) where the t2dAnimatedSprite (fxAnimatedSprite2D) kicks-out an initial "onAnimationEnd()" when it is created. This is easily fixed by changing the following default in the t2dAnimatedSprite constructor 't2dAnimatedSprite::t2dAnimatedSprite()' to "mAnimationCallbackComplete(true)" (instead of false).

In the example above, the "hiding" and "should be hidden" is output when the t2dAnimatedSprite is created, not when the animation ends. The reason you don't get an animation end callback is because you're using a looping animation "lightningAnimation" which never ends.

Hopefully, this explains what's going on here. :)

- Melv.
#8
06/04/2005 (5:13 am)
Ah yes, forgot to mention that, I edited the lightning animation datablock so that it doesn't loop. And in my real code, the animation is non-looping.
#9
06/04/2005 (5:26 am)
Cool.

So if you change the default of "mAnimationCallbackComplete(true)", it should hopefully work for you now.

- Melv.