/ CircuitPython_Scrolling_Clouds / code.py
code.py
1 # SPDX-FileCopyrightText: 2019 Dave Astels for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 """ 6 Continuously scroll randomly generated Mario style clouds. 7 Designed for an ItsyBitsy M4 Express and a 1.3" 240x240 TFT 8 9 Adafruit invests time and resources providing this open source code. 10 Please support Adafruit and open source hardware by purchasing 11 products from Adafruit! 12 13 Written by Dave Astels for Adafruit Industries 14 Copyright (c) 2019 Adafruit Industries 15 Licensed under the MIT license. 16 17 All text above must be included in any redistribution. 18 """ 19 20 import time 21 from random import seed, randint 22 import board 23 import displayio 24 from adafruit_st7789 import ST7789 25 import adafruit_imageload 26 27 28 # Sprite cell values 29 EMPTY = 0 30 LEFT = 1 31 MIDDLE = 2 32 RIGHT = 3 33 34 # These constants determine what happens when tiles are shifted. 35 # if randint(1, 10) > the value, the thing happens 36 37 # The chance a new cloud will enter 38 CHANCE_OF_NEW_CLOUD = 4 39 40 # The chance an existing cloud gets extended 41 CHANCE_OF_EXTENDING_A_CLOUD = 5 42 43 seed(int(time.monotonic())) 44 45 46 def make_display(): 47 """Set up the display support. 48 Return the Display object. 49 """ 50 spi = board.SPI() 51 while not spi.try_lock(): 52 pass 53 spi.configure(baudrate=24000000) # Configure SPI for 24MHz 54 spi.unlock() 55 56 displayio.release_displays() 57 display_bus = displayio.FourWire(spi, command=board.D7, chip_select=board.D10, reset=board.D9) 58 59 return ST7789(display_bus, width=240, height=240, rowstart=80, auto_refresh=True) 60 61 62 def make_tilegrid(): 63 """Construct and return the tilegrid.""" 64 group = displayio.Group() 65 66 sprite_sheet, palette = adafruit_imageload.load("/tilesheet-2x.bmp", 67 bitmap=displayio.Bitmap, 68 palette=displayio.Palette) 69 grid = displayio.TileGrid(sprite_sheet, pixel_shader=palette, 70 width=9, height=5, 71 tile_height=48, tile_width=32, 72 default_tile=EMPTY) 73 group.append(grid) 74 display.show(group) 75 return grid 76 77 78 def evaluate_position(row, col): 79 """Return how long of a cloud is placeable at the given location. 80 :param row: the tile row (0-4) 81 :param col: the tile column (0-8) 82 """ 83 if tilegrid[col, row] != EMPTY or tilegrid[col + 1, row] != EMPTY: 84 return 0 85 end_col = col + 1 86 while end_col < 9 and tilegrid[end_col, row] == EMPTY: 87 end_col += 1 88 return min([4, end_col - col]) 89 90 91 def seed_clouds(number_of_clouds): 92 """Create the initial clouds so it doesn't start empty""" 93 for _ in range(number_of_clouds): 94 while True: 95 row = randint(0, 4) 96 col = randint(0, 7) 97 cloud_length = evaluate_position(row, col) 98 if cloud_length > 0: 99 break 100 l = randint(1, cloud_length) 101 tilegrid[col, row] = LEFT 102 for _ in range(l - 2): 103 col += 1 104 tilegrid[col, row] = MIDDLE 105 tilegrid[col + 1, row] = RIGHT 106 107 108 def slide_tiles(): 109 """Move the tilegrid to the left, one pixel at a time, a full time width""" 110 for _ in range(32): 111 tilegrid.x -= 1 112 display.refresh(target_frames_per_second=60) 113 114 115 def shift_tiles(): 116 """Move tiles one spot to the left, and reset the tilegrid's position""" 117 for row in range(5): 118 for col in range(8): 119 tilegrid[col, row] = tilegrid[col + 1, row] 120 tilegrid[8, row] = EMPTY 121 tilegrid.x = 0 122 123 124 def extend_clouds(): 125 """Extend any clouds on the right edge, either finishing them with a right 126 end or continuing them with a middle piece 127 """ 128 for row in range(5): 129 if tilegrid[7, row] == LEFT or tilegrid[7, row] == MIDDLE: 130 if randint(1, 10) > CHANCE_OF_EXTENDING_A_CLOUD: 131 tilegrid[8, row] = MIDDLE 132 else: 133 tilegrid[8, row] = RIGHT 134 135 136 def add_cloud(): 137 """Maybe add a new cloud on the right at a random open row""" 138 if randint(1, 10) > CHANCE_OF_NEW_CLOUD: 139 count = 0 140 while True: 141 count += 1 142 if count == 50: 143 return 144 row = randint(0, 4) 145 if tilegrid[7, row] == EMPTY and tilegrid[8, row] == EMPTY: 146 break 147 tilegrid[8, row] = LEFT 148 149 150 display = make_display() 151 tilegrid = make_tilegrid() 152 seed_clouds(5) 153 154 while True: 155 slide_tiles() 156 shift_tiles() 157 extend_clouds() 158 add_cloud()