Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

questions about anchorChildren
Started by mark_steelman Dec 30 2013 01:52 PM

26 replies to this topic
graphics 2.0
[TOPIC CONTROLS]
Page 1 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

mark_steelman

[GLOBAL: userInfoPane.html]
mark_steelman
  • Contributor

  • 142 posts
  • Corona SDK

I've read the documentation but I still have some questions about this.

 

If I understand it correctly, the main thing this flag does is change the position of the objects in a displayGroup from coordinate based to a fraction.  It also allows the group to be rotated around it's anchor point instead of it's origin.

 

So, first, do I have that part right?

 

Second, how does it behave if there are groups inside of groups?

 

In my program, there is a player displayGroup, inside of a room displayGroup, inside of a map displayGroup.  I want to rotate the map around the player so that the player does not appear to move.  Something about the conversion to the new graphics 2.0 broke this functionality and I can't figure out what.



[TOPIC: post.html]
#2

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

 If I understand it correctly, the main thing this flag does is change the position of the objects in a displayGroup from coordinate based to a fraction.

 

Not really. The problem I have is with the name anchorChildren. It might be just me, but my brain doesn't process the term since it doesn't modify the behavior of the children per se.

Regardless of if anchorChildren is true or false, adding objects to the group will still use the children's common anchor point to position them relative to each other.

The only time anchorChildren comes into play is when you want to position the group on the stage.
When anchorChildren=true, the group will get its own anchor point which you can set like on any other object. This makes it easier to position if you have groups where the children's common anchor point is at an arbitrary position.
When anchorChildren=false, the group's positioning will be using the children's common anchor point which may prove to be tricky to position the way you want.

To me the term anchorGroup=true makes more sense than anchorChildren=true as the ultimate effect of setting this property affects the group's positioning, not the children within the group.



[TOPIC: post.html]
#3

mark_steelman

[GLOBAL: userInfoPane.html]
mark_steelman
  • Contributor

  • 142 posts
  • Corona SDK

I guess I'm not clear about what anchorChildren can do for me.  I can tell it is doing something because if I add objects to a group where anchorChildren = true then they are not in the same position as when I add them when it is false.  I examined the example of the clock hands spinning but that is a very limited use of a group... one object, a fixed group width...

 

Also, is anchorChildren the kind of thing I can turn on, then do some functions, then turn off?  It is very obtuse at this time.  I feel it needs to be explained a lot better than it has been explained before it is much use.



[TOPIC: post.html]
#4

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,328 posts
  • Corona Staff

@mark_steelman, have you read our tutorial/blog post on Anchor Points?  http://www.coronalabs.com/blog/2013/10/15/tutorial-anchor-points-in-graphics-2-0/

 

We try to explain the behavior there.

 

Rob



[TOPIC: post.html]
#5

mark_steelman

[GLOBAL: userInfoPane.html]
mark_steelman
  • Contributor

  • 142 posts
  • Corona SDK

I have read it and I played around with it.  I appreciate you writing it but it is not answering the questions I posted above.  I spent a little more time with it just now and changed the blocks so that they always appeared in the same location so I could be certain I wasn't wasting your time.

 

AnchorChildren seems to simply move the reference point of the group to a point within the objects of the group defined by anchorX and anchorY.

 

I feel that what makes it confusing is the name. The children in a group are in a fixed position from the moment you add them to the group, they aren't being anchored by anchorChildren. It would seem that it would make more sense if it were named, anchorAsRef = true or something like that. The way it is named, I was expecting the objects in my group to start sliding around when I moved the group and that is not what happens (thank God for that).

 

I think the problem I am still having is, there doesn't seem to be any tools that allow you to quickly assertain the total width of all the objects in the group that are considered by anchorChildren.  You say that anchorChildren converts the group so that it has a finite width and height but I don't have access to the information about those boundaries.

 

