• Editor
  • I'm working on a Python/Pygame runtime.

@[supprimé]

Are your graphics anchor points set to the centre in Python?

I ask because when I ported the Corona Lua to Gideros my graphics were out
of kilter (and bobbing) until I set the anchor points correctly

cheers

evs

I think you would find things a little easier to debug if you added a debug method to draw the bones, just indicate where the pivot is with a circle and the bone with a line. Then you'll know if it's the bones or the images that are causing the problem.

evs a écrit

@[supprimé]

Are your graphics anchor points set to the centre in Python?

I ask because when I ported the Corona Lua to Gideros my graphics were out
of kilter (and bobbing) until I set the anchor points correctly

cheers

evs

No, they're not. Pygame draws surfaces at (0, 0) by default.

Sounds like that may be the culprit... I'll give it a shot. Thanks!

What exactly did you have to do to fix this for Gideros?

Shiu a écrit

I think you would find things a little easier to debug if you added a debug method to draw the bones, just indicate where the pivot is with a circle and the bone with a line. Then you'll know if it's the bones or the images that are causing the problem.

Does my debug look correct? I can't quite tell, but it looks as though the images are off?

The top most circles look like the proper head/eye placement?

Thoughts?

 Loading Image

Let's try this again... the previous image was with flipX = False, flipY = False, and the root bone at 0, -300.

Here's one with flipY = True and the root bone at 0, 0:

 Loading Image

Hmmm... Looking at the Corona runtime some more, I think that I'm completely missing some steps.

I'm not rotating or scaling in pygame. I guess I got confused about that because the corona runtime apparently handles it internally with the image.x, image.y, image.scaleX, image.scaleY, and image.rotation variables on the texture?

Also, do I need to skeleton.flipY, or skeleton.flipX, considering that pygame is rendering from 0, 0 as the top-left corner? Seems like I need to set flipY?

Here's my debug code, which I'm not sure is correct:

                debug = True

            if debug:
                for bone in self.bones:
                    lineX = bone.worldX
                    lineY = bone.worldY
                    lineRotation = -bone.worldRotation

                    if self.flipX:
                        lineXScale = -1
                        lineRotation = -lineRotation
                    else:
                        boneXScale = 1
                    if self.flipY:
                        lineYScale = -1
                        lineRotation = -lineRotation
                    else:
                        boneYScale = 1

                    lineColor = pygame.Color(255, 0, 0, 0)

                    pygame.draw.line(screen, lineColor, (0, 0),  (x, y), 1)

                    circleX = int(bone.worldX)
                    circleY = int(-bone.worldY)
                    circleColor = (0, 255, 0, 0)
                    pygame.draw.circle(screen, circleColor, (circleX, circleY), 5, 1)

Your lines should not all come from 0,0. The lines show where the bones are. It should look like this:
 Loading Image
I think it makes sense to draw your lines before working about the images.

@[supprimé]

In Gideros it was just:

image:setAnchorPoint(0.5, 0.5)

I suppose in Python would be something like:

anchorX = slot.attachment.u2 - slot.attachment.width / 2
anchorY = slot.attachment.v2 - slot.attachment.height / 2

screen.blit(slot.attachment.texture, (anchorX, anchorY))

cheers

evs

So, I got a little frustrated with the bone/slot/rotation stuff, and I went ahead and got the color processing working. I had a few things that I missed, and I wasn't properly extracting the colors from the animation file.

Now I'm back to working on Shiu's suggestion of getting the slot/bone stuff working first, however, I think I've got everything right but the rotation (could be wrong, but it's worth asking, right?).

So, two questions:

  • Does this skeleton look right, sans rotation? I noticed that his eyes and head are actually properly textured... and when the eyes blink, they're in the correct spot. Everything else also looks like it's in the proper location, including the root bone, legs, arms, etc... they're just not rotated properly?

  • Any ideas why the hair is pink instead of orange, or whatever? Thoughts on debugging this?

His torso is missing here, but it shows up sometimes. I think someone else mentioned both the hair color and the torso issue in a previous post.

 Loading Image

[edit]

Here's an image with the torso, for posterity:

 Loading Image

The root bone is at 320x240.

It's quite a pain eh? :bang: Note the bone for the eyes is the same as for the head. Here's a screenshot for the un-animated Spineboy skeleton showing where you should expect the bones to be drawn.

 Loading Image

