Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AnimationSequence onAnimationComplete terminates the loop without reason. #37

Closed
JonathanReisCom opened this issue Feb 3, 2013 · 10 comments

Comments

@JonathanReisCom
Copy link

See an example of a hero:

package game.characters
{
import citrus.objects.platformer.nape.Hero;
import citrus.view.starlingview.AnimationSequence;

import flash.display.Bitmap;
import flash.events.TimerEvent;
import flash.utils.Timer;

import starling.textures.Texture;
import starling.textures.TextureAtlas;

/**
 * @author Jonathan Reis
 */
public class HeroTest extends Hero {

    [Embed(source="/../assets/chars/Espantalho.xml", mimeType="application/octet-stream")]
    private var _heroConfig:Class;

    [Embed(source="/../assets/chars/Espantalho.png")]
    private var _heroPng:Class;

    private var _attackBoomTimer:Timer;
    private var _isAttacking:Boolean = false;

    public function HeroTest(name:String, params:Object = null) {
        super(name, params);

        var bitmap:Bitmap = new _heroPng();
        var texture:Texture = Texture.fromBitmap(bitmap);
        var xml:XML = XML(new _heroConfig());
        var sTextureAtlas:TextureAtlas = new TextureAtlas(texture, xml);

        view = new AnimationSequence(sTextureAtlas, ["attack", "die", "fall", "walk", "duck", "idle", "jump", "hurt"], "idle");

        x = 183;
        y = 74;

        acceleration = 40;
        jumpHeight = 50;
        maxVelocity = 120;
        dynamicFriction = 10;

        offsetY = 0;

        _attackBoomTimer = new Timer(200, 1);
        _attackBoomTimer.addEventListener(TimerEvent.TIMER, attackBoom);

    }

    private function attack():void
    {
        trace("attack() -> attackBoom() -> attackFinishedAnim()");

        _animation = "attack";
        updateAnimation();

        _controlsEnabled = false;

        if(view is AnimationSequence){
            (view as AnimationSequence).onAnimationComplete.addOnce(attackFinishedAnim);
        }

        _attackBoomTimer.delay = 100;
        _attackBoomTimer.start();
    }

    private function attackBoom(event:TimerEvent):void
    {
        trace("attackBoom() completed.");
        _attackBoomTimer.reset();
    }

    private function attackFinishedAnim(name:String):void
    {
        trace("attackFinishedAnim() completed.");
        _controlsEnabled = true;
        _isAttacking = false;
    }

    override public function update(timeDelta:Number):void {
        if (controlsEnabled)
        {
            if(!_isAttacking){
                _isAttacking = true;
                attack();
            }
        }
        updateAnimation();
    }
}

}

My Output in Console:

[SWF] Main.swf - 3,944,196 bytes after decompression
[Starling] Initialization complete.
[Starling] Display Driver: OpenGL
[SWF] Main.swf/[[DYNAMIC]]/1 - 243,392 bytes after decompression
[SWF] Monstro.swf - 21,891 bytes after decompression
attack() -> attackBoom() -> attackFinishedAnim()
attackBoom() completed.
attackFinishedAnim() completed.
attack() -> attackBoom() -> attackFinishedAnim()
attackBoom() completed.
attackFinishedAnim() completed.
attack() -> attackBoom() -> attackFinishedAnim()
[Unload SWF] Main.swf

In 10 minutes running should run millions of times, but performs only 2 or 3 times and stops.
Please excuse me if it is any error in my code.

@alamboley
Copy link
Member

Hello, your updateAnimation function is called by the update & attack method. It's probably not what you want... ?

@JonathanReisCom
Copy link
Author

Actually, to call or not call the updateAnimation() inside attack() has no importance, I pulled out the call and the effect remains the same.
The fact is that when I call this line:
(view the AnimationSequence). onAnimationComplete.addOnce (attackFinishedAnim);
AttackFinishedAnim function is performed once or twice and then no longer runs.

She should infinite loop every time the animation ends, and it does not.

@alamboley
Copy link
Member

(view the AnimationSequence). onAnimationComplete.addOnce (attackFinishedAnim);

You've used addOnce, so attackFinishedAnim function will perform only one time!

@JonathanReisCom
Copy link
Author

The function attack () is executed when "_isAttacking = false" as shown inside updade ().
So when I run onAnimationComplete.addOnce, I am referring only 1 attack, when I restart the process, the hero will run the second attack, the function is called again, then run again another onAnimationComplete.addOnce

