question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItΒ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

PIXI AnimatedSprite don't have correct width and height Frames???

See original GitHub issue

Hello guy. have you an idea why I have a strange value on all my containers?

I’m working on an animation debugger plugin To easily exploit spriteAnimations in rmmv with texturePacker. # video: Alt text

here example of the spritesheet for demo and full template ressources pack its free, so here links The template will allow you to study if you start in animations and spritesheets(RIG) and understand how easy texturePacker make powerfull JSON animation sheets. spriteSheetsAni.zip bobspritesheet1

Logically I expected to be able to get the real value of frames, but I can not get. Is it possible by a calculation with a formula or a method of going to seek the real value of the frames (croped). Then adjust the parent container accordingly.

The problem is currently rather serious because if I want to add a pivot to left or bottom. It will be rather difficult to calculate it position from the parent container.

I may have misinterpreted the codes. Do you have suggestions for advice? thanks for help

Here for the moment, where i am in the dev of plugin free m.i.t

/*:
// PLUGIN ░────────────────────────────────░PIXI SPRITESHEETS ANIMATIONS FOR RMMV░─────────────────────────────────────────┐
 * @author β–‘ dimisterjon (jonforum) β–‘  Gamefall Team β–‘ 
 * @plugindesc Manager PIXI SpriteSheetAnimation && TexturePacker in RMMV
 * V.0.3
 * License: M.I.T
// β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
 * 
 * @help
 * Copy past this in console for test
var newAni = $gameScreen.createAnimation(1,'Bob',350,300); 
    newAni.addMotionContext_Linear('idl1','idl2',39,35); 
    newAni.addMotionContext_Linear('idl2','idl1',39,100);
    newAni.addMotionContext_Winks('idl1','winks1',0,80)
    newAni.addMotionContext_Winks('idl1','winks2',10,40);
    newAni.addMotionContext_Winks('idl1','winks3',20,40);
    newAni.addMotionContext_Winks('idl1','winks4',30,60);
    newAni.addMotionContext_Linear('att1','idl1',39,100);
    newAni.playMotion('idl1');
    newAni.debug();

    newAni.bindMotionsTo(200,200);
 * 
 */

_pixiSSA = function(){
    this.createLabel();
    this.setDefaultSpeed();
    this.importAniObj();
    this.checkJSON_Integrity(this.aniObj);
    this.load_aniOBJ(this.aniObj);
};
//aniOBJECT SETUP ░──────────────────────────────────────────────────────────────────────────────────────────────────────┐
//Register HERE ALL OBJ IN GAME you will need: name: ani: {ref:'', framesRange:[], loop:bool,  }
_pixiSSA.prototype.importAniObj = function() {
    this.aniObj = {
        Bob:{ // demo example 'Bob'
            json:['spriteSheetsAni/sheets/multiPack/bobSpriteSheet1'], // auto name format detection: see checkJSON_Integrity prototype↓↓↓
            ani:{ // set all animation type for ex: Bob + reference name in json + frames asign of type of this anim
                idl1:{ref:'bob_idle1_',framesRange:[0,39]},
                idl2:{ref:'bob_idle2_',framesRange:[0,39]},
                att1:{ref:'bob_action1_',framesRange:[0,39]}, 
                winks1:{ref:'bob_winks_',framesRange:[0,9]},
                winks2:{ref:'bob_winks_',framesRange:[10,19]},
                winks3:{ref:'bob_winks_',framesRange:[20,29]},
                winks4:{ref:'bob_winks_',framesRange:[30,39]},
            }
        }
    };
};
//aniOBJECT SETUP_END β–‘β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