I'd forget about images for now and just draw lines for the bones. Start by just drawing a circle for each bone world position. If your bone transforms are correct (and taking into account y-up/down) then you'll get positions like in the screenshot. Next try drawing the bone lines. When you get the rotation right, it'll look like the screenshot. This should help a lot when rotating the images.

Nate a écrit

It's quite a pain eh? :bang: Note the bone for the eyes is the same as for the head. Here's a screenshot for the un-animated Spineboy skeleton showing where you should expect the bones to be drawn.

 Loading Image

I'd forget about images for now and just draw lines for the bones. Start by just drawing a circle for each bone world position. If your bone transforms are correct (and taking into account y-up/down) then you'll get positions like in the screenshot. Next try drawing the bone lines. When you get the rotation right, it'll look like the screenshot. This should help a lot when rotating the images.

Haha, yes, it is a pain, but it feels so close... 😉

Thanks for the still image. That will help.

Nope, bones don't look right.

I guess I'll need to start looking in the BoneData class? [Edit] Errr... Bone class. 😉

 Loading Image

I can't get my root bone to draw properly. My Y is set to -240, which is obviously wrong. I can't see anything different between my Bone class and Corona's, and Corona isn't using FlipY, so I don't think I should use that either, correct?

What else might be causing the root bone's location to be flipped, if not something in the Bone class? Hrm.

:-O

'm01': -0.0,

Seriously? I didn't know Python had a concept of a negative 0. That's problematic.

Does pygame work in radians or degrees? The numbers from Spine are in degrees, which I overlooked at first.

