Tutorial: Partially filling an object

Tutorial: Partially filling an object

In designing your UI (User Interface), imagine that you want to include an element like a health bar or a thermometer that can be partially filled with a solid color (or any other image) which represents an “amount” that the element contains.

While Corona provides the pre-packaged ProgressView() widget which may meet this goal, taking it to a more elaborate visual appearance requires some creativity. In this tutorial, we will create a more customized health bar example where a symbol represents the player’s health — this will consist of a hollow outline that can be filled with a color as the player’s health increases or decreases.

Prerequisites

To make this work, you will need three separate images:

  1. An image that is the “empty” outline of the object — aside from the outline, all pixels should be transparent, as represented by the grey checkerboard grid in the example image below.
  2. An image which represents the fully “filled” object (again, all pixels that are not part of the filled image should be transparent).
  3. A basic white mask (including the required black border).

characterimageexample

Using these three elements, the general concept is to place the “filled” image on the screen, then overlay (draw at the exact same place on the screen) the “outline” image. This in itself won’t do anything — merely the outline will overlay the filled image. However, when you create and apply the mask to the bottom layer, you will gain the ability to set the position of that mask and effectively indicate how “full” the object is.

Basic setup

Consider this code:

The first block of code defines the underlying “filled” image (the image completely filled with color). For convenience, we position this object in the center of the content area.

Next, we create a mask (UIMask) using graphics.newMask(). This mask image is solid white except for the required black border around the edges. In this case, since the UI image is 100×200 pixels, the mask consists of a 100×200 area of white plus a 4 pixel black border, resulting in an overall mask image of 108×208. Once created, the mask is applied to the underlying image (filledUI) and positioned at a maskY value of 0 (this position will be important in the next step).

Next, we overlay the “outline” image (outlineUI) on top. This element will simply be used as a frame for the UI object as we adjust the mask position on the underlying filled image.

Controlling the fill

The fill of the UI meter is completely controlled by adjusting the y position of the mask (maskY). In this example, since the object is 200 pixels tall, we can set this value to 100 to set the visual health level at 50%. As a convenience method to calculate the proper position, we can use the following code:

Alternatively, you can achieve an animated fill effect by transitioning the mask’s position. Using a transition on the mask position is very similar to a typical positional transition, except in this case, we transition the maskY property, not the y property of the actual image:

Conclusion

As demonstrated, creating a stylish UI meter is simple and only requires the use of three elements, a simple calculation, and a direct set (or transition) of the underlying object’s mask position. If you wish to experiment with this code, you may copy/save the following images to your system as a basis for testing:

outline filled mask


Tags:
,
Rob Miracle
[email protected]

Rob is the Developer Relations Manager for Corona Labs. Besides being passionate about helping other developers make great games using Corona, he is also enjoys making games in his spare time. Rob has been coding games since 1979 from personal computers to mainframes. He has over 16 years professional experience in the gaming industry.

2 Comments
  • Joe
    Posted at 07:08h, 11 September

    Nice tutorial, thank! This solves my question I had for a long time.
    Hope you can give more tutorials like this to solve some things we see in designing games with Corona.

  • Adi
    Posted at 00:31h, 18 September

    I like this solution. I usually used plain rect to gradually fill meters but this concept allows for more flexible shapes.