Jump to content

Make movieclip from several atlases and play it whithout lags


PainKKKiller
 Share

Recommended Posts

In my project I have some animations which made from too many frames, and on machines with weak videocards I am getting error with MAX_TEXTURE_SIZE and animation shows as black rectangle. To avoid that I divided spritesheet with animation into smaller ones, and make movieclip from them. Code looks like this:

this.loader = new PIXI.loaders.Loader();

this.loader  //  load spritesheets with anime
            .add("b_b_0", 'res/anime/b_b_0.json')
            .add("b_b_1", 'res/anime/b_b_1.json')

...

AssetsManager.prototype.getFrames = function(resName) {
    var json = this.getJSON(resName);
    var frames = [];
    var framesKeys = Object.keys(json.frames).sort(naturalSort);
    var textures;
    if(this.commonLoader.resources[resName])
        textures = this.commonLoader.resources[resName].textures
    else if(this.ringLoader.resources[resName])    
        textures = this.ringLoader.resources[resName].textures;
    else throw new Error("There is no textures with name " + resName);
    
    for(var i = 0; i < framesKeys.length; i++) {
        frames.push(textures[framesKeys[i]]);
    }
    return frames;
}

//MAX_TEXTURE_SIZE problem WebGL
AssetsManager.prototype.getBigMovieClip = function(resName, length) {
    var frames = [];
    for (var i = 0; i < length; i++) {
         frames = frames.concat(this.getFrames(resName + "_" + i));
    }

    var movie = new PIXI.extras.AnimatedSprite(frames);
    return movie;  
}

and the I use getBigMovieClip("b_b", 2) to get MovieClip made from 2 spritesheets. Everything ok, but I see small lag while movieclip playing and I have no idea how to overcome it. Thanks for any suggestions in advance. 

Link to comment
Share on other sites

  • 2 weeks later...

 

Don't know how to use it properly, just found this post, tried to use it in several ways. one of attempts looks like this:

renderer = PIXI.autoDetectRenderer(consts.resolutions[consts.RESOLUTION].width, consts.resolutions[consts.RESOLUTION].height, 
                                        { view: document.getElementById("game-canvas") });

...

AssetsManager.prototype.getBigMovieClip = function(resName, length) {
    var frames = [];
    for (var i = 0; i < length; i++) {
        var fr = this.getFrames(resName + "_" + i);
        renderer.plugins.prepare.upload(fr);
        frames = frames.concat(this.getFrames(resName + "_" + i));
    }

    
    var movie = new PIXI.extras.AnimatedSprite(frames);
    return movie;  
}

But anyway I still have a lag in the middle of movieclip.

Link to comment
Share on other sites

ServerCharlie thanks for reply, tried in this way: 

AssetsManager.prototype.getBigMovieClip = function(resName, length) {
    var frames = [];
    for (var i = 0; i < length; i++) {
        var fr = this.getFrames(resName + "_" + i);
        renderer.plugins.prepare.upload(fr);
        frames = frames.concat(fr);
    }
    var fr_set = [];
    for (var j = 0; j < frames.length; j++) {
        var frame = {
            texture: frames[j],
            time: 50
        };
        fr_set.push(frame);
    }
    
    var movie = new PIXI.extras.AnimatedSprite(fr_set);
    return movie;  
}

Animation has got much slower, but lag still exists.

Link to comment
Share on other sites

  • 1 month later...

So I smoothed out my movie clip animation with the following.

The prepare plugin was the right solution but never worked. WebGL needs the entire texture(s) uploaded not the frames. The way textures are uploaded to the GPU is via renderer.bindTexture(texture). When the PIXI loader receives a sprite atlas url e.g. my_sprites.json it automatically downloads the image file and names it as mysprites.json_image in the loaders resources. So you need to grab that, make a texture and upload it to the GPU. 

let loader = new PIXI.loaders.Loader()
loader.add('http://mysite.fake/sprite1.json')
loader.add('http://mysite.fake/sprite2.json')
loader.add('http://mysite.fake/sprite3.json')
loader.once('complete', callback)
loader.load()


function uploadToGPU(resourceName){
  resourceName = resourceName + '_image'
  let texture = new PIXI.Texture.fromImage(resourceName)
  this.renderer.bindTexture(texture)
}

loadSpriteSheet(function(resource){
  uploadToGPU('http://mysite.fake/sprite1.json')
  uploadToGPU('http://mysite.fake/sprite2.json')
  uploadToGPU('http://mysite.fake/sprite3.json')

  // helper function to get all the frames from multiple textures
  let frameArray = getFrameFromResource(resource)
  let animSprite = new PIXI.extras.AnimatedSprite(frameArray)
  this.stage.addChild(animSprite)
  animSprite.play()  
})
Link to comment
Share on other sites

Quick explanation about attached demo.

Sorry for little mess, I tried to include only necessary files. 

Demo made in big (1920x1080 resolution) to show effect.

I do my project with browserify, so if you want to compile it from source (in src folder) you have to install it. Otherwise you can use app.bundle.js file, it not minified,  just check index.html to use it.

When click button PLAY movieclip plays, and in first time I clearly see lag when stone falls on back, after that movieclip plays without lag.

The module where movieclips are making is src/AssetsManager.js where getBigMovieClip function is located, where I tried to use prepare plugin. Then I play it in app.js with settimeout function just to check that all uploaded.

 

Thanks in advance.

bigdemo.zip

Link to comment
Share on other sites

Adding this to your code worked for me. As has been pointed out this is not the proper solution. But it works.

AssetsManager.prototype.preloadCommon = function(callBack) {

        preloader.show();

        this.commonLoader

            ...

            //Added this on complete handler
            .on("complete",function(loader, resource){
                console.log(resource)
                renderer.bindTexture(new PIXI.Texture.fromImage("b_k_0_image"))
                renderer.bindTexture(new PIXI.Texture.fromImage("b_k_1_image"))
            })

            ...

            .load(function() {
                callBack();
                preloader.remove();
            });

 

Link to comment
Share on other sites

From slack:

Quote

andrewstart [5:03 PM] 
looking at that, I am assuming that no one is actually passing a callback to `renderer.plugins.prepare.upload()`, so they are telling it to get prepared, then immediately trying to use it

I dont see in your demo the place when you actually wait for prepare.

 

Link to comment
Share on other sites

I have done some further research and I have found at least one of the possible issues. PIXI.extras.AnimatedSprite extends PIXI.Sprite, which assumes the concept that it has one BaseTexture. Creating an AnimatedSprite from frames from multiple sources still results in an AnimatedSprite with one BaseTexture, it appears to choose the last frames texture as the BaseTexture. Then when you run the prepare plugin it uses a function called `findBaseTextures` which uploads the baseTexture of an item to the GPU. In the case of an AnimatedSprite it uploads only the one texture, meaning one is the GPU and the others are not and when you play you AnimatedSprite it has to load any other things into the GPU at that time. Hence the laggy playback. I might place all this info in the PIXI issue tracker, see If I can get some help.

Link to comment
Share on other sites

I am pretty sure my jsfiddle is correct

app.renderer.plugins.prepare.upload(sprite,function(){
  console.log('uploaded animated sprite')
  enableButton()
})
    
...

function enableButton(){
  var button = document.getElementById('button')
  button.disabled = false
  button.innerHTML = 'Ready, play animation'
  button.addEventListener('click',function(){
    if(!app || !app.stage) return
    console.log('click')
    app.stage.addChild(sprite)
    sprite.gotoAndPlay(0)   
  })
}

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...