• Editor
  • Spine and Libgdx for MonoGame

I and My friends are working on a game project for windows 8 and we need spine for our game characters so we try to implement Spine for Monogame. The fact that we have implemented some amazing feature of libgdx in monogame so it is easy to "convert" libgdx spine to C# spines. Some feature we support in Gdna ( the name of project, which is in MonoGame): TextureAtlas ( we still not support filter or wrap because we will have to work more with texture2D but it can serialize all atlas file from TexturePacker now), re-write SpriteBatch to GdnaBatch, Particle Emitters, AssetsManager ( can load Skeleton and Particle async) , Sprite , SpriteA( animated sprite), GameCore2D( make it easy to manage your life cycle and catch Snap event in windows 8)... But it still lack of many feature, the code is totally free, you can do whatever you want with it😃 But if you have any comment about our code, logic, code style , design... plz tell us , we are student, we just want to learn more 😃
We haven't test this project in other platform , but we think it only Compatible with .Net 4.5

This is link to our project 😃
https://github.com/trungnt13/MonoGame/t ... ework/gdna
This is our test Project
http://sdrv.ms/WQrmcq
Sr for my bad English and Thanks for reading 😃

Related Discussions
...

Wow, that's quite a bit of code you have! 🙂 From a brief glance it looks like you ported the Spine runtime well. Did you port the libgdx stuff because MonoGame doesn't have the utilities necessary?

I'm also working on a MonoGame run-time, however I'm way behind you guys. I wasn't sure when the generic c# runtime would come out and was desperate to start seeing animations in code - also I thought it would be a good way to try and learn more about how the run-time worked. 🙂
Therefore the approach I took was to try and mirror the libgdx code as near as possible - thus ensuring I could easily update my version as and when fixes were applied to the libgdx version. I'm just finishing off the skeleton json import at the moment (using json.net) and then it is just the implementation of the attachments that I need to do. However this bit looks rather tricky and I'd say there is a good chance I won't complete it - especially if the official c# runtime comes out soon - although I guess it is an unknown as to how this will work with MonoGame. But it might be easier to port the official c# to MonoGame rather than libgdx possibly.
However looks like you guys might get something complete soon which would be great!

Sr for late Respond 😃
@ Nate: Yep I port many libgdx stuff such as: GdnaBatch with libgdx's style (you can draw TextureRegion, Texture2D - them same method as libgdx's SpriteBatch and the default origin is switch to bottom left corner), we have Sprite work the same way as libgdx, the TextureAtlas now work well too you can create it async or sync using Task of .Net, ParticleEffect & ParticleEmitter work well now ... 😃 The fact that after port some low level stuff of libgdx, it's easy to port other stuff , sometime it just like translate code 😃 And this will help us to merge Spine code from upstream very easy too 😃
@ randeroo: The fact that we develop Gdna( Gdx + XNA 😃) as a part of MonoGame, and we merge code from upstream MonoGame everyday and check for Spine update everyday 😃 You still can use all feature of MonoGame but when you draw something of Gdna such as: TextureRegion, Sprite, ParticleEmitter, Skeleton... you have to use GdnaBatch ( other batch that we re-write it) 😃 Porting libgdx to MonoGame make it really easy to keep Spine up to date and the other important thing is We are huge fan of libgdx 😃

One more time, sr for my bad English and thanks for reading😃

Wow - that is a lot of smileys 😉
I think that what you guys are doing is great - and it probably means that if I can't get my runtime working then I can try yours out.
And with the generic c# runtime in the not too distant future that gives me something else to look at.

Hi,

A quick update on my run-time. I feel like I'm almost there, however my problem is that I don't really know what I'm doing 😉 lol

I have managed to get my crab to animate, however I cannot get rotation to work. Here is a video of my crab running in MonoGame...

https://www.youtube.com/watch?v=BbiR30E ... e=youtu.be

...and this is what the crab should actually look like...

http://randolphburt.co.uk/?attachment_id=220

The video shows my animation with no attempt at rotation - As such I believe that all the bones are animating in exactly the right position. Once the rotation is fixed then it will be correct. The multiple attachments in slots appears to be working (you can see both types of eyes). I don't know about scale as I have not tried that (and indeed don't use it in this animation).