_pixiSSA.prototype.createLabel = function(labels) {// todo: (we will can affect groupe label to context with filter and motionContext)
    this.label = {'heroes':{}, 'monsters':{}, 'npc':{}, 'decors':{}, 'misc':{}, 'sfx':{}, 'menu':{},'unclassified':{}};
};
_pixiSSA.prototype.setDefaultSpeed = function(speed) {// todo: affect speed to motion
    this.defSpeed = speed||0.35;
};
_pixiSSA.prototype.checkJSON_Integrity = function(aniOBJ) {// Validate the integrity of json formats (multipack on single from texturePacker)
    var path = require('path'), gameDir = path.dirname(process.mainModule.filename);
    var fs = require('fs');
    for(objName in aniOBJ){
        this.aniObj[objName].valid_JSON = [];
        var len = this.aniObj[objName].json.length;
        for(var i = 0;i<len;i++){
            var dirFile = this.aniObj[objName].json[i];
            if(fs.existsSync(gameDir+'/'+dirFile+'.json')){
                this.aniObj[objName].valid_JSON.push(dirFile+'.json');
                continue;
            };
            for (var num=0; ;num++){
                if(fs.existsSync(gameDir+'/'+dirFile+'-'+num+'.json')){
                    this.aniObj[objName].valid_JSON.push(dirFile+'-'+num+'.json');
                }else{break;}
            };
        }
    }
};
_pixiSSA.prototype.load_aniOBJ = function(aniObj) { // load all obj set from _pixiSSA.prototype.importAniObj 
    var sheetsLoader = this.sheetsLoader = new PIXI.loaders.Loader(); // start newLoaders, dont affect other parallel loader.
    var allTexture = {};
    var val = function(i){ return i < 10 ? '00' + i : '0'+i; }; // return a number valur increment (callBack)
    for (var objName in aniObj) { sheetsLoader.add(aniObj[objName].valid_JSON) };
    sheetsLoader.load();
    sheetsLoader.onComplete.add(function(loader,data){ // called once when finish queued resources load. (callback)
        for (var ressourceName in data) { // apply loop setup only on .json, They hold the textures && compile all texture inside a variable 
            if(data[ressourceName].extension==="json"){ Object.assign(allTexture, data[ressourceName].textures) }; 
        };
        for (var aniName in aniObj) { // we have allTexture, now build all instence animation in aniObj
            for (var aniType in aniObj[aniName].ani) {
                var _objAni = aniObj[aniName].ani[aniType];
                var ref = _objAni.ref, framesRange = _objAni.framesRange;
                var frames = [];
                for (var i = framesRange[0]; i <= framesRange[1]; i++) { // push all texture need for the current ani (ordered list)
                    frames.push( allTexture[ref+val(i)+'.png']);
                };
                _objAni.texturesFrames = frames;
            };
        };
    });
};

var pixiSSA = pixiSSA || new _pixiSSA();
var Gamefall = Gamefall || {};
Gamefall.AniPicture = Gamefall.AniPicture || {};

//░▼↓▼░════════════════════════════════════════░-Spriteset_Base-░═════════════════════════════════════════════════════░↓↓↓
Gamefall.AniPicture.oldCreateScreenSprites = Spriteset_Base.prototype.createScreenSprites
Spriteset_Base.prototype.createScreenSprites = function() {
    this.createAnimations();
    Gamefall.AniPicture.oldCreateScreenSprites.call(this);
};
Spriteset_Base.prototype.createAnimations = function() { // Creating the container for the animations
    this._animationContainer = new PIXI.Container();
    this._animationContainer._listObjName = {}; // will store objName for fast get child index
    for(var i = 0; i <= 200; i++) {
        var _animationControler = new animationControler();  //experimental (will control all child) // New Sprite for storing the pixi container with the animation;
        this._animationContainer.addChild(_animationControler);
    };
    this.addChild(this._animationContainer);
};

pixiSSA.old_Spriteset_BaseUpdate = Spriteset_Base.prototype.update
Spriteset_Base.prototype.update = function() {
    // for now update are only for check animationControler binded to map
    this._animationContainer.children.forEach(function(animationControler) {
       if(animationControler._bindedToMap){
            animationControler.x = animationControler._originX - Math.abs($gameMap._displayX) * 48;
            animationControler.y = animationControler._originY - Math.abs($gameMap._displayY) * 48;
       };
    });
};


//░▼↓▼░════════════════════════════════════════░-Game_Screen-░═════════════════════════════════════════════════════░↓↓↓
Game_Screen.prototype.testMotionPerformance = function(name,valur) {//$gameScreen.testMotionPerformance('Bob',500); 
    // Warning: check dangerous gpu && cpu Temps! over 5000
    // 500 are multiply by X7 for eatch obj in bob.ani{} , ex: 500 = 3500 scyncro frame motion + MotionContext listener 
    var testPerf;
    for (var i=0;i<valur;i++){
        var x = Math.floor(Math.random() * Graphics.boxWidth) + 1;
        var y = Math.floor(Math.random() * Graphics.boxHeight) + 1;
        testPerf = $gameScreen.createAnimation(1,name,x,y);
    };
    var all = $gameScreen.get_animationContainer();
    for (var c=0;c<testPerf.children.length;c++){
        testPerf.children[c].play(), testPerf.children[c].renderable = true;
    };
};

