[FIXED] How can I use graphics.newOutline() with @2x and @4x image substitution?

Nevermind. graphics.newOutline is working very well. The issue was with my image such that higher resolution version had some very fine gaps / breaks in the outline. These must be compressed when I downshifted the image to 1x so outline for 1x was tracing well. Once I went to 4x suddenly my trace was broken but this has nothing to do with the graphics.newOutline api. All is good. Case closed. 

Hi Kerem,

I just posted my “physics body flipper” in the Code Exchange. Please test it out and let me know if there are any issues.

Currently, it only handles horizontal flipping. Adding vertical flipping would probably be easy enough, but I don’t have time to tinker with that and test it. As I said above, you can always take the “easy way out” and just rotate the horizontally-flipped body 180 degrees and achieve the same thing. :slight_smile:

http://code.coronalabs.com/code/physics-body-shape-flipper

Brent

Hi Brent, 

Will test as soon as possible. Thank you very much for sharing this solution. I agree, rotate + flip horizontal will cover all possible needs. 

Regards,

Kerem

I noticed the following in my console while running my app in simulator at 4x res… 

The generation of the physics body for this outline had to be cut short. Please provide a simpler input.

The resulting physics body still looked and worked ok so I don’t know what was cut short but then I reduced the coarsenessInTexels value one at a time from the initial 2 and eventually found a number which still looked and worked great did not generate this error. Thought I should share with others reading this thread about newOutline API and high-res images … 

In what way isn’t it working?  The physics body should be relative to your content area so it shouldn’t matter which image it grabs.

Rob

In what way it isn’t working? Hybrid mode allows me to verify the physics body drawn vs the actual image and I can see the physics body is following the pixel count of x1 image that was used in creating it. Here’s how I do it currently (as per sample app etc)

local imageOutline = graphics.newOutline( 2, "myImage.png" ) local physicsPiece = display.newImageRect(group, "myImage.png", 60, 512); physics.addBody(physicsPiece, "static", {bounce = 0, outline=imageOutline}); 

So my x1 image is 60x512. The graphics.newOutline works on it and gets me an outline which I then feed into the physics.addBody. The object is created with the newImageRect though so this means it might pull in the @2x (120x1024) or even @4x (240 x 2048) images respectively. The graphics.newOutline does not seem to pull in the @2x or @4x when needed. Does this help clarify my problem?

Thanks for your help.

A potential workaround could be to detect the resolution we are running in and therefore understand which image will be used by display.newImageRect and feed that version of the image to graphics.newOutline. Short of graphics.newOutline becoming able to  automatically substitute higher-resolution assets on higher-resolution devices this could be a possible way to deal with this issue. Would you agree?

I would think that the values are based on the content area you have defined in your config.lua.  The scaling should not have an effect.

Lets say you have a 1x image that generates say a 100x100 square.   That’s a 100x100 in your content area.  If we load in the @2x image, even though its 200x200, it’s still 100x100 with regards to your content area and that polygon would still be the right shape.  The @4x at 400x400 still takes up 100x100 in content space.

What evidence do you have that something is afoot?  Can you produce screen shots showing the physics overlaying the image so I can see where it’s off?

Thanks

Rob

Ok. Here it goes. I took the CL falling crate demo app. I upsized the crate to 2x and 4x sizes and marked with text to make sure I know which image is loaded. I then used the following code to define the body : 

 -- make a crate (off-screen), position it, and rotate slightly local crate = display.newImageRect( "crate.png", 90, 90 ) crate.x, crate.y = 160, -100 crate.rotation = 15 local imageOutline = graphics.newOutline( 2, "crate.png" ) -- add physics to the crate physics.addBody( crate, { density=.1, friction=1, bounce=0.1, outline=imageOutline } )

I put a pause in there somewhere so I can get screenshots. This is with hybrid mode on of course. Take a look at the 1x, 2x & 4x screenshots attached. You can clearly see the physics shape defined by graphics.newOutline keeping to the original 1x size of “crate.png”. 

Hope this helps. I now have the demo app anyways so I can submit this as a bug if you like. 

Perfect.  That’s what I needed to see.  This seems like a bug to me.  Can you file a bug report and make sure to include these screen shots?

Thanks

Rob

Thanks. Case 30296 submitted. Meanwhile I will rely on newImage rather than newImageRect and force my screen to use 1x images so I don’t have the problem.

If I wanted to implement the other workaround I mentioned above, what would be the easiest way to determine if display.newImageRect is about to use @2x or @4x images? Appreciate your help.

Well a lot depends on your config.lua and the scale values you use before you switch, but it’s something like:

local sf = display.pixelWidth / display.contentWidth

if sf > 3.0 then

    – use @4x

elseif sf > 1.5 then

    – use @2x

else

   – use 1x

end

Where 3.0 and 1.5 are the values you  have in your config.lua.

Rob

Got it. Thanks. That should work well in the meanwhile. 

The display.imageSuffix API is a better way of determining which suffix your app is going to use (or not use). It’ll return the suffix, or return nothing if the scale factor is 1:1 (so you have to test for “nil” which means the suffix is actually in the 1:1 ratio).

http://docs.coronalabs.com/api/library/display/imageSuffix.html

Brent

Thank you very much! Even better!!! Lets hope graphics.newOutline() gets fixed to deal with this internally in the future but for the time being the display.imageSuffix API will provide a simple workaround. 

I fixed the problem. Please try tomorrow’s daily build and let us know if you have any further issues. Thanks!

Will do. Thank you very much for the quick turnaround. And I must say this is one very powerful and useful API call. Its a pleasure to watch the outlines it creates it Hybrid mode.

Albert, additional observation. Not sure if you consider this a bug or a ‘feature’…

After setting the imageOutline I can use object.rotation and the outline will rotate with the object. This is great! If I use Yscale = -1 to flip the object then imageOutline does not flip with the object. In other words, 

Code Snippet A

object.yScale = -1;

object.xScale = -1;  

Code Snippet B

object.rotation = 180

Code Snippet A and Code Snippet B does exactly the same thing visually but as far as the physics body defined with graphics.newOutline() the outcome is 180 degrees different… I can live with rotation in this project but in some cases we will simply need to flip in one direction which rotate will not do.

Thoughts?

I don’t believe you can scale physics objects.  You have to remove and re-add the body after changing it’s scale.  Usually people are changing scale to make it bigger or smaller, but flipping images won’t affect the physics body either.

Rob

Thanks. Remove & add physics body doesn’t work in this situation because you can’t give graphics.newOutline() the flipped display object to process. You can only give it the original file which is still not flipped. Thankfully rotate works and gets the job done for me in this instance but I can see cases where you might need to supply the flipped image and do away with the X/Yscale = -1 calls. I understand the limitation coming from the Box2D engine. Thanks