I've given up on rotation for tonight - will have another look tomorrow evening.
However, I was wondering if someone could explain to me what all the vertices are that are passed into the libgdx spritebatch.draw method used by the RegionAttachment class. I have just used vertices[X2] and vertices[Y2] to position my crab. I have not used any of the other vertices data. I'm guessing that the 'c' is colour so I'm not too worried about that at the moment, however I don't know what 'u' and 'v' are? And why are there 4 of each x,y,c,u and v?
In MonoGame (and hence xna) the spritebatch does not have a corresponding method - I just pass in the destination area that I want filling and the source graphic to fill it with - hence I've just used the X2 and Y2 vertices data. Does the u and v contain some rotation/scaling data?

As I say, so far I haven't used any of the other x,y data nor any of the u,v data so I would think I must be something wrong - otherwise why would it be there?

Any advice gratefully received 🙂

libgdx uses 4 vertices, one for each corner of the image. If your game toolkit doesn't need this, you don't need to compute the other 3 vertices. The u,v values are texture coordinates for each vertex, again not needed for you. You can see the Corona runtime which likely works similar to MonoGame.

Nice one. Many thanks. I'll take a look. 🙂

Wow, those were a lot of smiley 😃 I didn't see the review of my comment 😃 however, that is my favorite emotion 😃
I rewrite the SpriteBatch in MonoGame so it accept the vertice in the same way with libgdx:
Here is the method

public void Draw (Texture2D texture, float[] vertices, Color color, float depth)
        {
            if (texture == null)
                return;

        CheckValid(texture);

        if (vertices.Length != VertexSize)
            throw new ArgumentException("Vertices length must be equal " + VertexSize);

        DrawInternal(texture, vertices, color, depth);
    }

Here is the DrawInternal:

 internal void DrawInternal (Texture2D texture,
                                    float[] vertices,
                                    Color color,
                                    float depth)
        {
            var item = _batcher.CreateBatchItem();

        item.Depth = depth;
        item.Texture = texture;

        item.Set(vertices, color);

        if (_sortMode == SpriteSortMode.Immediate)
            _batcher.DrawBatch(_sortMode);
    }

And here is the most important thing ( this is in SpriteBatchItem.cs - I add this method 😃 ):

public void Set (float[] vertices, Color color)
        {
            // TODO, Should we be just assigning the Depth Value to Z?
            // According to http://blogs.msdn.com/b/shawnhar/archive/2011/01/12/spritebatch-billboards-in-a-3d-world.aspx
            // We do.

        //because texture coordinate in libgdx and xna is different we have some change here
        // U2V2 - BL
        // U1V1 - TL
        // U3V3 - TR
        // U4V4 - BR

        // bottom left world coor
        vertexBL.Position.X = vertices[SpriteBatch.X1];
        vertexBL.Position.Y = vertices[SpriteBatch.Y1];
        vertexBL.Position.Z = Depth;
        vertexBL.Color = color;
        vertexBL.TextureCoordinate.X = vertices[SpriteBatch.U1];
        vertexBL.TextureCoordinate.Y = vertices[SpriteBatch.V1];

        // top left world coor
        vertexTL.Position.X = vertices[SpriteBatch.X2];
        vertexTL.Position.Y = vertices[SpriteBatch.Y2];
        vertexTL.Position.Z = Depth;
        vertexTL.Color = color;
        vertexTL.TextureCoordinate.X = vertices[SpriteBatch.U2];
        vertexTL.TextureCoordinate.Y = vertices[SpriteBatch.V2];

        // top right
        vertexTR.Position.X = vertices[SpriteBatch.X3];
        vertexTR.Position.Y = vertices[SpriteBatch.Y3];
        vertexTR.Position.Z = Depth;
        vertexTR.Color = color;
        vertexTR.TextureCoordinate.X = vertices[SpriteBatch.U3];
        vertexTR.TextureCoordinate.Y = vertices[SpriteBatch.V3];

        //bottom right
        vertexBR.Position.X = vertices[SpriteBatch.X4];
        vertexBR.Position.Y = vertices[SpriteBatch.Y4];
        vertexBR.Position.Z = Depth;
        vertexBR.Color = color;
        vertexBR.TextureCoordinate.X = vertices[SpriteBatch.U4];
        vertexBR.TextureCoordinate.Y = vertices[SpriteBatch.V4];
    }

