newPolygon: Can anyone explain how the .width parameter works?

I’ve made a simple game involving polygons that scales out from the center of the screen.

It can be found here if anyone, for some perverse reason, should be interested…:

https://play.google.com/store/apps/details?id=com.gmail.runewinse.Ketchup&hl=en

But I’m not sure that I do his the most efficient way. As it is now I delete and recreate each polygon with a new, recalculated set of vertices per frame.

Since the polys essentially doesn’t do anything but scale I was certain that it would be a good idea to just create the polygon once (at leas until it’s off screen and need to be replaced) at the largest visible size and then use the width/height parameter and set the size of the polygon according to the z value (depth).

But I just cannot make it to work. The .width/.height seem to work in a way that (to me) is completely unexpected. Please consider the code below:

local vertices = {-300, -300, 300, -300, 300, 300, -300, 300} local poly = display.newPolygon(display.contentWidth/2, display.contentHeight/2, vertices ) poly:setFillColor(1,1,0,1) local function RedrawPoly() poly.width = 580 poly.height = 580 end local frameRedrawListener = function(e) RedrawPoly() end Runtime:addEventListener( "enterFrame", frameRedrawListener )

Here I initialize a polygon and then (per frame) try to set the width/height to a fixed number. But what happens? Run it and see for yourself!

It seems like what happens by setting the width/height is depending on the original size of the poly. Here the original width/height is 600x600. Each time i set the width/height to 580x580 it seems to make the poly scale down a bit. So repeatedly setting the size to 580x580 just keep shrinking the poly until it’s gone.

The larger the difference from the original to the new size the faster the shrinking. Unless, that is, the new size is larger than the original size, in which case the poly just keeps expanding… :rolleyes:

So… what’s going on here. Is what I’m trying to to impossible? Do I have to keep recreating all the evil polygons (of doom) for each and every frame or is there a way to scale them with some sort of control?

try instead setting xScale/yScale, fe if it’s 600x600 and want it to appear 400x400 then:

poly.xScale = 400/600

poly.yScale = 400/600

Thanks a bunch! That seems to work. I didn’t want to use x/y scale because I thought it was relative to the last (rescaled) size, but apparently the scaling is compared to the creation size.

Thanks again, davebollinger!

Some additional info:

The method object:scale(x,y) scales relative to its current scale, whereas setting the .xScale / .yScale properties directly gives you exact control.

ingemar, by “exact control” you mean the scaling is relative to the “creation size” of the object?

BTW, I’ve tested the usage of .xScale and .yScale and it seems to work as intended  :slight_smile:

Thanks to both of you!

ingemar, by “exact control” you mean the scaling is relative to the “creation size” of the object?

Yes. The “creation size” of the object is simply the original width/height of it which is found in the .width / .height properties and don’t change when scaling. This is a thing to keep in mind if you want to know the true display width/height of an object which is object.width * object.xScale and object.height * object.yScale.

Most of the time xScale and yScale are 1.0 so it’s easy to forget that if the scale changes you’ll need to take these into consideration when calculating object size.

xScale and yScale work well with transition.to also.  That could make the housekeeping easier and opens up the possibility of using the easing functions.

http://docs.coronalabs.com/api/library/transition/to.html

the problem arises (tho it’s not really a problem, just misunderstood) from fact that your poly’s width/height are going to remain what’s defined by the vertices.

when you say “width=580”, what Corona interprets that to mean is “figure out object’s size, ok it’s 600x600, now make it appear 580x580, ok that means scale(0.966667), done”.   except that the poly’s native/true width/height have NOT changed, so if you repeat that you’ll get unexpected results (because you’re now starting with that 0.966 scale in place, and object size still 600x600 - different starting conditions, get it?)

next time you do that, the same exact math occurs (because your poly itself is STILL 600x600), so the equivalent of scale(0.9666667) occurs, but scale() is cumulative (it’s a factor, not an absolute).  so now you’re at 96.7% of 96.7% of 600, or ~561.  Next time even smaller, and so on.

