# Circuit Playground TFT Gizmo Snow Globe

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/083/459/medium800/lcds___displays_banner.png?1572734121)

Ah, the classic snow globe. That clear orb full of mystery liquid, some sort of flake material, and typically a diorama depicting some scene. Shake it up and watch the snow fall.

In this guide we'll show you how to use a [Circuit Playground Bluefruit](https://www.adafruit.com/product/4333) along with a [TFT Gizmo](https://www.adafruit.com/product/4367) to create a digital version of a snow globe. We'll display customizable snow globe goodness on the TFT. You'll be able to set a custom background, create custom snow flakes, and of course shake to clear the snow globe and start it all over.

All coded in [CircuitPython](https://circuitpython.org/).

Let's get started.

Warning: 

### Circuit Playground Bluefruit - Bluetooth® Low Energy

[Circuit Playground Bluefruit - Bluetooth® Low Energy](https://www.adafruit.com/product/4333)
 **Circuit Playground Bluefruit** is our third board in the Circuit Playground series, another step towards a perfect introduction to electronics and programming. We've taken the popular Circuit Playground Express and made it even better! Now the main chip is an nRF52840...

Out of Stock
[Buy Now](https://www.adafruit.com/product/4333)
[Related Guides to the Product](https://learn.adafruit.com/products/4333/guides)
![shot of a Black woman's neon-green manicured hand holding up a Circuit Playground Bluefruit glowing rainbow LEDs.](https://cdn-shop.adafruit.com/640x480/4333-11.jpg)

### Circuit Playground TFT Gizmo - Bolt-on Display + Audio Amplifier

[Circuit Playground TFT Gizmo - Bolt-on Display + Audio Amplifier](https://www.adafruit.com/product/4367)
Extend and expand your Circuit Playground projects with a bolt on TFT Gizmo that lets you add a lovely color display in a sturdy and reliable fashion. This PCB looks just like a round TFT breakout but has permanently affixed M3 standoffs that act as mechanical and electrical...

In Stock
[Buy Now](https://www.adafruit.com/product/4367)
[Related Guides to the Product](https://learn.adafruit.com/products/4367/guides)
![Hand pressing buttons on circuit playground, then turning over to show TFT gizmo display an image of a friendly robot or snake](https://cdn-shop.adafruit.com/product-videos/640x480/4367-05.jpg)

### DIY Ornament Kit - 6cm Diameter - Perfect for Circuit Playground

[DIY Ornament Kit - 6cm Diameter - Perfect for Circuit Playground](https://www.adafruit.com/product/4036)
Have you put up with mainstream, uninspiring, low-tech tree ornaments for too long? This season why not deck the halls with _codes_ of holly?

This **DIY Ornament Kit** is just the right size (6 cm diameter) for a Circuit Playground Express, 500mAh LiPoly battery, and...

In Stock
[Buy Now](https://www.adafruit.com/product/4036)
[Related Guides to the Product](https://learn.adafruit.com/products/4036/guides)
![6cm Diameter DIY Ornament Kit with Circuit board inside](https://cdn-shop.adafruit.com/640x480/4036-00.jpg)

# Circuit Playground TFT Gizmo Snow Globe

## How It Works

There are three main components to the snow globe:

- The background image
- The flakes
- The snow on the ground

Something like this:

![](https://cdn-learn.adafruit.com/assets/assets/000/083/334/medium800/lcds___displays_globe_items.png?1572557589)

Let's talk about each of these.

## Background

This one is pretty simple. It's just an image or a solid color. There's really nothing for it to do other than just sit there. So there's no more code associated with it other than loading it and showing it.

We'll pretty much just do what is described [here](https://learn.adafruit.com/circuitpython-display-support-using-displayio/display-a-bitmap%20) and then leave it alone.

## Flakes

These are the pretty little snowflakes that come falling out of the sky. We will use little bitmaps to give them shape. We will also allow for a few different fall speeds, so they all don't just fall at the same rate. The other thing that needs to be done is check if they have hit the ground - the current snow level.

To actually make the flakes move, all that needs to be done is change the `y` value of their associated TileGrid. This is a CircuitPython [displayio](https://learn.adafruit.com/circuitpython-display-support-using-displayio/) feature. For more info see [here](https://circuitpython.readthedocs.io/en/latest/shared-bindings/displayio/TileGrid.html) and [here](https://learn.adafruit.com/circuitpython-display-support-using-displayio/tilegrid-and-group). So basically, each flake will be a separate TileGrid, and we will change the `y` value of each to make them fall.

## Snow

This is the snow on the ground. At the beginning, there is no snow on the ground. As the flakes fall and hit the ground, snow will be added in the general area where the flake hit. So this level will grow as more and more flakes fall.

We'll use a displayio [Bitmap](https://learn.adafruit.com/circuitpython-display-support-using-displayio/bitmap-and-palette) to represent the snow. The bitmap size will be the same as the screen size. It will start empty - totally transparent. To "add snow" we will just set individual pixels to the snow color.

# Circuit Playground TFT Gizmo Snow Globe

## Simple Snow Globe

Let's start with a simple version of the snowglobe. This version does not require any additional bitmap files. You can set a background image if you want. But if you don't have one and just want to get up and running, just leave it alone and it will use a solid color.

Here's the code:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/TFT_Gizmo_Snowglobe/snowglobe_simple/code.py

The features you can customize are grouped at the top of the code:

```python
#---| User Config |---------------
BACKGROUND = 0xAA0000              # specify color or background BMP file
NUM_FLAKES = 50                    # total number of snowflakes
SNOW_COLOR = 0xFFFFFF              # snow color
SHAKE_THRESHOLD = 27               # shake sensitivity, lower=more sensitive
#---| User Config |---------------
```

The code comments describe what they do. Here's a summary:

- `BACKGROUND` - the background color **OR** image filename
- `NUM_FLAKES` - the total number of flakes to show
- `SNOW_COLOR` - the color of the snow
- `SHAKE_THRESHOLD` - shake-to-clear sensitivity

For now, just go ahead and try running it as is with the default values. You should get some nice white snow on a red background.

![](https://cdn-learn.adafruit.com/assets/assets/000/083/365/medium800/lcds___displays_ex_red_white.jpg?1572638877)

## Change Colors

Now try changing the `BACKGROUND` and `SNOW_COLOR` values. Change those lines to something like this:

```python
BACKGROUND = 0x00FF00              # specify color or background BMP file
NUM_FLAKES = 50                    # total number of snowflakes
SNOW_COLOR = 0xFF00FF              # snow color
SHAKE_THRESHOLD = 27               # shake sensitivity, lower=more sensitive
```

![](https://cdn-learn.adafruit.com/assets/assets/000/083/366/medium800/lcds___displays_ex_green_yellow.jpg?1572638906)

Hey! Yellow snow! On a green background.

## Change Background

If you specify a bitmap file instead of a color for `BACKGROUND`, it will be loaded and used. For the TFT Gizmo, the file needs to be an indexed BMP file that is 240x240 in size. Here's one you can use to try this out:

[blinka_dark.bmp](https://cdn-learn.adafruit.com/assets/assets/000/083/353/original/blinka_dark.bmp?1572629459)
Download that file and copy it to your **CIRCUITPY** folder. Then change the background setting line to:

```python
BACKGROUND = "/blinka_dark.bmp"              # specify color or background BMP file
```

And change the snow color back to white:

```python
SNOW_COLOR = 0xFFFFFF              # snow color
```

Run that and you should end up with snow falling over a Blinka background.

![](https://cdn-learn.adafruit.com/assets/assets/000/083/367/medium800/lcds___displays_ex_blinka.jpg?1572638928)

## Change Flakes

You can do a minor amount of flake shape customization. We'll provide a fancier version of the code next that will really let you do this. But if you want, you can play around with these lines of code:

```python
FLAKES = (
    0, 0, 0, 0,    0, 0, 0, 0,    1, 1, 1, 1,
    0, 0, 0, 0,    1, 1, 1, 0,    1, 1, 1, 1,
    0, 1, 1, 0,    1, 1, 1, 0,    1, 1, 1, 1,
    0, 1, 1, 0,    1, 1, 1, 0,    1, 1, 1, 1,
)
```

See how there are 3 separate 4x4 grids? Those are the flakes, which are each 4 pixels wide by 4 pixels high. A `0` ends up being transparent. A `1` ends up being the snow color. So you can edit those if you want to change the flake shape. But with only 4x4 pixels to work with, it's pretty minimal customization.

## Shake To Clear

Don't forget to also try shaking the board to "clear" the snow globe. This will erase all of the accumulated snow and reset all of the snowflakes back to the top. Go ahead - shake it like a polaroid!

# Circuit Playground TFT Gizmo Snow Globe

## Fancy Snow Globe

OK, let's get fancy with those flakes. Allowing for custom flakes is a perfect use of creating a "sprite sheet" to hold the flake shapes, as discussed [here](https://learn.adafruit.com/circuitpython-display-support-using-displayio/sprite-sheet).

This comes at the cost of requiring you to actually create this sprite sheet. You'll also need to modify a few lines of code to provide some info about the sprite sheet layout. But with this feature, along with a settable background image, you can really have fun customizing your snow globe. We'll provide a few examples to get you started.

Here's the fancy version of the snow globe code:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/TFT_Gizmo_Snowglobe/snowglobe_fancy/code.py

As you can see, there are more items in the customization section:

```python
#---| User Config |---------------
BACKGROUND = "/blinka_dark.bmp"    # specify color or background BMP file

NUM_FLAKES = 50                    # total number of snowflakes
FLAKE_SHEET = "/flakes_sheet.bmp"  # flake sprite sheet
FLAKE_WIDTH = 4                    # sprite width
FLAKE_HEIGHT = 4                   # sprite height
FLAKE_TRAN_COLOR = 0x000000        # transparency color

SNOW_COLOR = 0xFFFFFF              # snow color

SHAKE_THRESHOLD = 27               # shake sensitivity, lower=more sensitive
#---| User Config |---------------
```

Most of these are the same as the simple version in the previous section. The new ones are for specifying a flake sprite sheet. They are:

- `FLAKE_SHEET` - the BMP file containing the flake sprites
- `FLAKE_WIDTH` - the width of each sprite
- `FLAKE_HEIGHT` - the height of each sprite
- `FLAKE_TRAN_COLOR` - the color to use as transparency

For `FLAKE_TRAN_COLOR`, it's best to just pick something simple when creating your sprite sheet bitmap. Don't use one of the colors in the flake itself, since then it wouldn't show up.

The two that are probably the most confusing are `FLAKE_WIDTH` and `FLAKE_HEIGHT`. You can think of these as the **width** and **height** of each of your flakes. These should be the same for each flake. It's not the total width and height of your flake sheet - just the sprites themselves. For a more in depth discussion see [here](https://learn.adafruit.com/circuitpython-display-support-using-displayio/tilegrid-and-group) and [here](https://learn.adafruit.com/circuitpython-display-support-using-displayio/sprite-sheet).

## Background Image

To start out, the code is reusing the background image from the previous section of the guide. Download it from the link there. Be sure to have the file **blinka\_dark.bmp** in your **CIRCUITPY** folder.

## Simple Snowglobe Redux

Let's start by simply recreating the same flakes from the previous section, but this time by using a sprite sheet. Here's the file:

[flakes_sheet.bmp](https://cdn-learn.adafruit.com/assets/assets/000/083/355/original/flakes_sheet.bmp?1572633406)
Download that and copy it to your **CIRCUITPY** folder.

If you open it in an image viewer, you won't see much since it's so small. But zoomed in, it looks something like this:

![](https://cdn-learn.adafruit.com/assets/assets/000/083/354/medium800/lcds___displays_flake_sheet.png?1572633392)

The border and grids have been added for reference. They aren't part of the actual file. You can see how there are 3 different 4x4 bitmaps. We need to tell the code this, which is what these lines do:

```python
FLAKE_WIDTH = 4                    # sprite width
FLAKE_HEIGHT = 4                   # sprite height
```

With the background ( **blinka\_dark.bmp** ) and flake sprite sheet ( **flake\_sheet.bmp** ) files copied to your **CIRCUITPY** folder, you can try running the code above. You should get the same as before - a Blinka background with simple white snow flakes.

![](https://cdn-learn.adafruit.com/assets/assets/000/083/371/medium800/lcds___displays_ex_blinka.jpg?1572643902)

Now let's try something different.

## Who Watches The...Squids?

This example better shows how you can customize the snow globe. Hmmm. What else can we make fall from the sky. How about squids? Sure. And with a background that matches the reference. Grab these two files:

[watchmen_bg.bmp](https://cdn-learn.adafruit.com/assets/assets/000/083/359/original/watchmen_bg.bmp?1572635437)
[squid_sheet_16.bmp](https://cdn-learn.adafruit.com/assets/assets/000/083/358/original/squid_sheet_16.bmp?1572635429)
and save to your **CIRCUITPY** folder.

Then, change the customization settings to this:

```python
#---| User Config |---------------
BACKGROUND = "/watchmen_bg.bmp"    # specify color or background BMP file

NUM_FLAKES = 20                    # total number of snowflakes
FLAKE_SHEET = "/squid_sheet_16.bmp"  # flake sprite sheet
FLAKE_WIDTH = 16                   # sprite width
FLAKE_HEIGHT = 16                  # sprite height
FLAKE_TRAN_COLOR = 0x000000        # transparency color

SNOW_COLOR = 0x279ED5              # snow color

SHAKE_THRESHOLD = 27               # shake sensitivity, lower=more sensitive
#---| User Config |---------------
```

The background image is just another BMP file. Other than that, nothing new.

The sprite sheet is pretty different though. The flakes are larger - 16 x 16. They also contain multiple colors. Zoomed in, it looks something like this:

![](https://cdn-learn.adafruit.com/assets/assets/000/083/357/medium800/lcds___displays_squid_sheet.png?1572635420)

The total number of flakes is reduced a bit, since these are larger flakes. And to make the snow match the squids, it is set to a blue-ish color.

With everything copied over and the other changes in place, run the code again and you should get:

![](https://cdn-learn.adafruit.com/assets/assets/000/083/368/medium800/lcds___displays_ex_watchmen.jpg?1572638974)

Falling squids!

## Have Fun!

Have fun with this flake customization feature. Like maybe have cat and dog flakes? Or maybe frogs? Falling hearts might be nice. Or just fancier snow flakes. Up to you.

What else can fall from the sky? Here's one more for you. But you'll have to load these up to see...

[wg_bg.bmp](https://cdn-learn.adafruit.com/assets/assets/000/083/363/original/wg_bg.bmp?1572636811)
[wg_sheet.bmp](https://cdn-learn.adafruit.com/assets/assets/000/083/364/original/wg_sheet.bmp?1572636819)
```python
#---| User Config |---------------
BACKGROUND = "/wg_bg.bmp"    # specify color or background BMP file

NUM_FLAKES = 20                    # total number of snowflakes
FLAKE_SHEET = "/wg_sheet.bmp"  # flake sprite sheet
FLAKE_WIDTH = 20                   # sprite width
FLAKE_HEIGHT = 20                  # sprite height
FLAKE_TRAN_COLOR = 0x000000        # transparency color

SNOW_COLOR = 0xFF00FF              # snow color

SHAKE_THRESHOLD = 27               # shake sensitivity, lower=more sensitive
#---| User Config |---------------
```

# Circuit Playground TFT Gizmo Snow Globe

## More Details

## Making Sprite Sheets

The main key is to save your files as indexed bitmap image files. Then they can be loaded using the [CircuitPython Image Load](https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad) library. Exactly how you do this will depend on what software you are using. The sprite sheets in this guide were created using [GIMP](https://www.gimp.org/). The general process went something like:

- Create new image width x height pixels
- Use 1 pixel pencil tool to draw sprites
- Save as .xcf file for future edits
- When ready to export:
  - Image -\> Mode -\> Indexed
  - File -\> Export As...
  - specify filename with .bmp extension

Info: 

## Flake Fall Speed

So how were different flake fall speeds implemented? Well, pretty simply. The speed is based on the flake index. It comes down to this one line of code (from the fancy version):

```python
flake_pos[i] += 1 - flake[0] / NUM_SPRITES
```

The first flake falls the fastest. The last flake falls the slowest. That's why the various flake examples arranged the flakes from smallest to largest.

Since the `y` location is an integer value, a separate float value is used to allow for floating point math. That is what gets stored in `flake_pos`. This is simply changed to an integer when it comes time to set the flake position:

```python
flake.y = int(flake_pos[i])
```

A fancier way to do this might be to allow for setting custom fall speeds for each flake. But that would require an additional storage mechanism and even more work to manually set up for each flake sprite sheet.

Another idea might be to somehow "weigh" the flake sprite, like how many non-transparent pixels it contains. And then base fall speed on that.

## Animated Flakes?

Sure. Why not? That would be pretty cool. This could be done. Maybe in a future version.

## Snow Accumulation

It's pretty easy to know when a flake hits the ground. But then what? How do we "add" snow to the currently accumulated snow. The simplest would be to just blindly add a few pixels around where the flake fell. However, this can lead to a "spikey" profile to the snow, which doesn't look very natural.

The current version of the code tries to deal with this, but in a pretty simple way. It does a local steepness check based on the surrounding snow and will only add pixels if it is currently not too steep. This works for the most part, but does lead to somewhat unnatural looking edge effects.

It'd be nice if this were fancier. Another maybe-in-the-future mod. Maybe an avalanche simulator?

## Layering in displayio

This project is a good example of how multiple `TileGrids` and `Groups` can be used to create layered effects and animation. The background image and the snow on the ground are just a single `TileGrid` that fills the entire display. The flakes are more interesting. Each flake is a `TileGrid` and is only as big as the flake itself. These are all added to the same `Group`. All three of these elements, background (`TileGrid`), snow (`TileGrid`), and flakes (`Group` of `TileGrid`s), are then added to the main `Group` which is shown on the display. As such, the ordering matters in these lines of code:

```python
# Add everything to display
splash = displayio.Group()
splash.append(background)
splash.append(flakes)
splash.append(snow)
display.show(splash)
```


## Featured Products

### Circuit Playground TFT Gizmo - Bolt-on Display + Audio Amplifier

[Circuit Playground TFT Gizmo - Bolt-on Display + Audio Amplifier](https://www.adafruit.com/product/4367)
Extend and expand your Circuit Playground projects with a bolt on TFT Gizmo that lets you add a lovely color display in a sturdy and reliable fashion. This PCB looks just like a round TFT breakout but has permanently affixed M3 standoffs that act as mechanical and electrical...

In Stock
[Buy Now](https://www.adafruit.com/product/4367)
[Related Guides to the Product](https://learn.adafruit.com/products/4367/guides)
### Circuit Playground Bluefruit - Bluetooth® Low Energy

[Circuit Playground Bluefruit - Bluetooth® Low Energy](https://www.adafruit.com/product/4333)
 **Circuit Playground Bluefruit** is our third board in the Circuit Playground series, another step towards a perfect introduction to electronics and programming. We've taken the popular Circuit Playground Express and made it even better! Now the main chip is an nRF52840...

Out of Stock
[Buy Now](https://www.adafruit.com/product/4333)
[Related Guides to the Product](https://learn.adafruit.com/products/4333/guides)
### Adafruit Circuit Playground Bluefruit Express Starter Kit

[Adafruit Circuit Playground Bluefruit Express Starter Kit](https://www.adafruit.com/product/4504)
If you missed out on ADABOX 014, its not too late for you to pick up the parts necessary to build many of the projects! This kit pack doesn't come with tissue paper or the nifty extras, but it does have all the electronic goodies you need  
  
This project pack features...

Out of Stock
[Buy Now](https://www.adafruit.com/product/4504)
[Related Guides to the Product](https://learn.adafruit.com/products/4504/guides)

## Related Guides

- [Adafruit Circuit Playground Bluefruit](https://learn.adafruit.com/adafruit-circuit-playground-bluefruit.md)
- [Adafruit Circuit Playground TFT Gizmo](https://learn.adafruit.com/adafruit-tft-gizmo.md)
- [TensorFlow Lite for Circuit Playground Bluefruit Quickstart](https://learn.adafruit.com/tensorflow-lite-for-circuit-playground-bluefruit-quickstart.md)
- [Cyberpunk Santa Eye](https://learn.adafruit.com/cyberpunk-santa-eye.md)
- [Glowing Bottle Castle and Capacitive Touch Piano](https://learn.adafruit.com/glowing-bottle-castle-and-capacitive-touch-piano.md)
- [CircuitPython Sin Complicaciones para la Circuit Playground Express y la Bluefruit](https://learn.adafruit.com/circuitpython-sin-complicaciones-para-la-circuit-playground-express.md)
- [Bluefruit Playground Hide and Seek](https://learn.adafruit.com/hide-n-seek-bluefruit-ornament.md)
- [Sound Reactive Sunflower Baby Crib Mobile with Bluetooth Control](https://learn.adafruit.com/sound-reactive-sunflower-baby-crib-mobile-with-bluetooth-control.md)
- [No-Solder PaperCraft Crystal Light Strand](https://learn.adafruit.com/no-solder-papercraft-crystal-light-strand.md)
- [AdaBox 014](https://learn.adafruit.com/adabox014.md)
- [Sailor Moon Star Locket](https://learn.adafruit.com/sailor-moon-star-locket.md)
- [PyLeap EyeLights LED Glasses Rainbows for Circuit Playground Bluefruit](https://learn.adafruit.com/pyleap-eyelights-led-glasses-for-circuit-playground-bluefruit.md)
- [Snow Globe with Circuit Playground Bluefruit](https://learn.adafruit.com/snow-globe-bluefruit-cpb.md)
- [Turtle Graphics in CircuitPython on TFT Gizmo](https://learn.adafruit.com/turtle-graphics-gizmo.md)
- [Bluefruit TFT Gizmo ANCS Notifier for iOS](https://learn.adafruit.com/ancs-gizmo.md)
- [Circuit Playground Bluefruit Quick Draw Duo](https://learn.adafruit.com/circuit-playground-bluefruit-quick-draw-duo.md)
- [Using LoraWAN and The Things Network with CircuitPython](https://learn.adafruit.com/using-lorawan-and-the-things-network-with-circuitpython.md)