Game_Screen.prototype.get_animationContainer = function() { //$gameScreen.get_animationContainer()
    if(SceneManager._scene._spriteset !== undefined) return SceneManager._scene._spriteset._animationContainer; //Method for calling easily the array of the animations
};

Game_Screen.prototype.get_animationByName = function(objName,motionName) {//a = $gameScreen.get_animationByName('Bob','idl1');
    var _animationContainer = this.get_animationContainer();
    var objNameIndex = _animationContainer._listObjName[objName];
    if(motionName){
        var motionNameIndex = _animationContainer.children[objNameIndex-1]._motionsListing[motionName]; // index of the motion
        return _animationContainer.children[objNameIndex-1].children[motionNameIndex]; // return le motion AnimatedSprite
    };
    return _animationContainer.children[objNameIndex-1]; // return _animationContainer
};

Game_Screen.prototype.getMotionsList = function(objName) {//$gameScreen.getMotionsList()
    return pixiSSA.aniObj[objName] && pixiSSA.aniObj[objName].ani || console.error(pixiSSA.aniObj,'ERROR! name: '+objName+ ' Not existing!');
};

Game_Screen.prototype.createAnimation = function(animationId,name,x,y) { //var a = $gameScreen.createAnimation(1,'Bob').playMotion('idl1'); ***
    var _animationContainer = this.get_animationContainer();
    var _animationControler = _animationContainer.getChildAt(animationId-1); // get sprite animationControler by ID
    if(_animationContainer.name === name){console.error('ERROR! animationId:'+animationId+' already has obj: '+name); return _animationControler};
        _animationContainer._listObjName[name] = animationId;
        _animationControler.name = name;
    var _motionsList = this.getMotionsList(name); // return motionsList possibility from nameObj ('bob')
    for (var motion in _motionsList) {
        var refNumber = _animationControler.children.length; // get current child num
        var aniSprite = new PIXI.extras.AnimatedSprite(_motionsList[motion].texturesFrames);
            aniSprite.anchor.set(0.5,0.5); // Compulsory value, for set use Parent
            aniSprite.name = motion;
            aniSprite.renderable = false;
            aniSprite._motionContext = {};
            aniSprite.animationSpeed = 0.4;
            // config: aniSprite.animationSpeed = 0.35; aniSprite.x = x||0, aniSprite.y = y || 0;
            aniSprite.onFrameChange = function(frame){
                if(this.renderable){
                    var ran = Math.random() * 100+ 1;
                    for (context in this._motionContext){ // execute all registered context
                        if (this._motionContext[context](frame,ran,_animationControler)){ 
                            break;
                        };
                    };
                }
            };
        _animationControler._motionsListing[motion] = refNumber; // list les motions dans les child
        _animationControler.addChild(aniSprite);
    };
    _animationControler.x = x; // todo
    _animationControler.y = y; // todo
    return _animationControler;
};


//░▼↓▼░════════════════════════════════════════░-animationControler-░═════════════════════════════════════════════════════░↓↓↓
// control ex: SceneManager._scene._spriteset._animationContainer.children bob
animationControler = function () {
    this._motionsListing = {};
    this._currentMotionRendered = null;
    PIXI.Container.call(this);
};
animationControler.prototype = Object.create(PIXI.Container.prototype);
animationControler.prototype.constructor = animationControler;

animationControler.prototype.get_CurrentMotionRendered = function() { //var .playMotion('idl1');
    return this._currentMotion;
};

//Allows you to call a new motions when a specific frame reach, stop and not renderable emiter.
animationControler.prototype.addMotionContext_Linear = function(motion,motionCall,frames,luck) { //var .addMotionContext_Linear('idl1','idl2',39,80)
    var motionChild = this.getChildAt(this._motionsListing[motion]);
    var motionChildCall = this.getChildAt(this._motionsListing[motionCall]);
    var luck = luck || 100;
    var that = this;
    motionChild._motionContext[frames+motionCall] = function(frame,ran,_animationControler){
        if(frame===frames && ran<luck){
            that._currentMotionRendered = motionCall;
            motionChild.renderable = false;
            motionChild.stop(); //ex: 'idl1'
            motionChildCall.gotoAndPlay(0); //ex: 'idl2'
            motionChildCall.renderable = true;
            return true;
        };
        return false;   
    };
};

