Jump to content

Pixi + DragonBones


alex_h
 Share

Recommended Posts

Found another little bug about the stripping of the file extension. changes:

dragonBones.makeBonesAtlas = function (atlasJson, name, partsList) {    var bonesAtlas = {};    bonesAtlas.name = name;    bonesAtlas.SubTexture = [];    var subTextures = atlasJson.frames;    var n = partsList.length;    var k = subTextures.length;    var partName;    var txData;    var filename;    var subTexture;    var frame;    var hasExtension = false;    for (var i = 0; i < n; i++) {        partName = partsList[i];        hasExtension = partName.match(/.png/i) !== null;        if(hasExtension){            filename = partName;            partName = partName.slice(0, -4);        } else {            filename = partName + ".png";        }        for (var j = 0; j < k; j++) {            txData = subTextures[j];            if (txData.filename === filename) {                frame = txData.frame;                subTexture = {name: partName};                subTexture.x = frame.x;                subTexture.y = frame.y;                subTexture.width = frame.w;                subTexture.height = frame.h;                bonesAtlas.SubTexture[i] = subTexture;                break            }        }    }    return bonesAtlas};
            PhaserBonesFactory.prototype._generateDisplay = function (textureAtlas, frameName, pivotX, pivotY) {                //get reference to the image object                var imageRef = textureAtlas.image;                //fetch the id of the atlas image                var imgName = textureAtlas.atlasId;                //create a sprite                var image = new Phaser.DragonBonesSprite(dragonBones.game, 0, 0, imgName);                //set the sprite frame from the texture atlas                image.animations.loadFrameData(image.game.cache.getFrameData(imgName));                //and the frameName... (restoring the .png that was stripped earlier)                image.frameName = frameName;// + ".png";                //set anchor point                // image.anchor.setTo(pivotX / image.width, pivotY / image.height);                image.pivot.setTo(pivotX, pivotY);                return image            }; 
Link to comment
Share on other sites

This look awesome! I was hoping someone to port the Dragon Bones JS version to Pixi.js. I would love to see how this works on mobile (without an accelerator of course)!

 

Can I ask you if does this support nested skeletons like the Create.js counterpart?

 

Link to comment
Share on other sites

I've only been using it on mobile with a single armature but so far it works just fine for me. The Pixi support is ported directly from the create.js factory so it should support any features that the create.js one does (minus the skewing for now, as discussed above!)

Link to comment
Share on other sites

That sounds impressive, I'll check it out whenever I can.

I've been making some things with Create js + dragonbones+ cocoonjs, with Cocoonjs everything was alright, but in mobile browsers performance was very slow. I was hoping someone to port the library to pixi because it's really fast on browsers.

Link to comment
Share on other sites

  • 2 weeks later...
  • 2 weeks later...

Found another little bug in phaser_dragonbones.js:

 

getChildIndex() --> getIndex()

 

            PhaserDisplayBridge.prototype.setDisplay = function (value) {                if (this._display == value) {                    return                }                if (this._display) {                    var parent = this._display.parent;                    if (parent) {                        var index = this._display.parent.getIndex(this._display)                    }                    this.removeDisplay()                }                this._display = value;                this.addDisplay(parent, index)            };
Link to comment
Share on other sites

And here's how to make tints work:

 

            PhaserDisplayBridge.prototype.updateColor = function (aOffset, rOffset, gOffset, bOffset, aMultiplier, rMultiplier, gMultiplier, bMultiplier) {                if (this._display) {                    this._display.alpha = aMultiplier;                    this._display.tint = Phaser.Color.getColor(255 * (rMultiplier + (rOffset / 100)), 255 * (gMultiplier + (gOffset / 100)), 255 * (bMultiplier + (bOffset / 100)));                }            };
Link to comment
Share on other sites

  • 3 months later...

Hi, I just did a quick test with PIXI 2.1 and the armature was animated as normal for me. Here is the adapter code I'm using, it's more or less the same as in my original post I think

var __extends = this.__extends || function (d,  {    for (var p in  if (b.hasOwnProperty(p)) d[p] = b[p];    function __() { this.constructor = d; }    __.prototype = b.prototype;    d.prototype = new __();};var dragonBones;(function (dragonBones) {    (function (display) {        var PixiDisplayBridge = (function () {            function PixiDisplayBridge() {            }            PixiDisplayBridge.prototype.getVisible = function () {                return this._display ? this._display.visible : false;            };            PixiDisplayBridge.prototype.setVisible = function (value) {                if (this._display) {                    this._display.visible = value;                }            };            PixiDisplayBridge.prototype.getDisplay = function () {                return this._display;            };            PixiDisplayBridge.prototype.setDisplay = function (value) {                if (this._display == value) {                    return;                }                var index = -1;                if (this._display) {                    var parent = this._display.parent;                    if (parent) {                        index = this._display.parent.children.indexOf(this._display);                    }                    this.removeDisplay();                }                this._display = value;                this.addDisplay(parent, index);            };            PixiDisplayBridge.prototype.dispose = function () {                this._display = null;            };            PixiDisplayBridge.prototype.updateTransform = function (matrix, transform) {                this._display.x = matrix.tx;                this._display.y = matrix.ty;                this._display.rotation = transform.skewX;                this._display.scale.x = transform.scaleX;                this._display.scale.y = transform.scaleY;            };            PixiDisplayBridge.prototype.updateColor = function (aOffset, rOffset, gOffset, bOffset, aMultiplier, rMultiplier, gMultiplier, bMultiplier) {                if (this._display) {                    this._display.alpha = aMultiplier;                }            };            PixiDisplayBridge.prototype.addDisplay = function (container, index) {                var parent = container;                if (parent && this._display) {                    if (index < 0) {                        parent.addChild(this._display);                    } else {                        parent.addChildAt(this._display, Math.min(index, parent.children.length));                    }                }            };            PixiDisplayBridge.prototype.removeDisplay = function () {                if (this._display && this._display.parent) {                    this._display.parent.removeChild(this._display);                }            };            PixiDisplayBridge.RADIAN_TO_ANGLE = 180 / Math.PI;            return PixiDisplayBridge;        })();        display.PixiDisplayBridge = PixiDisplayBridge;    })(dragonBones.display || (dragonBones.display = {}));    var display = dragonBones.display;    (function (textures) {        var PixiTextureAtlas = (function () {            function PixiTextureAtlas(image, textureAtlasRawData, scale) {                if (typeof scale === "undefined") { scale = 1; }                this._regions = {};                this.image = image;                this.scale = scale;                this.parseData(textureAtlasRawData);            }            PixiTextureAtlas.prototype.dispose = function () {                this.image = null;                this._regions = null;            };            PixiTextureAtlas.prototype.getRegion = function (subTextureName) {                return this._regions[subTextureName];            };            PixiTextureAtlas.prototype.parseData = function (textureAtlasRawData) {                var textureAtlasData = dragonBones.objects.DataParser.parseTextureAtlasData(textureAtlasRawData, this.scale);                this.name = textureAtlasData.__name;                delete textureAtlasData.__name;                for (var subTextureName in textureAtlasData) {                    this._regions[subTextureName] = textureAtlasData[subTextureName];                }            };            return PixiTextureAtlas;        })();        textures.PixiTextureAtlas = PixiTextureAtlas;    })(dragonBones.textures || (dragonBones.textures = {}));    var textures = dragonBones.textures;    (function (factorys) {        var PixiFactory = (function (_super) {            __extends(PixiFactory, _super);            function PixiFactory() {                _super.call(this);            }            PixiFactory.prototype._generateArmature = function () {                var armature = new dragonBones.Armature(new PIXI.DisplayObjectContainer());                return armature;            };            PixiFactory.prototype._generateSlot = function () {                var slot = new dragonBones.Slot(new display.PixiDisplayBridge());                return slot;            };            PixiFactory.prototype._generateDisplay = function (textureAtlas, fullName, pivotX, pivotY) {                var texture = PIXI.Texture.fromFrame(fullName + ".png");                //pixi sprite                var image = new PIXI.Sprite(texture);                image.pivot.x = pivotX;                image.pivot.y = pivotY;                //               return image;            };            return PixiFactory;        })(factorys.BaseFactory);        factorys.PixiFactory = PixiFactory;    })(dragonBones.factorys || (dragonBones.factorys = {}));    var factorys = dragonBones.factorys;})(dragonBones || (dragonBones = {}));/* generate a dragonbones atlas out of a TexturePacker JSONArray or Hash format atlas */dragonBones.parseJSONAtlas = function(atlasJson,name,partsList){    var bonesAtlas = {};    bonesAtlas.name = name;    bonesAtlas.SubTexture = [];    var n = partsList.length;    var subTextures = atlasJson.frames;    var isArray = Array.isArray(subTextures);    var k = 0;    if(isArray) k = subTextures.length;    //    var partName;    var txData;    var filename;    var hasExtension;    function createFrame(txData, p_partName){        var frame = txData.frame;        //make a subTexture        var subTexture = {name:p_partName};        subTexture.x = frame.x;        subTexture.y = frame.y;        subTexture.width = frame.w;        subTexture.height = frame.h;        //        bonesAtlas.SubTexture[i] = subTexture;    }    for(var i = 0; i < n; i++){        partName = partsList[i];        hasExtension = partName.match(/.png/i) !== null;        if(hasExtension){            filename = partName;            partName = filename.substr(-4);        } else {            filename = partName + ".png";        }        //find the subtexture        if(isArray){            for(var j = 0; j < k; j++){                txData = subTextures[j];                if(txData.filename == filename){                    createFrame(txData, partName);                    break;                }            }        } else {            for(var s in subTextures){                if(s == filename){                    createFrame(subTextures[s], partName);                    break;                }            }        }    }    return bonesAtlas;};dragonBones.makeArmaturePIXI = function(config, skeletonJSON, atlasJson, texture){    var skeletonId = config.skeletonId;    var armatureName = config.armatureName;    var animationId = config.animationId;    var partsList = config.partsList;    var textureData = dragonBones.parseJSONAtlas(atlasJson,skeletonId,partsList);    var factory = new dragonBones.factorys.PixiFactory();    factory.addSkeletonData(dragonBones.objects.DataParser.parseSkeletonData(skeletonJSON));    var atlas = new dragonBones.textures.PixiTextureAtlas(texture, textureData);    factory.addTextureAtlas(atlas);    var armature = factory.buildArmature(armatureName,animationId,skeletonId);    //updateAnimation();    dragonBones.animation.WorldClock.clock.add(armature);        armature.animation.gotoAndPlay(animationId, 0);    return armature;}
Link to comment
Share on other sites

  • 3 weeks later...

I finally, finally had the time to look at this properly - very simple fix for me:

 

Phaser.DragonBonesSprite.prototype.updateTransform = function(matrix, transform){     var parentTransform = this.parent.worldTransform;    var worldTransform = this.worldTransform;     var px = this.pivot.x;    var py = this.pivot.y;     var a00 = this.scale.x * Math.cos(this.rotation + this.skewY),        a01 = this.scale.y * Math.sin(-this.rotation - this.skewX),        a10 = this.scale.x * Math.sin(this.rotation + this.skewY),        a11 = this.scale.y * Math.cos(this.rotation + this.skewX),        a02 = this.position.x - a00 * px - py * a01,        a12 = this.position.y - a11 * py - px * a10,        b00 = parentTransform.a, b01 = parentTransform.c,        b10 = parentTransform.b, b11 = parentTransform.d;     worldTransform.a = b00 * a00 + b01 * a10;    worldTransform.c = b00 * a01 + b01 * a11;    worldTransform.tx = b00 * a02 + b01 * a12 + parentTransform.tx;     worldTransform.b = b10 * a00 + b11 * a10;    worldTransform.d = b10 * a01 + b11 * a11;    worldTransform.ty = b10 * a02 + b11 * a12 + parentTransform.ty;     this.worldAlpha = this.alpha * this.parent.worldAlpha;    };
Link to comment
Share on other sites

To create DragonBones animation you need to use the DragonBones Design Panel extension for Flash Pro

 

http://dragonbones.effecthub.com/

 

This generates the timeline data and texture atlas for your animation.

Thank you very much.

 

Do you know any other open source design tool. I don't  have a Flash pro to try Dragon Bones Design panel.  I am looking to port the tool to the Browser or Gimp  or inkscape. What you say? Any suggestions?

Link to comment
Share on other sites

  • 4 weeks later...

I can see wayfinder posted a solution on the skewing problem, but I thought I would post my solution anyway.

This one also support nested skeletons.

 

First the DragonBonesSprite:

Phaser.DragonBonesSprite = function (game, x, y, name) {    Phaser.Sprite.call(this, game, x, y, name);    this.skewX = 0;    this.skewY = 0;};Phaser.DragonBonesSprite.prototype = Object.create(Phaser.Sprite.prototype);Phaser.DragonBonesSprite.prototype.constructor = Phaser.DragonBonesSprite;Phaser.DragonBonesSprite.prototype.updateTransform = function(){    // create some matrix refs for easy access    var pt = this.parent.worldTransform;    var wt = this.worldTransform;    // temporary matrix variables    var a, b, c, d, tx, ty;    // so if rotation is between 0 then we can simplify the multiplication process..    if(this.rotation % PIXI.PI_2 ||   this.skewY % PIXI.PI_2)    {        a  =  Math.cos(this.skewY)* this.scale.x;        b  =  Math.sin(this.skewY) * this.scale.x;        c  =  Math.sin(- this.skewX)* this.scale.y;        d  =  Math.cos(this.skewX) * this.scale.y;        tx =  this.position.x;        ty =  this.position.y;        // check for pivot.. not often used so geared towards that fact!        if(this.pivot.x || this.pivot.y)        {            tx -= this.pivot.x * a + this.pivot.y * c;            ty -= this.pivot.x * b + this.pivot.y * d;        }        // concat the parent matrix with the objects transform.        wt.a  = a  * pt.a + b  * pt.c;        wt.b  = a  * pt.b + b  * pt.d;        wt.c  = c  * pt.a + d  * pt.c;        wt.d  = c  * pt.b + d  * pt.d;        wt.tx = tx * pt.a + ty * pt.c + pt.tx;        wt.ty = tx * pt.b + ty * pt.d + pt.ty;    }    else    {        // lets do the fast version as we know there is no rotation..        a  = this.scale.x;        d  = this.scale.y;        tx = this.position.x - this.pivot.x * a;        ty = this.position.y - this.pivot.y * d;        wt.a  = pt.a * a;        wt.b  = pt.b * d;        wt.c  = pt.c * a;        wt.d  = pt.d * d;        wt.tx = tx * pt.a + ty * pt.c + pt.tx;        wt.ty = tx * pt.b + ty * pt.d + pt.ty;    }    // multiply the alphas..    this.worldAlpha = this.alpha * this.parent.worldAlpha;};

Then create a DragonBonesGroup that extends Phaser.Group:

Phaser.DragonBonesGroup = function (game, parent, name, addToStage, enableBody, physicsBodyType) {    Phaser.Group.call(this, game, parent, name, addToStage, enableBody, physicsBodyType);    this.skewX = 0;    this.skewY = 0;};Phaser.DragonBonesGroup.prototype = Object.create(Phaser.Group.prototype);Phaser.DragonBonesGroup.prototype.constructor = Phaser.DragonBonesGroup;Phaser.DragonBonesGroup.prototype.updateTransform = function(){    // create some matrix refs for easy access    var pt = this.parent.worldTransform;    var wt = this.worldTransform;    // temporary matrix variables    var a, b, c, d, tx, ty;    // so if rotation is between 0 then we can simplify the multiplication process..    if(this.rotation % PIXI.PI_2 ||  this.skewY % PIXI.PI_2)    {        a  =  Math.cos(this.skewY)* this.scale.x;        b  =  Math.sin(this.skewY) * this.scale.x;        c  =  Math.sin(- this.skewX)* this.scale.y;        d  =  Math.cos(this.skewX) * this.scale.y;        tx =  this.position.x;        ty =  this.position.y;        // check for pivot.. not often used so geared towards that fact!        if(this.pivot.x || this.pivot.y)        {            tx -= this.pivot.x * a + this.pivot.y * c;            ty -= this.pivot.x * b + this.pivot.y * d;        }        // concat the parent matrix with the objects transform.        wt.a  = a  * pt.a + b  * pt.c;        wt.b  = a  * pt.b + b  * pt.d;        wt.c  = c  * pt.a + d  * pt.c;        wt.d  = c  * pt.b + d  * pt.d;        wt.tx = tx * pt.a + ty * pt.c + pt.tx;        wt.ty = tx * pt.b + ty * pt.d + pt.ty;    }    else    {        // lets do the fast version as we know there is no rotation..        a  = this.scale.x;        d  = this.scale.y;        tx = this.position.x - this.pivot.x * a;        ty = this.position.y - this.pivot.y * d;        wt.a  = pt.a * a;        wt.b  = pt.b * d;        wt.c  = pt.c * a;        wt.d  = pt.d * d;        wt.tx = tx * pt.a + ty * pt.c + pt.tx;        wt.ty = tx * pt.b + ty * pt.d + pt.ty;    }    // multiply the alphas..    this.worldAlpha = this.alpha * this.parent.worldAlpha;    for(var i=0,j=this.children.length; i<j; i++)    {        this.children[i].updateTransform();    }};

Make sure to use them:

PhaserBonesFactory.prototype._generateDisplay = function (textureAtlas, frameName, pivotX, pivotY) {  //fetch the id of the atlas image  var imgName = textureAtlas.atlasId;  //create a sprite  var image = new Phaser.DragonBonesSprite(dragonBones.game, 0, 0, imgName);  //set the sprite frame from the texture atlas  image.animations.loadFrameData(image.game.cache.getFrameData(imgName));  //and the frameName... (restoring the .png that was stripped earlier)  image.frameName = frameName + ".png";  image.pivot.setTo(pivotX, pivotY);  return image;};
PhaserBonesFactory.prototype._generateArmature = function () {  var display = new Phaser.DragonBonesGroup(dragonBones.game);  var armature = new dragonBones.Armature(display);  return armature; };

And finally make sure to update skewing in PhaserDisplayBridge:

PhaserDisplayBridge.prototype.updateTransform = function (matrix, transform) {  // apply the matrix to the phaser / pixi display object  this._display.x = matrix.tx;  this._display.y = matrix.ty;  this._display.skewX = transform.skewX;  this._display.skewY = transform.skewY;  this._display.rotation = transform.skewX;  this._display.scale.x = transform.scaleX;  this._display.scale.y = transform.scaleY; };

This is only tested on Phaser v2.1.3 using Pixi.js v2.0.0, but should hopefully work on newer releases too.

 

Link to comment
Share on other sites

  • 3 months later...

Hi everybody and Alex_h!

i am trying to run pixidragonbones with my animations and have some questions and troubles:
1) Where i need to get the "skeletonId"?

function createDragon(){        var partsList = [            "Bubbles.png",            "cauldron.png",            "oldie.png",            "young.png"        ];        var texture = PIXI.TextureCache["folder/texture.png"];        var skeletonJSON = loadedData["folder/skeleton.json"];        var atlasJson = loadedData["folder/texture.json"];        var config = {            armatureName: "GameFieldAnimation",            skeletonId: "Dragon",            animationId: "idle",            partsList: partsList        };

2 The example of pixidragonbones i change to load my own animation and every time i get the error:
"Uncaught TypeError: Cannot read property 'frames' of undefined"
Screenshot%20at%20%D0%B0%D0%BF%D1%80.%20

The animation is correct and well works with createjs.
I use last pixijs build and try export 2.4 and 3.0 dragonbones.

Link to comment
Share on other sites

Hi Olehakimov,

 

1) if you look in the skeleton json file the first property you see should be called "name". The value of this property is what I have referred to as the skeletonId.

 

2) Because I initially put this together for my own purposes I only configured the adapter to work with TexturePacker JSON format, not dragonbones json format. I'm guessing that your texture content is exported directly from the dragonbones design tool. You'll need to re-export it as individual pngs and then add those to a texturepacker atlas in either JSON Array or JSON hash format in order for this to work.

 

Good luck!

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...