Here is my alias:

   public const int X1 = 0;
        public const int Y1 = 1;
        public const int U1 = 2;
        public const int V1 = 3;
        //
        public const int X2 = 4;
        public const int Y2 = 5;
        public const int U2 = 6;
        public const int V2 = 7;
        //
        public const int X3 = 8;
        public const int Y3 = 9;
        public const int U3 = 10;
        public const int V3 = 11;
        //
        public const int X4 = 12;
        public const int Y4 = 13;
        public const int U4 = 14;
        public const int V4 = 15;

    public const int VertexSize = 16;

However the UV in libgdx is not the same as MonoGame so you need a method to Convert it (RegionU,RegionV here is the uv,u2v2 of TextureReiogn in libgdx)

 /// <summary>
        /// Convert from uv,u2v2 to (BL,TL,TR,BR) vector
        /// </summary>
        public void ToTextureCoordinate (float[] vertices)
        {
            if (vertices.Length != 16)
                return;
            //	=============	Bottom left (u v2)	=============
            vertices[GdnaBatch.U1] = RegionU;
            vertices[GdnaBatch.V1] = RegionV2;
            //	=============	top left (u v)	=============
            vertices[GdnaBatch.U2] = RegionU;
            vertices[GdnaBatch.V2] = RegionV;
            //	=============	top right	(u2 v)=============
            vertices[GdnaBatch.U3] = RegionU2;
            vertices[GdnaBatch.V3] = RegionV;
            //	=============	bottom right (u2 v2)	=============
            vertices[GdnaBatch.U4] = RegionU2;
            vertices[GdnaBatch.V4] = RegionV2;
        }

I write it but now I forget why😐 maybe i will explain more when I remember how it work 😃

C# conventions are so weird. 🙁 Variables should start with small caps! Only class names should be start caps!

lol - I looked at those java files and thought 'Why are the methods names starting in lower case' - They should all be upper case 😉

Nate and trungnt - many thanks for taking the time to answer my queries - much appreciated. I have now re-coded my 'libgdx style runtime' to be a bit more 'corona runtime' like - but in c# so I can use it for MonoGame/xna. The runtime is on github (https://github.com/RandolphBurt/spine-runtime-monogame) for anyone who wants to take a look or whatever. As it stands I can now get an animation to work! Woohoo! Well happy 🙂
The code includes a demo project with my 'dancing crab' and it's targeted at iOS - but in theory should run on any platform that MonoGame supports - would just need to add all the code files to a project/solution appropriate for that run-time .
The c# code needs a bit of cleaning up - mainly better encapsulation. A lot of the class members may be more accessible than required - and those that do need to be accessed should be done via properties/methods. Depending on how the official generic c# runtime would suit MonoGame I may leave this for now though - as it may be that I'd be better off just fitting the MonoGame specifics around the generic c# runtime.

Nate - if any of this code is of any use to you for the generic c# runtime then please feel free to take it. I can't really claim any real credit for the work as it was a copy of the libgdx/corona work that you did anyway! 🙂
If however you look at the code and think 'yuck - I wouldn't do it like that', then I'm also not offended 🙂

I do have one problem that I haven't quite worked out yet - for some reason I have to specify a negative 'y' value when setting my root bone otherwise it doesn't appear on screen. I dare say I have a bug in there somewhere, although the MonoGame origin is top-left so that might have something to do with it.

I haven't tested this with scaling images in a timeline yet - and I haven't done anything with colour - however I feel I've used up my luck for today (and it's late) so I'm leaving it there for now.

cheers

A step closer - resolved the negative y axis issue.
Below I have a video of spine boy, the dragon and my crab on the iPad using MonoGame. For some reason the dragon's wings are not appearing quite right. Also spineboy has what looks like some scaling issues around the hip. Getting nearer though.... 🙂

https://www.youtube.com/watch?v=yHWU2vr ... e=youtu.be

Don't suppose anyone has any ideas on what is happening with the dragon wings? Looks like the wing bone is twisted 90 degrees too far. Very strange.