gfx2-iconOne of the foundational concepts of Corona SDK is display groups. These allow developers to organize different display objects like images, vector shapes, and text into groups and then manipulate the group as a whole.

Objects in the group are layered similar to the way layers are stacked in image editing tools like Photoshop. That is, the first object inserted in the group resides on the bottom. As new objects are added, they stack on top, obscuring objects underneath. This is known as the painter’s method.

In Corona, display groups are “boundless” with nearly infinite capacity, yet they do have one limitation. If you want a group to span just a 200×200 pixel region, the typical solution is to mask the entire group. However, this requires that you to create a separate mask image for each size and purpose. In essence, this is a challenge for developers who want to implement dynamically-sized masked regions.

Introducing Containers

To help address this challenge, Corona’s Graphics 2.0 engine introduces a new and powerful feature: containers. Basically, containers can be considered self-masking groups. That is, you can set a width/height for the container and only child display objects (or any portion of those objects) inside the container bounds will be visible. In addition, the width and height can be changed dynamically, allowing you to expand or shrink the bounding box of the container.

To create a container, simply call display.newContainer() passing it the width and height:

local myContainer = display.newContainer( 300, 200 )
myContainer.x = display.contentCenterX 
myContainer.y = display.contentCenterY

Once created, adding display objects to a container is identical to adding objects to groups:

local gradient = { type="gradient", color1={1,0,0}, color2={0.2,0,0}, direction="down" } 

local bg = display.newRect( 0, 0, 1000, 1000 )
bg.fill = gradient
myContainer:insert( bg )
local myText = display.newText( "Hello World!", 0, 0, native.systemFont, 20 )
myContainer:insert( myText )

In this example, we first create a big rectangle and fill it with a gradient. This exhibits how the gradient rectangle, larger than the container, is “clipped” by the container bounds.

Next we add a text object. If you run this code, you may be surprised to notice that myText appears centered in the screen, even though it was created at the coordinates 0,0. This is because of a few important differences in Graphics 2.0.

Center Anchor Default

In Graphics 2.0, all display objects are now drawn, by default, relative to their center, even when you specify an x and y coordinate in the function call. For comparison, examine this code:

display.newText( "Some string", 0, 0, native.systemFont, 24 )

In the previous graphics engine, this would have drawn the text “Hello World!” with its top-left corner at the top-left point of the screen (0,0). In Graphics 2.0, the center of the text object will be drawn at 0,0.

Containers and Anchor Points

When inserting objects into a standard display group, the group’s origin is at 0,0. Then, if you move the group, the text moves relative to the group’s new origin.

In containers, the clip bounds is aligned relative to the container’s origin based on the anchor values (if you missed the tutorial on anchors, please access it here). By default, the container’s bounding box is centered (anchored) around the container’s origin.

In our example above, the text is centered in the container because its x and y is 0,0. So if you want to position the text above or left of center, you must position it at negative x and y coordinates.

Unlike groups, containers have the .anchorChildren property set to true. If you change the container’s anchor values, the children move along with the clipping bounds. However, if you want containers to behave more like groups in this respect, set .anchorChildren to false. This ensures that only the clipping bounds are affected by the anchor. For more information, see the anchor points tutorial.

Precautions

Internally, containers use masks. Be careful in this regard, because devices have a limited number of masks that can be “stacked” together (nested). The maximum is 3 but may be less. Thus, you should avoid putting containers inside other containers, because if the limit is exceeded, container clipping will fail.

This limit does not apply to the basic number of containers/masks used, but rather the nested number of items that occupy a texture unit.

In Summary

If you’ve ever used a rectangular mask to constrain a group’s content, containers are a powerful and flexible alternative. To get started, please read the documentation and download one of the sample projects: Container, ContainerAlignment, and ContainerAnchorChildren.

  1. Thanks for the tutorial Rob! I’ll be finishing my current project using graphics 1.0 so it’ll have to wait, but I’ll make sure to check up on this later!

  2. these links:
    ……one of the sample projects: Container, ContainerAlignment, and ContainerAnchorChildren.
    above are now dead…..

    Also, please clarify whether groups in G2.0 have the same (.5) default anchor as Containers, or if they still are an exception, defaulting to (0,0)

    • These samples are now located with the other SampleCode samples in the Graphics-Premium folder.

      Groups have anchor points at 0.5, 0.5, but since Groups have no height/width, it’s Origin defaults to 0, 0. This gives it an illusion that 0, 0 is it’s top left corner, but the group can have items positioned at negative values.

      Rob

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>