bitarray.py

../_images/bitarray.png

An example using map_bitarray_to_rgb565 to draw sprites

  1"""
  2bitarray.py
  3===========
  4
  5.. figure:: /_static/bitarray.png
  6  :align: center
  7
  8  An example using map_bitarray_to_rgb565 to draw sprites
  9"""
 10
 11# pylint: disable=import-error
 12import random
 13import time
 14import gc9a01
 15import tft_config
 16
 17
 18tft = tft_config.config(1)
 19
 20#
 21SPRITE_WIDTH = 16
 22SPRITE_HEIGHT = 16
 23SPRITE_STEPS = 3
 24# fmt: off
 25SPRITE_BITMAPS = [
 26    bytearray([
 27        0b00000000, 0b00000000,
 28        0b00000001, 0b11110000,
 29        0b00000111, 0b11110000,
 30        0b00001111, 0b11100000,
 31        0b00001111, 0b11000000,
 32        0b00011111, 0b10000000,
 33        0b00011111, 0b00000000,
 34        0b00011110, 0b00000000,
 35        0b00011111, 0b00000000,
 36        0b00011111, 0b10000000,
 37        0b00001111, 0b11000000,
 38        0b00001111, 0b11100000,
 39        0b00000111, 0b11110000,
 40        0b00000001, 0b11110000,
 41        0b00000000, 0b00000000,
 42        0b00000000, 0b00000000]),
 43
 44    bytearray([
 45        0b00000000, 0b00000000,
 46        0b00000011, 0b11100000,
 47        0b00001111, 0b11111000,
 48        0b00011111, 0b11111100,
 49        0b00011111, 0b11111100,
 50        0b00111111, 0b11110000,
 51        0b00111111, 0b10000000,
 52        0b00111100, 0b00000000,
 53        0b00111111, 0b10000000,
 54        0b00111111, 0b11110000,
 55        0b00011111, 0b11111100,
 56        0b00011111, 0b11111100,
 57        0b00001111, 0b11111000,
 58        0b00000011, 0b11100000,
 59        0b00000000, 0b00000000,
 60        0b00000000, 0b00000000]),
 61
 62    bytearray([
 63        0b00000000, 0b00000000,
 64        0b00000111, 0b11000000,
 65        0b00011111, 0b11110000,
 66        0b00111111, 0b11111000,
 67        0b00111111, 0b11111000,
 68        0b01111111, 0b11111100,
 69        0b01111111, 0b11111100,
 70        0b01111111, 0b11111100,
 71        0b01111111, 0b11111100,
 72        0b01111111, 0b11111100,
 73        0b00111111, 0b11111000,
 74        0b00111111, 0b11111000,
 75        0b00011111, 0b11110000,
 76        0b00000111, 0b11000000,
 77        0b00000000, 0b00000000,
 78        0b00000000, 0b00000000]),
 79
 80    bytearray([
 81        0b00000000, 0b00000000,
 82        0b00000000, 0b00000000,
 83        0b00000000, 0b00000000,
 84        0b00000000, 0b00000000,
 85        0b00000000, 0b00000000,
 86        0b00000000, 0b00000000,
 87        0b00000000, 0b00000000,
 88        0b00000000, 0b00000000,
 89        0b00000000, 0b00000000,
 90        0b00000000, 0b00000000,
 91        0b00000000, 0b00000000,
 92        0b00000000, 0b00000000,
 93        0b00000000, 0b00000000,
 94        0b00000000, 0b00000000,
 95        0b00000000, 0b00000000,
 96        0b00000000, 0b00000000])]
 97
 98# fmt: on
 99
100
101def collide(first, second):
102    """return true if two sprites collide or overlap"""
103
104    return (
105        first.sprite_x + first.width > second.sprite_x
106        and first.sprite_x < second.sprite_x + second.width
107        and first.sprite_y + first.height > second.sprite_y
108        and first.sprite_y < second.sprite_y + second.height
109    )
110
111
112class Pacman:
113    """
114    Pacman class to keep track of a sprites location and step
115    """
116
117    def __init__(self, sprites, width, height, steps):
118        """create a new pacman sprite that does not overlap another sprite"""
119        self.sprite_x = 0
120        self.sprite_y = 0
121        self.steps = steps
122        self.step = random.randint(0, self.steps)
123        self.width = width
124        self.height = height
125
126        # Big problem if there are too many sprites for the size of the display
127        while True:
128            self.sprite_x = random.randint(0, tft.width() - width)
129            self.sprite_y = random.randint(0, tft.height() - height)
130            # if this sprite does not overlap another sprite then break
131            if not any(collide(self, sprite) for sprite in sprites):
132                break
133
134    def move(self):
135        """move the sprite one step"""
136        max_x = tft.width() - SPRITE_WIDTH
137        self.step += 1
138        self.step %= SPRITE_STEPS
139        self.sprite_x += 1
140        if self.sprite_x == max_x - 1:
141            self.step = SPRITE_STEPS
142
143        self.sprite_x %= max_x
144
145    def draw(self, blitable):
146        """draw the sprite on the screen"""
147        tft.blit_buffer(blitable, self.sprite_x, self.sprite_y, self.width, self.height)
148
149
150def main():
151    """
152    Draw on screen using map_bitarray_to_rgb565
153    """
154
155    # enable display and clear screen
156    tft.init()
157    tft.fill(gc9a01.BLACK)
158
159    # convert bitmaps into rgb565 blitable buffers
160    blitable = []
161    for sprite_bitmap in SPRITE_BITMAPS:
162        sprite = bytearray(512)
163        tft.map_bitarray_to_rgb565(
164            sprite_bitmap, sprite, SPRITE_WIDTH, gc9a01.YELLOW, gc9a01.BLACK
165        )
166        blitable.append(sprite)
167
168    sprite_count = tft.width() // SPRITE_WIDTH * tft.height() // SPRITE_HEIGHT // 4
169
170    # create pacman spites in random positions
171    sprites = []
172    for _ in range(sprite_count):
173        sprites.append(Pacman(sprites, SPRITE_WIDTH, SPRITE_HEIGHT, SPRITE_STEPS))
174
175    # move and draw sprites
176    while True:
177        for sprite in sprites:
178            sprite.move()
179            sprite.draw(blitable[sprite.step])
180        time.sleep(0.05)
181
182
183main()