How It Works

This code isn't very complex. However, there a few things it does that are worth discussing so you can use the same ideas in your code and projects.

Custom Font

To get the TFT candy heart to look like an actual candy heart, a custom font is used. There's a guide about this here:

The font used for the TFT Candy Hearts is this one:

which we've already converted for use with CircuitPython and this project. The font file will be included along with the code when you download the Project Zip. See the Code pages for details about downloading it and copying it to your board.

Text Positioning

Thanks to a recent update to the The CircuitPython Display Text library, you can now change the anchor point used to locate the text label. You do so by using the anchor_point property of the label and giving it an (x, y) tuple, like this:

Download: file
label.anchor_point = (0.1, 0.8)

The values range from 0 to 1 with x being the horizontal and y being the vertical. The origin is in the upper left corner. A value of 0 is at the origin. A value of 1 is all the way to the right/down.

Here are some example locations:

You can then set the position of the label on the display using the anchored_position property and also specifying an (x, y) tuple. But this time, the values are actual screen coordinates in pixels, like this:

Download: file
label.anchored_position = (120, 85)

The candy hearts code uses two labels, one for each line of text. The x position is simply half the screen width, 240 / 2 = 120, so that it is centered. The y positions were determined by trial and error. Just came up with values that looked about right.

The end result is something like this:

If you want to tweak the position of the messages, you can change these lines of code:

Download: file
# update location for new text bounds
line1.anchored_position = (120, 85)
line2.anchored_position = (120, 175)

Changing Heart Color

The way the heart color is changed is kind of interesting. Instead of having separate bitmap files for each color, the palette is altered directly. For a review of how bitmaps and palettes work in CircuitPython displayio, see here:

But for quick reference, we copy the important illustration here:

It is the palette that defines the colors that are used to render the bitmap on the screen. And you can change any of the palette entries anytime you want by doing something like:

Download: file
palette[1] = 0x0000FF # blue

This would set the second entry (index 1) of the palette to the color blue. Any pixel of the bitmap using that palette entry would then get rendered as blue. But then you can do:

Download: file
palette[1] = 0x00FF00 # green

and those same pixels would now become green.

This trick is used for the heart. The actual bitmap is only two colors - black and white:

The black pixels are left alone so the background is always black. But you could change that if you want. The candy heart code only changes the white entry of the bitmap. The actual colors are defined by you at the top of the code. The choice function from the random library is used to select one of these at random. And then the palette entry for white is set to it:

Download: file
palette[1] = choice(HEART_COLORS)

Then whatever used to be white becomes the new color. And when it happens again, the color is replaced by a new random color. And so on.

This guide was first published on Feb 09, 2020. It was last updated on Feb 09, 2020.
This page (How It Works) was last updated on Jul 07, 2020.