Another thing that took me awhile, was to figure out how to calculate the attachment rotation. (I'm working in C++, but in quads, not vertices, so I had to reference the corona runtime to figure it out.)

My final rotation looks like this: (Note the negation at the front.)

-(slot->bone->worldRotation + rotation) * 3.14159f / 180.0f

Does anyone know whether Corpna's. image rotation functions rotate clockwise or counter-clockwise?

Chounard a écrit

Does pygame work in radians or degrees? The numbers from Spine are in degrees, which I overlooked at first.

Another thing that took me awhile, was to figure out how to calculate the attachment rotation. (I'm working in C++, but in quads, not vertices, so I had to reference the corona runtime to figure it out.)

My final rotation looks like this: (Note the negation at the front.)

-(slot->bone->worldRotation + rotation) * 3.14159f / 180.0f

Hmmmm

I'm using math.radians() and I've quadruple checked my code against both Corona and C++ in terms of the mathematics.

But Pygame rotates counter-clockwise so I am wondering if that is different than other graphics libraries?

It looks like I've got an inversion happening on my Y-axis somewhere, so I'm trying to track that down. My root bone isn't in the right spot.

I've set my system up with x = 320, y = 240 but when the drawing code gets ahold of things the bone is at 320, -240.

Pygame uses degrees to rotate, so I think this is fine.

Still struggling with my root bone.

I've been combing through the code trying to figure out what's going on.

Here's the main initialization code and loop:

    skeleton.flipX = False
    skeleton.flipY = False
    skeleton.setToBindPose()
    rootBone = skeleton.getRootBone()
    rootBone.x = 320
    rootBone.y = 240
    skeleton.setRootBone(rootBone)
    skeleton.updateWorldTransform()

clock = pygame.time.Clock()
animationTime = 0.0

done = False

while not done:
    clock.tick(60)
    animationTime += clock.get_time() / 1000.0
    animation.apply(skeleton=skeleton,
                    time=animationTime,
                    loop=True)
    screen.fill((0, 0, 0))
    skeleton.draw(screen, 0)
    pygame.display.flip()
pygame.quit()

Here's my debug code for drawing the bone circles:

            if self.debug:
                for bone in self.bones:
                    if not bone.circle:
                        bone.circle = Circle(0, 0, 3)
                    bone.circle.x = int(bone.worldX)
                    bone.circle.y = -int(bone.worldY)
                    bone.circle.color = (0, 255, 0)
                    pygame.draw.circle(screen,
                                       bone.circle.color,
                                       (bone.circle.x, bone.circle.y),
                                       bone.circle.r,
                                       3)

When this debug code gets used, the bone.worldY is 240, so it gets flipped to -240 and my circle draws off screen.

This is exactly how Corona does it, so I can only assume that I've got something messed up somewhere that is supposed to be making bone.worldY negative before this drawing routine, but it's not happening.

Any ideas? I can't seem to figure out what's going on.

You don't need skeleton.setRootBone(rootBone). Doesn't help your problem though. I would not apply the animation until your are drawing the skeleton correctly.

Is 0,0 in the lower left corner of the screen? If so, then you have a y-up coordinate system like the libgdx runtime. Is 0,0 in the upper left corner of the screen? If so, then you have a y-down coordinate system like the Corona runtime.

If the negation is wrong, take it out. You might try not loading the bones from the file. Create a second bone parented to the root. Get those two bones to draw correctly with just translation, without any rotation and with scale at 1,1. Then add some rotation and make sure the two bones are in the correct place. Then go back to loading the skeleton from a file.

I would jump in the code and help out, but I'm swamped with other stuff at the moment. I've had a lot of non-coding stuff to get done and it's stressing me out, both that those tasks aren't finished and that I haven't been coding so I'm not making progress on the Kickstarter goals. :doh:

Thanks for the suggestions Nate. I realize you're super busy and I really appreciate all of your help.

I did figure some things out. 😉

I realized that the Corona runtime is actually setting skeleton.x and skeleton.y, while C++ is setting the root bone coordinates.

Both are setting these to positive values. I missed the fact that Corona is NOT actually setting the root bone coordinates, which means that when the root bone gets drawn, it is drawn at 0, 0 relative to skeleton.x, skeleton.y... doh... and since C++ uses flipped coordinates, setting the root bone to a positive value will cause it to get flipped with is The Right Thing™ for the SMFL runtime.

So... one mystery solved. :-)

I've added an x, y to my own skeleton class, and now I'm drawing things relative to its x, y.

I hate to be optimistic, but my pose looks 100% correct compared to the Corona bone points EXCEPT for the arm bone locations! :/

Image supprimée en raison de l'absence de support de HTTPS. | Afficher quand même

Is this another red herring, or does this actually help?

As for your other suggestion, I did a simple test where I created a root bone, and 4 other bones with a length of 10 and coordinates of:

(10, 10), (-10, 10), (10, -10), (-10, -10)

All of those bone points check out. I tested them one at a time. My drawing looks like:

Image supprimée en raison de l'absence de support de HTTPS. | Afficher quand même

I also plugged this into a test skeleton file and tested those one at a time... they draw correctly.

Any thoughts?

Good progress! 🙂 Do more tests with simple bones. Rotate the root, do the 4 children rotate correctly? Add more debug drawing, draw lines for the bone lengths.

These guys say they have Spine in Python, but I can't find the code:
http://ignifuga.org/

Since I'm currently only drawing the first frame of the skeleton at bone.worldX, -bone.worldY, shouldn't the arm placements be correct, or is there something that happens in the initial setup that could cause these to be off?

I'm not currently doing any rotation or anything like that... do I need to do that for these circles? I just drew them at bone.worldX, -bone.worldY.

This is what the Corona runtime seems to be doing, and the bones are all correct... so why are my arms broken?

I'll play some more, but it sounds like you're saying I'm on the right track...? 😉

Thanks for the link to the other library. I'll take a look.

I redrew the children in different colors to visualize what was happening.

When I add a positive rotation to the bones (self.bones[0].rotation += 10), they rotate counter-clockwise.

Is this the expected behavior?

It looks like children of children bones are properly rotating:

Initial state:

Image supprimée en raison de l'absence de support de HTTPS. | Afficher quand même

Rotated state:

Image supprimée en raison de l'absence de support de HTTPS. | Afficher quand même

Assuming additive rotation should cause counter-clockwise motion, this should be doing what it's supposed to?

Aha... something looks wrong with my rotation.

Starting point (looks good):

Image supprimée en raison de l'absence de support de HTTPS. | Afficher quand même

And once I start rotating:

Image supprimée en raison de l'absence de support de HTTPS. | Afficher quand même


Image supprimée en raison de l'absence de support de HTTPS. | Afficher quand même

Nate a écrit

These guys say they have Spine in Python, but I can't find the code:
http://ignifuga.org/

I don't see the code in their repo. Maybe it's unreleased.

Could be wrapping C++ maybe. Thought about doing that myself, but I like the idea of a pure Python implementation. It'll Just Work™ on Windows, Linux, OS X. :-)

Well, that is, if I can ever get it to work. 😉

HAH!

Found it.

grumble

terrymisu a écrit

HAH!

Found it.

grumble

Image supprimée en raison de l'absence de support de HTTPS. | Afficher quand même

     def setToBindPose(self):
@@ -34,7 +37,7 @@ class Bone(object):
             self.worldY = self.x * self.parent.m10 + self.y * self.parent.m11 + self.parent.worldY
             self.worldScaleX = self.parent.worldScaleX * self.scaleX
             self.worldScaleY = self.parent.worldScaleY * self.scaleY
-            self.worldRotation = self.parent.rotation + self.rotation
+            self.worldRotation = self.parent.worldRotation + self.rotation

Teehee. 😉

Hahaha... Still have a few kinks to work out:

Image supprimée en raison de l'absence de support de HTTPS. | Afficher quand même

Love those Neanderthal eyes though!

terrymisu a écrit

I don't think my timeline rotation is working... but he finally draws properly!

http://youtu.be/MiiUMWTkZzk

Got the timeline stuff working, but the rotation is obviously backwards... need to figure out where the extra minus sign is present or missing. 😉

http://youtu.be/qKBv-X3il3g

Took a little detour to figure out how to use the libgdx texture packer so I could play with an animation I made.

I used it to make the scaling code work. Unfortunately, Pygame doesn't seem to have an independent x and y scaling mode, so I took the average of x and y and I'll scale the image equally... I'm not sure if that's the best idea, but it seemed like a better idea than arbitrarily picking X or Y.

I'm still chasing some bad math, but here's a video of Spine Boy with his new sparkly sword:

http://youtu.be/Ld45-LlHxPY

Haha rotation is a little messed up, but nice sword! 😃

If your game toolkit can't draw quadrilaterals, then you should only use uniform scaling (equal x and y) in Spine. This is the case with Corona. You can actually use non-uniform scaling even if the game toolkit can't draw quads, but you have to align your images with the bone so that the images don't get squashed to a rhomboid (diamond) shape when the bone is scaled non-uniformly.

Nate a écrit

Haha rotation is a little messed up, but nice sword! 😃

If your game toolkit can't draw quadrilaterals, then you should only use uniform scaling (equal x and y) in Spine. This is the case with Corona. You can actually use non-uniform scaling even if the game toolkit can't draw quads, but you have to align your images with the bone so that the images don't get squashed to a rhomboid (diamond) shape when the bone is scaled non-uniformly.

Yeah, still chasing some pesky bugs. :/

I'm not sure I understand exactly what you're saying here. I can't blit non-rectangle shaped textures, so it sounds like I need to use uniform scaling, which is why I do my scale with (xScale + yScale) / 2 (not ideal, but...) Basically, I only have the option of passing a single float value for my "zoom" parameter.

The thing I'm confused about is that you've got scaling on your bones, and on your textures... and you could theoretically have your bones scaled differently than your textures. What happens if I scale something with different X/Y values in Spine and then try to use that in the python runtime?

If there is no rotation on the image attached to the bone you can use non-uniform scale. In the spineboy example all scale values are uniform at 1,1.
If you need to use non-uniform scaling the local-axis rotation of the image needs to be 0.

I haven't had much time to work on the Python port this week, but I'd like to wrap up the work I've done.

I'm having some trouble drawing the bones.

I don't understand what Corona is doing - it looks like the upper layer automatically takes care of drawing the line object that is created.

I can't draw lines with a rotation value in Pygame, so I need to draw the bones with specified (x, y) coordinates for the start and end point.

The origin is (bone.worldX, -bone.worldY), but where is the end point? Is it the parent's (bone.worldX, -bone.worldY)?

Afaik the end point is calculated by the rotation and length of the bone.

Yep, Shiu is right. Start by drawing your lines at the bone world x,y to bone world x+length,y. Works? Good. Now draw your lines with these coordinates:

float x1 = bone.worldX;
float y1 = bone.worldY;
float x2 = bone.worldX + cos(bone.worldRotation) * bone.length;
float y2 = bone.worldY + sin(bone.worldRotation) * bone.length;