xScale/yScale are absolute scales (not factors relative to current scale), so they’re the ones that work as you need.

note that similar happens between .rotation and :rotate(), and .x/.y and :translate() – the property version sets an absolute, the method is relative.  *setting* values for width/height is not rigorously defined in the docs (tho it’s clear from experimentation like this what “happens” internally - it’s implied meaning is equivalent to calling scale())

I don’t know if it’s even possible to “misunderstand” if the behavior is not described in the docs at all…  :wacko:

Seems like you have to figure out by yourself how these things work - or get help by guys like yourself here, of course!

I think I’m beginning to get how it works, but I fail to see the logic behind why it. Why setting the width property does not do just that: Setting the width to the specified value instead of going through some internal scaling that is cumulative. From a SDK users standpoint it’s messy…

But when I know of these things it’s no big a deal.

And that is what width/height should also have been IMHO  :slight_smile:

try instead setting xScale/yScale, fe if it’s 600x600 and want it to appear 400x400 then:

poly.xScale = 400/600

poly.yScale = 400/600

Thanks a bunch! That seems to work. I didn’t want to use x/y scale because I thought it was relative to the last (rescaled) size, but apparently the scaling is compared to the creation size.

Thanks again, davebollinger!

Some additional info:

The method object:scale(x,y) scales relative to its current scale, whereas setting the .xScale / .yScale properties directly gives you exact control.

ingemar, by “exact control” you mean the scaling is relative to the “creation size” of the object?

BTW, I’ve tested the usage of .xScale and .yScale and it seems to work as intended  :slight_smile:

Thanks to both of you!

ingemar, by “exact control” you mean the scaling is relative to the “creation size” of the object?

Yes. The “creation size” of the object is simply the original width/height of it which is found in the .width / .height properties and don’t change when scaling. This is a thing to keep in mind if you want to know the true display width/height of an object which is object.width * object.xScale and object.height * object.yScale.

Most of the time xScale and yScale are 1.0 so it’s easy to forget that if the scale changes you’ll need to take these into consideration when calculating object size.

xScale and yScale work well with transition.to also.  That could make the housekeeping easier and opens up the possibility of using the easing functions.

http://docs.coronalabs.com/api/library/transition/to.html

the problem arises (tho it’s not really a problem, just misunderstood) from fact that your poly’s width/height are going to remain what’s defined by the vertices.

when you say “width=580”, what Corona interprets that to mean is “figure out object’s size, ok it’s 600x600, now make it appear 580x580, ok that means scale(0.966667), done”.   except that the poly’s native/true width/height have NOT changed, so if you repeat that you’ll get unexpected results (because you’re now starting with that 0.966 scale in place, and object size still 600x600 - different starting conditions, get it?)

next time you do that, the same exact math occurs (because your poly itself is STILL 600x600), so the equivalent of scale(0.9666667) occurs, but scale() is cumulative (it’s a factor, not an absolute).  so now you’re at 96.7% of 96.7% of 600, or ~561.  Next time even smaller, and so on.

xScale/yScale are absolute scales (not factors relative to current scale), so they’re the ones that work as you need.

note that similar happens between .rotation and :rotate(), and .x/.y and :translate() – the property version sets an absolute, the method is relative.  *setting* values for width/height is not rigorously defined in the docs (tho it’s clear from experimentation like this what “happens” internally - it’s implied meaning is equivalent to calling scale())

I don’t know if it’s even possible to “misunderstand” if the behavior is not described in the docs at all…  :wacko:

Seems like you have to figure out by yourself how these things work - or get help by guys like yourself here, of course!

I think I’m beginning to get how it works, but I fail to see the logic behind why it. Why setting the width property does not do just that: Setting the width to the specified value instead of going through some internal scaling that is cumulative. From a SDK users standpoint it’s messy…

But when I know of these things it’s no big a deal.

And that is what width/height should also have been IMHO  :slight_smile: