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

The new graphics.newOutline() works great in the actual resolution of the png file provided. When I use it with a display.newImageRect I have a problem though. newImageRect substitutes higher resolution assets depending on the device specifics and the outline used in physics.addBody does not seem to follow suit. Is there a way around this issue?

I could use display.newImage obviously and not make use of the higher resolution assets but then the visuals are not appealing at all. What is the best strategy to follow in this situation? Thanks for your help.

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

Hi Kerem,

I recently created a simple “shape flipper” function, which could potentially be used to flip the coordinates of newOutline()-generated shapes. Do you want me to post it here? It only works for horizontal (y-axis) flipping, not vertical, but in truth a vertical flip is the same as a 180-degree-rotated horizontal flip.

Brent

Hi Brent, thanks for offering that. Indeed would love to have a copy. Maybe a post in Code Exchange for maximum exposure? Thanks in advance. 

Albert, I tried 2174 and I can see graphics.newOutline is doing something different @2x and @4x so thank you very much for your prompt response. There is a problem though and it is not returning the right outline as 1x did against the 1x image. It might be something to do with my images which was not becoming a problem earlier. May I send you 3 images for you to see for yourself?