Jump to content

2.4.7 -> 2.4.8 body anchoring. Any migration tips?


Noid
 Share

Recommended Posts

Any migration guide for how the new body anchoring works? 

I have a prite with anchor set to 0.5,0.5 and size set to  (20,30,0,0)
With 2.4.7 I could just do sprite.scale.x *= 1 to flip the sprite, now it displaces the body a lot. 
I'm not really sure how to fix it. 

 

bodyflipping.png

Link to comment
Share on other sites

Hi, this answer is going to be long...

 I am answering your question as 2.4.8 fix/change was made based on my GitHub issue (https://github.com/photonstorm/phaser/issues/2470), so I feel little responsible for it...

 I will use test graphics 60x60 pixels and it will be always tested with anchors from 0,0 to 1,1 (in 5 steps) on these 4 scenarios:

  • setSize(30, 30 0, 0) and scale.x = 1
  • setSize(30, 30, 15, 15) and scale.x = 1
  • setSize(30, 30 0, 0) and scale.x = -1
  • setSize(30, 30, 15, 15) and scale.x = -1

 In Phaser 2.4.7 two lines in src/physics/arcade/Body.js looked like this:

        this.position.x = (this.sprite.world.x - (this.sprite.anchor.x * this.width)) + this.offset.x;
        this.position.y = (this.sprite.world.y - (this.sprite.anchor.y * this.height)) + this.offset.y;

 Which produced results like this (red dot is anchor, green rect is body debug):

Phaser247.png

 As you can see on first row, despite offset was requested 0,0, it is actually changing from 0,0 to -30, -30, depending on the anchor. Your problem is with setting scale x to -1. You can see, you were lucky in Phaser 2.4.7, because happily it produced the same result in first row (third image) and in third row (third image). But having your anchor different from 0.5, 0.5 would produce less predictable results.

 

 In Phaser 2.4.8 source was changed to:

         this.position.x = (this.sprite.world.x - (this.sprite.anchor.x * this.sprite.width)) + this.offset.x;
         this.position.y = (this.sprite.world.y - (this.sprite.anchor.y * this.sprite.height)) + this.offset.y;

It produces results:

Phaser248.png

In first two rows, you can see, that setting setSize produces predictable result regardless of anchor. Body is now always set from top left corner of the sprite and its position is not influenced with sprite's anchor changes. Unfortunately, that change was obviously not enough to take into acount axis flips...

 So, suggested change may be like this, which takes into account also flips (negative scales):

        this.position.x = (this.sprite.world.x - (this.sprite.anchor.x * this.sprite.width)) + this.sprite.scale.x * this.offset.x;
        this.position.x -= this.sprite.scale.x < 0 ? this.width : 0;
        this.position.y = (this.sprite.world.y - (this.sprite.anchor.y * this.sprite.height)) + this.sprite.scale.y * this.offset.y;
        this.position.y -= this.sprite.scale.y < 0 ? this.height : 0;

It will produce these results:

Phaser248add.png

It keeps positioning made in 2.4.8 and add correction when scale is negative. Now, your body is always correctly offseted from top left (or top right with negative x scale).

If Rich is reading this and agrees with suggested changes, I will create GitHub issue for it...

 

Link to comment
Share on other sites

So, for anyone using sprite.anchor.setTo(0.5,0.5) and a body of width A and height B and who was using sprite.body.setSize(A,B,0,0) to get the body centered, they now have to do sprite.body.setSize(A,B,0.5*(sprite.width-A),0.5*(sprite.height-B)).  That is, offset to half the width of the sprite minus half the width of the body and half the height of the sprite minus half the height of the body.

That works fine now, even with negative values for scale. However, something else must have broken now, cause when I set the anchor to anything other than 0,0 it's starts vibrating. If I set the anchor to 1,1 the vibration is really noticeable and I can notice the character bumping against the wall. 

I'm adding a gif to demonstrate. I'm using debug.body with sprite.renderable = false so it's easier to see. Notice the erratic movement in the first half of the video(anchor set to 0.5, 0.5) and the smooth movement in the second half(anchor set to 0,0). Setting it to higher values makes the movement even more erratic, even if they're integers. Setting it hi negative values produces the same result. 
I started noticing this with 2.4.8 but I'm not sure if it's related to fixing #2470 or not so I'm gonna do some bisecting to find out where it started happening. 

Update: I can confirm the wobbling was introduced in commit f9994fac75c8ed4bf0b84751a1058de1b35e86f4 which is related to fixing #2470

anchor.gif

Edited by Noid
update
Link to comment
Share on other sites

8 hours ago, rich said:

Thanks for the quick fix Tom. This is now in the dev branch, along with updated jsdocs.

Everyone: Please give it a test! I've uploaded the 2.4.9 build files for you as well, so you don't need to even build it.

Why in version 2.4.9 function "setCircle" removed?

Link to comment
Share on other sites

10 hours ago, Noid said:

That works fine now, even with negative values for scale. However, something else must have broken now, cause when I set the anchor to anything other than 0,0 it's starts vibrating. If I set the anchor to 1,1 the vibration is really noticeable and I can notice the character bumping against the wall. 

Are you changing your sprite width and/or hieght? As it now clearly says what offset the body is from top-left corner of sprite, it can wobble body is sprite dimensions are different from frame to frame. For anchor 0,0 your body offset is always X, Y from top left of the sprite, which is anchored. If your anchor is let's say 0.5, 0.5 and you are animating frames with different dimentsions, then sprites's top left is changing (-width/2, -height/2 from anchor). As offset is from top-left of sprite it is then changing too.

Solution is to make all frames of animation the same size. If you are using atlas, then you are not wasting any space, as atlas tools usually trim empty space on export, while original dimensions are still preserved in atlas metadata and engine is using it internally.

Link to comment
Share on other sites

10 hours ago, rich said:

No, it was an experiment that wasn't finished in time for 2.4.8, so was moved out of dev and into its own branch. That function must have slipped through.

Richard, I want to ask one more question. Will circles-arcade-physics added into the main branch, if it will work well?

Link to comment
Share on other sites

On 5/24/2016 at 3:42 AM, Tom Atom said:

Are you changing your sprite width and/or hieght? As it now clearly says what offset the body is from top-left corner of sprite, it can wobble body is sprite dimensions are different from frame to frame. For anchor 0,0 your body offset is always X, Y from top left of the sprite, which is anchored. If your anchor is let's say 0.5, 0.5 and you are animating frames with different dimentsions, then sprites's top left is changing (-width/2, -height/2 from anchor). As offset is from top-left of sprite it is then changing too.

Solution is to make all frames of animation the same size. If you are using atlas, then you are not wasting any space, as atlas tools usually trim empty space on export, while original dimensions are still preserved in atlas metadata and engine is using it internally.

The problem seems to be that the empty space is being trimmed but the engine is not loading the metadata properly. 

This is part of my atlas.json file
 

	{"filename":"Pichon_Vuela00.png",
		"frame": {"x":865, "y":391, "w":58, "h":58},
		"spriteSourceSize": {"x":8,"y":1,"w":77,"h":66},
		"sourceSize": {"w":77,"h":66}
	},
	{"filename":"Pichon_Vuela01.png",
		"frame": {"x":550, "y":411, "w":65, "h":57},
		"spriteSourceSize": {"x":5,"y":1,"w":77,"h":66},
		"sourceSize": {"w":77,"h":66}
	},
	{"filename":"Pichon_Vuela02.png",
		"frame": {"x":616, "y":411, "w":64, "h":56},
		"spriteSourceSize": {"x":6,"y":0,"w":77,"h":66},
		"sourceSize": {"w":77,"h":66}
	},

If I console.log sprite.width while the animation is running I get the following values: 58, 65, 64. Those are the widths on the atlas image, were the sprites are tightly packed ignoring transparent pixels. However, when extracted from the atlas they should all be 77x66 as defined in sourceSize and spriteSourceSize. 
Maybe the atlas format changed and my .json file is no longer up to spec, but I can't find the specs anywhere on the repo.  

UPDATE: I couldn't find the specs but I could find some examples on the examples repo and it seems my json is no longer up to spec. It now needs a "trimmed" : true property in each frame that has been trimmed. Sorry, must've missed the update where that was added. 

Thanks for all the help, Tom! I think everything's working fine now. 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...