For example, referring to your tutorial, say I wanted to create 5 buttons that move the anchor point to the center of each of your 5 rectangles.  I think what I would have to do is determine which of the rectangles is farthest to the left and the right, then calculate the x offset and y offset of the target rectangle from that position, then move the anchorX and anchorY to the fraction equivalent of that position, then anchorChildren, then rotate.

 

That's a pretty big mathematical mess, especially if you change which rectangle is in the center after they start rotating.

 

I am also still unclear on whether or not anchorX and anchorY has an effect on the behavior of a group when you don't turn on anchorChildren. It doesn't seem to affect the rectangles in your example until I anchorChildren. I might be trying to get it to do something that it just doesn't do.  What I really want is to get back the functionality that existed before the change so that the code that I have been developing for almost a year will stop being broken by "graphics 2.0". I want a coordinate based displayGroup with it's reference point in the upper left corner. Now it seems that the only way I can get an upper left corner reference is by using fraction based positioning which is not nearly as flexible/simple.



[TOPIC: post.html]
#6

mark_steelman

[GLOBAL: userInfoPane.html]
mark_steelman
  • Contributor

  • 142 posts
  • Corona SDK

Ok, I worked it out.

 

In fact, anchorX and anchorY don't do anything unless anchorChildren is active.  It seems that making anchorChildren exposed is kind of useless and causes needless confusion.  It would make the whole thing simpler to just have setting anchorX or anchorY to anything other than .5 automatically turn on the functionality and setting them both back to .5, .5 would turn it off.

 

The problem I was experiencing was actually related to the change in reference points and once I could sort that out I fixed it.  This other business turned out to be just confusion about what was causing the problem.



[TOPIC: post.html]
#7

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,328 posts
  • Corona Staff

I'm not sure how well this will help illustrate this from the way I understand it.  But lets start with groups:

group.png

 

In this example we have a display.newGroup() which by default has its origin at 0,0.  Positive coordinates of objects on the screen are in the white area.  Without using anchor children, if I move the group's origin to say 100, 100 then every thing shifts down and to the right by 100 pixels.   This is what we are used to.  Now if you rotate the group, the blocks in this case would orbit the group's new origin.  

 

Now add anchorChildren = true:

group2.png

 

In this case, the group will have a constrained width and height and it's X, Y by default now are centered in that imaginary box.  Since it's a box it can now have anchor points, which groups don't have (since they by definition don't have a left, right, top or bottom edge).    Now if you move it by it's X, Y, its the center of the faux-block.  If you rotate it, it's going to rotate around the anchor point of the box.

 