//Allows you to call a motions when a specific frame reach, will keep emiter running but not renderable
animationControler.prototype.addMotionContext_Winks = function(motion,motionCall,frames,luck) { //var .addMotionContext_Winks('idl1','winks1',0,80)
    var motionChild = this.getChildAt(this._motionsListing[motion]);
    var motionChildCall = this.getChildAt(this._motionsListing[motionCall]);
    var luck = luck || 100;
    var that = this;
    motionChild._motionContext[frames+motionCall] = function(frame,ran,_animationControler){
        if(frame===frames && ran<luck){
            that._currentMotionRendered = motionCall;
            motionChild.renderable = false;
            motionChildCall.loop = false;
            motionChildCall.gotoAndPlay(0); //ex: 'winks1'
            motionChildCall.renderable = true;
            return true;
        };
        return false;
    };
    motionChildCall.onComplete = function(){ // maybe use _motionContext than .onComplete (need check)
        that._currentMotionRendered = motion;
        this.renderable = false;
        motionChild.renderable = true;
    };
};




//Allows you to call a audio objet synchronously when a specific frame reach
animationControler.prototype.addMotionContext_Audio = function(motion,audio,frames,luck) { //var .addMotionContext_Audio('idl1','idl2',39,80)
    // todo: https://pixijs.github.io/pixi-sound/examples/index.html
};

//Allows you to call a motions simultaneously and synchronously when a specific frame reach keep all render and play
animationControler.prototype.addMotionContext_FX = function(motion,motionCall,frames,luck) { //var .addMotionContext_FX('idl1','FX1',39,80)
    var motionChild = this.getChildAt(this._motionsListing[motion]);
    var motionChildCall = this.getChildAt(this._motionsListing[motionCall]);
    var currentMotionRendered = this._currentMotionRendered;
    var luck = luck || 100;
    motionChild._motionContext[frames+motionCall] = function(frame,ran){
        if(frame===frames && ran<luck){
            motionChildCall.loop = false;
            motionChildCall.gotoAndPlay(0); //ex: 'winks1'
            motionChildCall.renderable = true;
            currentMotionRendered = motionCall;
            return false;
        };
        return false;
    }
    motionChildCall.onComplete = function(){ // maybe use _motionContext than .onComplete (need check)
        this.renderable = false;
    };
};

//simply play a specific motion
animationControler.prototype.playMotion = function(motion) { //var .playMotion('idl1');
    var currentMotionRendered = this.getChildAt(this._motionsListing[this._currentMotionRendered]);
    console.log('this._currentMotionRendered: ', this._currentMotionRendered);
    if(currentMotionRendered){// check if a animation a curently running
        console.log('currentMotionRendered: ', currentMotionRendered.name);
        currentMotionRendered.stop();
        currentMotionRendered.renderable = false;
    }
    var motionChildCall = this.getChildAt(this._motionsListing[motion]);
    motionChildCall.gotoAndPlay(0);
    this._currentMotionRendered = motion;
    motionChildCall.renderable = true;
    
};


//stop current motion and say if we keep rendering
animationControler.prototype.stopMotion = function(keepRender, motion) { //var .stopMotion('idl1');
    var currentMotionID = this._motionsListing[motion||this._currentMotionRendered];
    if(typeof currentMotionID === 'number'){// check if a animation a curently running
        this.children[currentMotionID].stop();
        this.children[currentMotionID].renderable = keepRender||false;
    }
};

// will change parent layer [bottom,below_tilemap,below_characters,below_weather,default]
animationControler.prototype.changeLayerTo = function(Layer) { //var .changeLayerTo('idl1');
};

// Allow to Bind animation at specific X,Y coor
animationControler.prototype.bindMotionsTo = function(x,y) { //var .bindMotionsTo(0,0);
    this._bindedToMap = true;
    this._originX = x||this.x;
    this._originY = y||this.y;
};

animationControler.prototype.debug = function() { //var .debug();
    /*
    var newAni = $gameScreen.createAnimation(1,'Bob'); 
    newAni.playMotion('idl1');
    newAni.debug();
    */
    console.log('this: ', this);
    var debugChild = new PIXI.Text('5555555555555666666');
        debugChild.anchor.set(0.5,0.5);
        debugChild.width = this.width;
        debugChild.height = this.height;
        debugChild.canvas.width = debugChild.width;
        debugChild.canvas.height =  debugChild.height;
        var ctx = debugChild.canvas.getContext('2d');
        ctx.globalAlpha = 0.5; ctx.lineWidth = 6; ctx.strokeStyle = "#cd0000";
        ctx.strokeRect(0, 0, debugChild.width,  debugChild.height);
        ctx.globalAlpha = 1; ctx.font = "700 15px sans-serif"; ctx.lineWidth = 1; ctx.strokeStyle = '#ffffff'; ctx.fillStyle = "#cd0000";
        var txt = 'PIXI.extras.AnimatedSprite DEBUG: W:'+debugChild.width+' H:'+debugChild.height;
        ctx.strokeText(txt, 0, debugChild.canvas.height-5);
        ctx.fillText(txt, 0, debugChild.canvas.height-5);
    console.log('debugChild: ', debugChild);
    this.addChild(debugChild);
    

    /*
    var graphics = new PIXI.Graphics();
    graphics.pivot.set(0.5,0.5);
    console.log('graphics: ', graphics);
    graphics.beginFill(0xFFFF00);
    graphics.lineStyle(5, 0xFF0000);// set the line style to have a width of 5 and set the color to red
    graphics.drawRect(this.x, this.y, this.width, this.height);// draw a rectangle
        this.addChild(graphics);
        */
};

