PIXI AnimatedSprite don't have correct width and height Frames???
See original GitHub issueHello 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:
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
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:
- Created 6 years ago
- Comments:11 (8 by maintainers)
Top GitHub Comments
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.jsIn 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 π