You can determine the bounding box of a group (and what an anchored group becomes) using object.contentBounds (http://docs.coronalabs.com/api/type/DisplayObject/contentBounds.html)

 

Not two answer your original questions the best that I can:

 

1.  You have this partially right.  The group gets bounds and therefore has a center that can be rotated around and moved relative to that center point.  It's the same as drawing things at negative locations relative to the group's origin then moving the group's X, Y.  By  letting you have boundaries, you can now have anchor points if you don't want to use the center of the group (the X, Y) above.

 

2. Groups inside of Groups, I don't know.  Let me see if I can get an engineer to discuss this further.

 

Rob



[TOPIC: post.html]
#8

Tom

[GLOBAL: userInfoPane.html]
Tom
  • Moderator

  • 1,480 posts
  • Corona Staff

The anchorChildren property was never intended to be used with groups. It was added afterwards as a way to bring back some Graphics 1.0 compatibility where you can set a reference point for groups. Normally groups are dynamic and the bounding box is determined by the children within the group so there is no concept of Left, Right, Bottom or Top. By default, there are no anchor points for groups. Setting anchorChildren true enables anchor points for the group. Setting this property on groups within groups can be confusing and not recommended. In fact you shouldn't be setting anchorChildren true on groups unless it's the only way to achieve what you want.
 
The real purpose of the anchorChildren property is to determine what happens when you change the anchor point of a normal display object (e.g., non-group). By default, moving an anchor point shifts the object's position. By setting anchorChildren to true, the object position will not move when the anchor point is changed. This mimics the behavior or changing the setReferencePoint in Graphics 1.0.
 
Containers are really groups with a mask and therefore have a bounding box. anchorChildren is set to true by default (for containers only).


[TOPIC: post.html]
#9

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

Tom, we are using nested groups extensively in G1.0 with fantastic applications especially to create a kind of parented animation. Think of wheel group rotating, car body group moving up and down, all children of one car group which is moving across the screen. Are you saying this is no longer possible in G2.0? Why can't anchorChildren be true for groups within groups?



[TOPIC: post.html]
#10

Tom

[GLOBAL: userInfoPane.html]
Tom
  • Moderator

  • 1,480 posts
  • Corona Staff

I never said you can't set anchorChildren on groups within groups, but don't expect it to work the same way as Graphics 1.0 and nested groups.



[TOPIC: post.html]
#11

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

No, anchors don't work the same as reference points that's for sure. But once anchors are being used as designed there's no reason they shouldn't work theoretically. Are you talking about unpredictability of performance by G2 when it comes to nested anchors, in other words, bugs? It is exasperating that group anchors/reference points have de-evolve in G2 that they require so much more effort and code to achieve something done so effortlessly in G1.

[TOPIC: post.html]
#12

bjsorrentino

[GLOBAL: userInfoPane.html]
bjsorrentino
  • Veteran

  • 8,506 posts
  • Corona SDK

Hi @kilopop,

Have you read our guide on groups and anchorChildren? This is the most clear guide available (or at least I haven't seen anything more descriptive). It should illustrate exactly what is happening when you use anchorChildren on groups.

 

http://docs.coronalabs.com/guide/graphics/group.html

 

Take care,

Brent



[TOPIC: post.html]
#13

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

Thanks Brent, I understand how they work. Clearly they work differently to reference points. But the point I'm asking is whether there's something we haven't been told yet about the stability of anchor points, as hinted by Tom posting stuff like:

 

"Setting anchorChildren true enables anchor points for the group. Setting
this property on groups within groups can be confusing and not
recommended. In fact you shouldn't be setting anchorChildren true on
groups unless it's the only way to achieve what you want."

 

There was never a problem with reference points when it came to nested groups - you could nest til your heart was content. Now it's clearly become more difficult to do. So my questions would be:

 

Is Tom saying it is still possible and robust to nest groups in G2 if not a lot more complicated than it used to be in G1? Or is he saying nested groups are not encouraged because goodness knows if G2 can actually handle it i.e. possible instability of the api?



[TOPIC: post.html]
#14

bjsorrentino

[GLOBAL: userInfoPane.html]
bjsorrentino
  • Veteran

  • 8,506 posts
  • Corona SDK

Hi @kilopop,

I'm not aware of any "instability" issues. For nesting, I guess I'd have to see what you're aiming to accomplish from an animation standpoint.

 

Brent



[TOPIC: post.html]
#15

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

Just normal animation aims, nothing G1 couldn't handle in its sleep. Will report back if something isn't working as it should. But the reality is that G2 now requires more layers of code to achieve the exact same thing as G1 did in reference to nested groups. Struggling to see how this is an improvement to the api.



[TOPIC: post.html]
#16

bjsorrentino

[GLOBAL: userInfoPane.html]
bjsorrentino
  • Veteran

  • 8,506 posts
  • Corona SDK

Hi @kilopop,

If you have a test example, please share. I haven't seen much yet that anchor points can't handle, and one vast improvement over reference points is the ability to set the anchor around any point on the object, not just 8 edge points and a center point.

 

Brent



[TOPIC: post.html]
#17

Tom

[GLOBAL: userInfoPane.html]
Tom
  • Moderator

  • 1,480 posts
  • Corona Staff

My point was nested groups with "anchorChildren = true" was never intended to be supported and is not tested. The property was added to support containers, which are a form of groups. Graphics 2.0 groups are not 100% compatible with Graphics 1.0 groups.



[TOPIC: post.html]
#18

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

You're saying effectively that you can't see any application for requiring anchors in a group and the implementation of it now in Corona is an after thought addition, the use of which leading to unpredictable outcomes?

 

But you have to allow for anchors in groups, otherwise how can you perform animation on groups that need to define where the anchor is such as rotation, scale and move (to exact coordinates rather than self.x=self.x+z)?

 

What is your suggestion for animating groups without using anchors?



[TOPIC: post.html]
#19

bjsorrentino

[GLOBAL: userInfoPane.html]
bjsorrentino
  • Veteran

  • 8,506 posts
  • Corona SDK

I didn't state that I can't see any need for using anchors on groups. It clearly does work as shown in the groups guide. Where are you encountering issues that can't seemingly be overcome?



[TOPIC: post.html]
#20

Tom

[GLOBAL: userInfoPane.html]
Tom
  • Moderator

  • 1,480 posts
  • Corona Staff

Groups with anchorPoints is allowed and was designed into Graphics 2.0. Setting the anchorChildren property for nested groups was not intended and not recommended. I never said groups with anchorPoints was an afterthought. 



[TOPIC: post.html]
#21

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

Ok sure, more specifically you are saying nested Groups were never intended to be supported. That statement in itself is very concerning as it sounds like you're starting to limit who uses Corona and how.

 

Here's a quick test of nested groups. It creates a simple vehicle with wheels rotating which are a part of a vehicle group which is moving across the screen, landscape, h_1536, w_2048. Of course there are plenty of ways to make this car and move it, that's not the point of this comparison but rather to show how nested groups are not working. Firstly G1:

 

-----------------------------------------------------------------------------------------
--
-- main.lua
--
-----------------------------------------------------------------------------------------

local gp_carBody = display.newGroup()
local gp_wheel1 = display.newGroup()
local gp_wheel2 = display.newGroup()
local gp_car = display.newGroup()

-- body positioning
local body = display.newRect( 1098, 808, 748, 228 ) 
body:setFillColor( 255, 255, 255 )

-- top positioning
local top = display.newRect( 1315, 628, 276, 260 )
top:setFillColor( 255, 255, 255 )

-- tyre1 positioning
local tyre1 = display.newCircle( 1265, 1041, 75 )
tyre1:setFillColor( 3, 145, 222 )

-- cap1 positioning
local cap1 = display.newCircle( 1265, 1041, 53 )
cap1:setFillColor( 255, 255, 255 )

-- tyre2 positioning
local tyre2 = display.newCircle( 1689, 1041, 75 )
tyre2:setFillColor( 3, 145, 222 )

-- cap2 positioning
local cap2 = display.newCircle( 1689, 1041, 53 )
cap2:setFillColor( 255, 255, 255 )

-- Organise Groups

gp_carBody:insert(body)
gp_carBody:insert(top)

gp_wheel1:insert(tyre1)
gp_wheel1:insert(cap1)
gp_wheel1:setReferencePoint( display.CenterReferencePoint )
gp_wheel1.xScale = 0.5

gp_wheel2:insert(tyre2)
gp_wheel2:insert(cap2)
gp_wheel2:setReferencePoint( display.CenterReferencePoint )
gp_wheel2.yScale = 0.5

gp_car:insert(gp_carBody)
gp_car:insert(gp_wheel1)
gp_car:insert(gp_wheel2)

-- animation

transition.to (gp_car, { time = 4000, x = -1000 } )
transition.to (gp_wheel1, { time = 500, rotation = -360,  iterations=8} )
transition.to (gp_wheel2, { time = 500, rotation = -360,  iterations=8} )

The body of the vehicle stays still in the Y axis as the group moves across the X.

Now here is the G2 version. Firstly, it requires 9 more lines of code to achieve the same thing. We have to set anchor is true, then work out where the object would be on the screen and add that. Working out where the group is takes calculations of the height, width, average x and y of the group's contents and do math depending on where you want the anchor. Still more lines would be required if we suddenly needed to change the anchor mid way through to stop the groups contents from snapping to a new position. Anyway, here's G2 version:

 

-----------------------------------------------------------------------------------------
--
-- main.lua
--
-----------------------------------------------------------------------------------------

local gp_carBody = display.newGroup()
local gp_wheel1 = display.newGroup()
local gp_wheel2 = display.newGroup()
local gp_car = display.newGroup()

gp_wheel1.anchorChildren = true
gp_wheel2.anchorChildren = true
gp_car.anchorChildren = true

-- body positioning
local body = display.newRect( 1472, 922, 748, 228 ) 
body:setFillColor( 255/255, 255/255, 255/255 )

-- top positioning
local top = display.newRect( 1454, 758, 276, 260 )
top:setFillColor( 255/255, 255/255, 255/255 )

-- tyre1 positioning
local tyre1 = display.newCircle( 1265, 1041, 75 )
tyre1:setFillColor( 3/255, 145/255, 222/255 )

-- cap1 positioning
local cap1 = display.newCircle( 1265, 1041, 53 )
cap1:setFillColor( 255/255, 255/255, 255/255 )

-- tyre2 positioning
local tyre2 = display.newCircle( 1689, 1041, 75 )
tyre2:setFillColor( 3/255, 145/255, 222/255 )

-- cap2 positioning
local cap2 = display.newCircle( 1689, 1041, 53 )
cap2:setFillColor( 255/255, 255/255, 255/255 )

-- Organise Groups

gp_carBody:insert(body)
gp_carBody:insert(top)

gp_wheel1:insert(tyre1)
gp_wheel1:insert(cap1)
gp_wheel1.anchorX, gp_wheel1.anchorY = 0.5, 0.5
gp_wheel1.x, gp_wheel1.y = 1265, 1041
gp_wheel1.xScale = 0.5

gp_wheel2:insert(tyre2)
gp_wheel2:insert(cap2)
gp_wheel2.anchorX, gp_wheel2.anchorY = 0.5, 0.5
gp_wheel2.x, gp_wheel2.y = 1689, 1041
gp_wheel2.xScale = 0.5

gp_car:insert(gp_carBody)
gp_car:insert(gp_wheel1)
gp_car:insert(gp_wheel2)
gp_car.anchorX, gp_car.anchorY = 0.5, 0.5
gp_car.x, gp_car.y = 1472, 922

-- animation

transition.to (gp_car, { time = 4000, x = -200 } )
transition.to (gp_wheel1, { time = 500, rotation = -360,  iterations=8} )
transition.to (gp_wheel2, { time = 500, rotation = -360,  iterations=8} )

Now if you run this, the car is suddenly jiggling up and down in the y axis. The reason? Because the wheels are rotating, their height is changing which effects the overall height of the group gp_car which shifts up and down to remain anchored to the BottomCenter.

 

Now, if we were to anchor the gp_carBody which is nested in the gp_car then it's crazy clown fun time. The car comes completely to bits.. Try it by adding:

 

gp_carBody.anchorChildren = true
gp_carBody.anchorX, gp_carBody.anchorY = 0.5, 1
gp_carBody.x, gp_carBody.y = 1472, 1000
transition.to (gp_carBody, { time = 250, y = -50, iterations=16  } )
 

 

So you're not wrong when you said that nested groups are no longer possible in Corona, or at least highly restricted in their application. This is a big shame because as an animator using Corona in G1 has been a joy and has led on to some great results. Things like walk cycles of characters rotating limbs and moving up and down while also moving across. Also squash and stretch where the anchor needs to change its position.

 

Having to add all this extra code to achieve only a small part of what you could do with reference points doesn't seem like an evolution of the software especially since it actually no longer works no matter how much code you have to write..



[TOPIC: post.html]
#22

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

I think you've found a bug.

Even if you comment out the xScale property of the wheels so they're round, the car still bounces when the wheels are rotating.

If you also comment out the rotation transitions, the car remains stable.



[TOPIC: post.html]
#23

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

Oh is that the case Ingemar? I didn't try that. But you're right, there must be something deeply wrong if it's still jiggling around.

Also if you run G1 code in the latest public release simulator with v1 compatibility mode set then nested groups still have issues. So there must be something going on if it still manages to occur in this case..

 

What next, log this bug?



[TOPIC: post.html]
#24

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

Your sample code is a good example of the problem.

If you leave the wheels round, I think it's a good idea to log that bug.

 

I thought I had anchor points down, but as I'm playing around with your code I can't wrap my head around some things I see.

There are weird things happening that I don't understand. I'm also playing around with your sample adding containers instead of groups, but I'm struggling to get things the way I want them.

 

One thing that I totally agree on is that if V1 compatibility mode is activated, things should work exactly as they did in V1 without modifications, otherwise what's the point?



[TOPIC: post.html]
#25

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

I got it to work ... without anchorChildren!

 

The anchorChildren property was causing all the problems. After removing that and adjusting the coordinates of the objects it looks OK and there are no more jitters while the wheels are turning.

I even implemented your bouncing "crazy clown fun time" feature... without the crazy clown  :ph34r:.

 

Using anchorChildren can cause all sorts of unpredictable issues. This example has taught me that I might have to re-think my group positioning strategy as I'm also using anchorChildren=true in many places (however without any issues so far).

By rethinking the positioning in "G2.0 terms" it might just be possible to get everything working, however it *will* require an extensive re-write of the code to do so.

 

Remember that groups have no settable anchors. It uses the common anchor among the children.

You *can* use anchors among the children though to help with the internal positioning.

 

I guess that the final chapter in this story hasn't been written yet, but here's the code:

--
-- main.lua
--

display.setStatusBar(display.HiddenStatusBar)

local gp_carBody = display.newGroup()
local gp_wheel1 = display.newGroup()
local gp_wheel2 = display.newGroup()
local gp_car = display.newGroup()

-- body positioning
local body = display.newRect(0, 0, 748, 228 )
body.anchorY = 0;
body:setFillColor(0.9)

-- top positioning
local top = display.newRect(0, 0, 276, 260 )
top.anchorY = 1;
top:setFillColor(1)

-- tyre1 positioning
local tyre1 = display.newCircle(0, 0, 75 )
tyre1:setFillColor( 3/255, 145/255, 222/255 )

-- cap1 positioning
local cap1 = display.newCircle(0, 0,53 )
cap1:setFillColor( 255/255, 255/255, 255/255 )

-- tyre2 positioning
local tyre2 = display.newCircle(0, 0, 75)
tyre2:setFillColor( 3/255, 145/255, 222/255 )

-- cap2 positioning
local cap2 = display.newCircle(0, 0, 53 )
cap2:setFillColor( 255/255, 255/255, 255/255 )

-- Organise Groups
gp_carBody:insert(body)
gp_carBody:insert(top)

gp_wheel1:insert(tyre1)
gp_wheel1:insert(cap1)
gp_wheel1.x, gp_wheel1.y = gp_carBody.x - 200, gp_carBody.height / 2
gp_wheel1.xScale = 0.5

gp_wheel2:insert(tyre2)
gp_wheel2:insert(cap2)
gp_wheel2.x, gp_wheel2.y = gp_carBody.x + 200, gp_carBody.height / 2
gp_wheel2.yScale = 0.5

gp_car:insert(gp_carBody)
gp_car:insert(gp_wheel1)
gp_car:insert(gp_wheel2)
gp_car.x, gp_car.y = 1000, 600

-- animation
transition.to (gp_carBody, {time=250, y=-25, iterations=16, transition=easing.continuousLoop} );
transition.to (gp_car, { time = 4000, x = -200} )
transition.to (gp_wheel1, { time = 500, rotation = -360,  iterations=8} )
transition.to (gp_wheel2, { time = 500, rotation = -360,  iterations=8} )




[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]