/*
var newAni = $gameScreen.createAnimation(1,'Bob',200,300); 
    newAni.addMotionContext_Linear('idl1','idl2',39,35);
    newAni.playMotion('idl1');
    newAni.debug();
*/











//todo
//░▼↓▼░════════════════════════════════░-PLUGIN_COMMAND-░═══════════════════════════════════════════════════░↓↓↓
Gamefall.AniPicture.Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand; //CREATING PLUGIN COMMAND FOR SHOWING THE ANIMATION
Game_Interpreter.prototype.pluginCommand = function(command, args) {
Gamefall.AniPicture.Game_Interpreter_pluginCommand.call(this, command, args);
if (command === 'ShowAnim') { // EX. ShowAnim 1 200 200 heroes Bob idl1 --> Show the animation;
    var id = Number(args[0]);
    var x = Number(args[1]);
    var y = Number(args[2]);
    var category = String(args[3])
    var name = String(args[4])
    var motion = String(args[5])
    $gameScreen.createAnimation(id, x, y, category, name, motion)
}
if (command === 'Anim') { //Ex. Anim Texture 1 decors grass1 footing --> Change the texture;
    if(args[0] === 'Texture') {
        var id = Number(args[1]);
        var category = String(args[2])
        var name = String(args[3])
        var motion = String(args[4])
        $gameScreen.changeTexture(id, category, name, motion);
    }
    else if(args[0] === 'Motion') { // Ex. Anim Motion 1 att1 --> Change the current texture motion
        var id = Number(args[1]);
        var motion = String(args[2])
        $gameScreen.changeMotion(id, motion);            
    }
    else if(args[0] === 'Move') { //Ex. Anim Move 1 300 250 --> Change the position of the anim
        var id = Number(args[1]);
        var x = Number(args[2]);
        var y = Number(args[3]);   
        $gameScreen.moveAnim(id, x, y)        
    }
}
};
//░▲↑▲░══════════════════════════════░-PLUGIN_COMMAND_END-░═════════════════════════════════════════════════░↑↑↑

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:11 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
finscncommented, Aug 28, 2017

I suggest that please use pivot as less as possible . In your use case , the pivot is not necessary. When you do translate rotate skew and scale , the pivot would trouble you, maybe.

Understanding frame, orig, trim, anchor, pivot, position, transform is a very important thing for using Pixi.js

1reaction
ivanpopelyshevcommented, Aug 28, 2017

i update square from base

square.x = -(this.width/2)+textureTrim.x;

In theory, you should only correctly set orig and trim for every frame, and not set position based on them. This thing works but it means you still dont understand how it actually works πŸ˜‰

Read more comments on GitHub >

github_iconTop Results From Across the Web

PIXI AnimatedSprite don't have correct width and height ...
Is it possible by a calculation with a formula or a method of going to seek the real value of the frames (croped)....
Read more >
PIXI.AnimatedSprite - PixiJS
The total number of frames in the AnimatedSprite. This is the same as number ... If the textures have not loaded then they...
Read more >
PixiJS Spritesheet sometimes doesn't load (appears as as a ...
background = new PIXI.AnimatedSprite.fromFrames(frames); myApp.background.width = Constants.WIDTH; myApp.background.height = Constants.HEIGHT;Β ...
Read more >
Pixi JS 7 / Error on PIXI.Assets.load(json) - Stack Overflow
I try using path to JSON in PIXI.Assets.load('/assets/fighter.json), is not help me. But i'm get another message in browser console : UncaughtΒ ...
Read more >
Pixi.js: SpriteSheet Animated Movement - YouTube
Pixi.js: SpriteSheet Animated MovementIn this tutorial we take a look at using spritesheets. I have a viking with some simple animations forΒ ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found