Corona SDK Pro Tip of the Day #35
Dynamic masks without display.newContainer()

Masks are extremely useful for building a rich UI or some game elements. However it's use in Corona SDK is somewhat limited. To use a mask we must create a specific PNG file with size equal to masking area.

You can end up with many mask files for all kind of sizes. Wouldn't it be cool if you didn't need all these files? And Corona Labs introduced display.newContainer() which is a group with a resizable mask glued to it. You can change the size of the container and you don't need to use many mask files.

However there is one downside using containers - coordinates x = 0, y = 0 is the center of the container and you can't change it to say the top left corner. So if you rely on the top left positioning of the elements in the container - you have to subtract half width and half height of the container from position of every object inside the container. Sometimes it's very hard to do and the code becomes very hard to follow.

However, recently I found a method how to use dynamic mask on any object (group, image, shape, ...) from a single mask image. The trick is to use the smallest mask file possible, scale it using .maskScaleX and .maskScaleY, and use nearest neighbor texture filtering for the mask so it doesn't become blurry.

If you have a group and you want it to become a container of size wxh, then you would use the following code.

local mask = graphics.newMask('mask.png')  
display.setDefault('magTextureFilter', 'nearest')  
display.setDefault('magTextureFilter', 'linear')  
group.maskScaleX = w * 0.5  
group.maskScaleY = h * 0.5  
group.maskX = group.maskScaleX  
group.maskY = group.maskScaleY  

Not only you gain masks of any size with this method. You can perfom transitions on the mask as well!

Mask image and demo project can be found on GitHub

You may notice that we have to change .maskY along with .maskScaleY when we want to enlrage it, that is because masks don't support anchors. If we had properties like .maskAnchorX and .maskAnchorY, we would only change .maskScaleY and .maskY would stay the same.

I have made a feedback page on that, please go and give your votes for this.

Also you can watch a Corona Geek episode where I describe this method.

Indie Game Developer