[SOLVED] Playing a sprite sheet once

I was curious if you guys had a way to stop the infinite loop with your current project. Basically having it only play once, just like you do with your particles and 3d animation.

https://developer.playcanvas.com/en/tutorials/animated-textures/

This is the project I’m learning from. I tried to put some constraints on when the animations can play. I got it to do a simple start and finish. But What I’d like to have is a complete restart of the animation and end the loop once it reaches the last frame. I admit I didn’t spend more than 30 minutes on this, but I figured you guys could just give me a simple answer and save me some time lol

-AJ

A solution, but seems clunky.

I was trying to count when the animation would cycle through and once it has to STOP the animation. This is what I wrote, but I feel it can be more efficient.

Here is a screen shot.

I came up with a more precise solution; the only issue is that if I change the Frame Rate on one entity, it seems to affect all of them. I want them to be independent of each other so that I can control each’s loop animation.

Here is the code

var closeGate = true;
var roundAbout = 0;
// initialize code called once per entity
AnimatedTexture.prototype.initialize = function() {
    if (this.materialAsset) {
        this.material = this.materialAsset.resource;
    }

    this.timer = 1/this.frameRate;
    this.frame = this.startFrame;
    this.transform = new pc.Vec4();

    this.updateMaterial(this.frame);
};

// update code called every frame
AnimatedTexture.prototype.update = function(dt) {
    console.log(roundAbout);
    console.log(this.frame);
    //My code to freeze the frame!
    if(this.frame === this.numFrames - 1) {   
        roundAbout++;   
    }
    
    if(roundAbout >= this.frameRate/2){  
        closeGate = false;
        roundAbout = 0;
    } 
    
    if(this.app.keyboard.wasPressed(pc.KEY_P) && !closeGate){
        this.frame = 0;
        roundAbout = 0;
        closeGate = true;
    }
    //added a condition where it will listen to whether we keep the timer counting. 
    //This way I can stop it when I want too. 
    //The issue is I feel it could be simplier. 
    if(closeGate){
        this.timer -= dt;  
    }
if(roundAbout >= this.frameRate/2)

// can actually just be

if(roundAbout >= 1) 

I believe somewhere in that code I can make it loop numerically. But this is the solution I needed!

Please chime in on your thoughts also I plan to do a mock up of something you guys should do for Sprite animations as part of your UI

This would be a huge boost for your platform since it will save time on the implementation of 2d animations!

It should be just as easy as your 3d model+ 3d animation UI. Which IMO is leaps and bounds better than most I’ve seen, and I see no reason why the 2d can’t be just as good. This could really compete against a lot of other game engines who primarily focus on 2d. Like construct 2.

Anyways I would like to know your thoughts, and I’ll put together something for you guys to chew on :slight_smile:

The framerate should already be on a per entity basis already as shown in the sample project with the two coins spinning.

As for not looping, the script knows what frame it is currently on and also knows how many frames there are in total. So knowing that, you know when the animation has finished and to not reset the current frame back to 0.

OH I see what the problem is, it’s my variables. They are shared in each instance, so it’s screwing with them. I’ll sort this out. Thanks!

Guys try this code to run frame by frame animations on UI Image

var AnimateSprite = pc.createScript('animateSprite');

AnimateSprite.attributes.add('startFrame', {
    type: 'number',
    default: 0,
    description: 'Frame to start animation from'
});

AnimateSprite.attributes.add('numFrames', {
    type: 'number',
    default: 1,
    description: 'Number of frames to play before looping'
});

AnimateSprite.attributes.add('wantLoop',{type:'boolean',default : true , description : 'do you want animation to loop'});
AnimateSprite.attributes.add('animationExecutionTime', {type:'number', description:'Set number of seconds you want to set for aniamtion'});

AnimateSprite.prototype.asyncImageLoader = async function()
{ 
    let wait = (this.animationExecutionTime / this.numFrames)*1000;
    while(true)
    {
        for(let i = this.startFrame; i <= this.numFrames; i++)
        {
            this.entity.element.spriteFrame = i; 
            await sleep(wait);   
        }
        if(this.wantLoop == false)
        {
            break;
        }
    }
};

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// initialize code called once per entity
AnimateSprite.prototype.initialize = async function() {
    console.log('started init');
    await this.asyncImageLoader();
};
1 Like