But anyway, I changed the line to
(view the AnimationSequence). onAnimationComplete.add (attackFinishedAnim);
And got the same result.

The result is different in your test?

@alamboley
Copy link
Member

I don't have material to test.

Could you show us the updateAnimation function?

Also I've heard that it may have a bug in Starling 1.3 concerning animation complete: http://forum.starling-framework.org/topic/animation-eventcomplete-fires-early not sure if it was baked into Starling 1.3

Also it seems more related to Starling itself than Citrus Engine. Could you try a simple test running only on Starling and then on the Citrus Engine ? (You may want to duplicate the AnimationSequence class). Thanks!

@alamboley
Copy link
Member

Do you still have the issue?

@JonathanReisCom
Copy link
Author

I no longer have the problem. Decided to go for another logic.

@alamboley
Copy link
Member

Ok, I hope everything is going well.

@alamboley
Copy link
Member

Hey, I think what you're looking for is the StarlingArt.setLoopAnimations(tabAnimations) function ;)

Le 14 mars 2013 à 19:34, dkfast notifications@github.com a écrit :

Hey Aymeric, I know this post is closed, and i apologize for posting back on it, but i didn't know of another way to contact you. I seem to have a similar issue as to the original poster here. I am using a sprite sheet for all my animations for my hero. I have also been loosely following the "Braid" example to help with my custom hero animation frames. I have run into this issue and i just cannot seem to figure out no matter how many examples and posts i read. All my animations are now playing, however they all stop on the final frame and just stay there. for example if i hold down the "left" arrow my character runs left correctly, but when his animation frames end the character continues to move left, but he looks like he is frozen. I'm fairly new to Citrus and so far i love it, i just cant seem to figure out what im doing wrong on this. Thank you in advance for any help you may have.

below is the main part of my custom hero class, if you need to see more please let me know. I'm sure this isnt the best way to do things but again im kind of learning as i go along, reading through all the docs trying to figure it out.

public var canUseSword:Boolean = true;
public var isAttacking:Boolean = false;
public var swordExists:Boolean = false;
protected var _sword:Sword;
protected var _swordJointDef:b2WeldJointDef;
protected var _swordJoint:b2WeldJoint;

public function HeroClass(name:String, params:Object = null)
{
super(name, params);
}

override public function update(timeDelta:Number):void
{

var velocityX:Number = velocity[0];
var velocityY:Number = velocity[1];

if (_onGround && !isAttacking)
{
this.animation = "MainNeutral";
}

if (_ce.input.isDoing("right", inputChannel))
{
if (!isAttacking)
{
if (_onGround)
{
this.animation = "MainRunCycle";
this.velocity = [7,velocityY];
}
if (!_onGround) this.velocity = [5,velocityY];
_inverted = false;
}
}

if (_ce.input.isDoing("left", inputChannel))
{
if (!isAttacking)
{
if (_onGround)
{
this.animation = "MainRunCycle";
this.velocity = [-7,velocityY];
}
if (!_onGround) this.velocity = [-5,velocityY];
_inverted = true;
}
}

if (_ce.input.isDoing("jump", inputChannel) && _onGround)
{
if (!isAttacking)
{
this.animation = "MainJump";
this.velocity = [velocityX,-12];
onJump.dispatch();
}
}

if (canUseSword && _ce.input.isDoing("attack", inputChannel))
{
isAttacking = true;
swordExists = true;
if (_onGround) _animation = "MainBasicAttack";
if (_inverted) {
_sword = new Sword("Sword", {x:x - width, y:y, width:30, height:10});
} else {
_sword = new Sword("Sword", {x:x + width, y:y, width:30, height:10});
}
CitrusEngine.getInstance().state.add(_sword);

_swordJointDef = new b2WeldJointDef();
_swordJointDef.Initialize(_body, _sword.body, _body.GetWorldCenter());

_swordJoint = b2WeldJoint(_box2D.world.CreateJoint(_swordJointDef));    

_box2D.world.DestroyJoint(_swordJoint);
CitrusEngine.getInstance().state.remove(_sword);        

}

if (swordExists && _ce.input.getActionValue("attack") != 1)
{
isAttacking = false;
swordExists = false;
}
}


Reply to this email directly or view it on GitHub.

@dkfast
Copy link

dkfast commented Mar 15, 2013

Yes! that was it, thank you very much Aymeric. I actually figured that out soon after i messaged you, i tried removing my original post as to not bother you with it. But again, thank you for your time, i very much appreciate it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants