Bewegte Bilder auf PicoBoy Color


technische Daten wie beim RPi Pico
Microcontroller RP2040 - 1,69 Zoll Farbdisplay mit 240 x 280 Pixeln

Projekte und Anleitung in CircuitPython 9.x.x



Bildbox 1 (klick hier)



Hardware

- PicoBoy-Color


bewegte Sprites

Zunächst brauchen wir ein weiteres Sprite_Sheet, welches den PicoMax darstellt. Dazu habe ich genau wie für den Hintergrund eine Bitmap-Datei picomax.bmp vorbereitet. Auch die können Sie
von hier herunterladen, entpacken und in den Ordner 'images' speichern.


Die 'Sprites' (32x32 Pixel) sind untereinander angeordnet und enthalten wie bei einer animierten gif-Datei die einzelnen Elemente. Außer 'PicoMax nach rechts' und 'PicoMax nach links' gibt es für später noch weitere 'Figuren'. Das oberste Sprite ist 32x32 Pixel weiss. Diese Farbe wird im Programm für die Transparenz genutzt. Im Programm wird die sprite_sheet wie bereits der Hintergrund geladen, einer TileGrid zugewiesen und der selben Gruppe 'main' hinzugefügt, wie der Hintergrund. Wenn Sie in der TileGrid 'default_tile=0' wählen, ist PicoMax beim Programmstart nicht sichtbar. Rufen Sie dann z.B. 'picomax[0] = 3' auf, wird das 4. Sprite (Zählweise beginnt immer bei 0) von oben angezeigt. Um jetzt noch die Position auf dem Display festzulegen braucht es eine entsprechende x- und y-Koordinate. Z.B.
picomax.x = 120 (von links nach rechts)
picomax.y = 90 (von oben nach unten)

Kopieren Sie den Code aus dem unteren Kasten ins Thonny und schauen sich das Ergebnis an:

  
  
1  import time
2  import board
3  import busio
4  import displayio
5  import terminalio
6  import digitalio
7  from adafruit_st7789 import ST7789
8  import adafruit_imageload
9
10  # 1,69 Zoll 240x280 Pixel ST7789 Display
11  # SPI,  in Landscape format
12  dc=board.GP8
13  reset=board.GP9
14  cs=board.GP10
15  sck=board.GP18
16  mosi=board.GP19
17  bl=board.GP26
18  # Release any resources currently in use for the displays
20  19  displayio.release_displays()
21  spi = busio.SPI(sck, mosi)
22  display_bus = displayio.FourWire(spi, command=dc, chip_select=cs, reset=reset)
23  display = ST7789(display_bus, rotation=90, width=280, height=240, backlight_pin=bl, rowstart=20, colstart=0)
24  display.brightness = 1
25  main = displayio.Group()
26
27  # Load the backgr sprite sheet (bitmap)
28  sprite_sheet, palette = adafruit_imageload.load("/images/floor.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
29  backgr_group = displayio.TileGrid(sprite_sheet, pixel_shader=palette, width=7, height=6, tile_width=40, tile_height=40, default_tile=7)
30
31  # Load the sprite sheet for PicoMax (bitmap)
32  sprite_sheet, palette = adafruit_imageload.load("/images/picomax.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
palette.make_transparent(1)
33  picomax = displayio.TileGrid(sprite_sheet, pixel_shader=palette, width=1, height=1, tile_width=32, tile_height=32, default_tile=0)
34  picomax_group = displayio.Group(scale=1)
35  picomax_group.append(picomax)
36
37  backgr = [15, 16, 13, 13, 13, 13, 13,
38            18, 19, 20, 14, 20, 14, 20,
39            7, 7, 7, 7, 7, 7, 7,
40            7, 1, 5, 5, 5, 8, 6,
41            7, 0, 7, 7, 7, 7, 2,
42            12, 0, 11, 11, 8, 10, 11]
43
44  def floor():
45      # show the 42 sprites
46      for x in range(0, 7):
47          for y in range(0, 6):
48              backgr_group[x, y] = backgr[y*7 +x]
49
50  def set_sprites():
51      picomax.x = 90
52      picomax.y = 90
53      picomax[0] = 3
54
55  main.append(backgr_group)
56  main.append(picomax_group)
57  display.root_group = main
58
59  floor()
60  set_sprites()
61  right = True
62  left = False
63  step = time.monotonic()
64
  

Nun muss PicoMax laufen. Dazu definiere ich die Variablen 'right', 'left' und 'step'. In der 'while-Schleife' zeigen die Kommentarzeilen die jeweilige Funktionalität an. Durch die Änderung des Wertes von m werden in picomax[0] = m die Sprites 1 bis 4 (nach rechts) bzw. von 5 bis 8 (nach links) angezeigt. Um den Programmablauf nicht mit time.sleep(xx) zu unterbrechen, verwende ich die Variable step und gleiche diese jeweils mit time.monotonic() ab. Beim Erreichen des rechten Randes bei if picomax.x >= 250 bzw. des linken Umkehrpunktes bei if picomax.x <= 90 wird die Laufrichtung durch Ändern der Variable right bzw. left erreicht. Ergänzen Sie zum Probieren den Code aus dem unteren Kasten:

  
  
65 while True:
66     # PicoMax laeuft nach rechts
67     if right == True:
68         if time.monotonic() - step > 0.07:
69             picomax[0] = m
70             m += 1
71             picomax.x += 4
72             if m == 4:
73                 m = 1
74             step = time.monotonic()
75     # PicoMax laeuft nach links
76     if left == True:
77         if time.monotonic() - step > 0.07:
78             picomax[0] = m
79             m += 1
80             picomax.x -= 4
81             if m == 8:
82                 m = 5
83             step = time.monotonic()
84     # pruefen ob PicoMax rechts oder links angekommen ist
85     # rechts
86     if picomax.x >= 250:
87         right = False
88         left = True
89         m = 5
90     # links
91     if picomax.x <= 90:
92         right = True
93         left = False
94         m = 1
  


Und so sieht das jetzt aus:



Wenn wir die 'while-Schleife' noch mit ein paar Ergänzungen versehen, ergibt das schon fast ein 'PicoMax rennt'-Demo. Hier noch einmal der komplette Code:

  
  
1   import time
2   import board
3   import busio
4   import displayio
5   import terminalio
6   import digitalio
7   from adafruit_st7789 import ST7789
8   import adafruit_imageload
9
10  # 1,69 Zoll 240x280 Pixel ST7789 Display
11  # SPI,  in Landscape format
12  dc=board.GP8
13  reset=board.GP9
14  cs=board.GP10
15  sck=board.GP18
16  mosi=board.GP19
17  bl=board.GP26
18  # Release any resources currently in use for the displays
19  displayio.release_displays()
20  spi = busio.SPI(sck, mosi)
21  display_bus = displayio.FourWire(spi, command=dc, chip_select=cs, reset=reset)
22  display = ST7789(display_bus, rotation=90, width=280, height=240, backlight_pin=bl, rowstart=20, colstart=0)
23  display.brightness = 1
24  main = displayio.Group()
25
26  # Load the backgr sprite sheet (bitmap)
27  sprite_sheet, palette = adafruit_imageload.load("/images/floor.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
28  backgr_group = displayio.TileGrid(sprite_sheet, pixel_shader=palette, width=7, height=6, tile_width=40, tile_height=40, default_tile=7)
29
30  # Load the sprite sheet for PicoMax (bitmap)
31  sprite_sheet, palette = adafruit_imageload.load("/images/picomax.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
32  palette.make_transparent(1)
33  picomax = displayio.TileGrid(sprite_sheet, pixel_shader=palette, width=1, height=1, tile_width=32, tile_height=32, default_tile=0)
34  picomax_group = displayio.Group(scale=1)
35  picomax_group.append(picomax)
36
37  backgr = [15, 16, 13, 13, 13, 13, 13,
38            18, 19, 20, 14, 20, 14, 20,
39            7, 7, 7, 7, 7, 7, 7,
40            7, 0, 5, 5, 5, 8, 6,
41            7, 0, 7, 7, 7, 7, 2,
42            12, 0, 11, 11, 8, 10, 11]
43
44  def floor():
45      # show the 42 sprites
46      for x in range(0, 7):
47          for y in range(0, 6):
48              backgr_group[x, y] = backgr[y*7 +x]
49
50  def set_sprites():
51      picomax.x = 90
52      picomax.y = 90
53      picomax[0] = 3
54
55  main.append(backgr_group)
56  main.append(picomax_group)
57  display.root_group = main
58
59  floor()
60  set_sprites()
61  right = True
62  left = False
63  m = 1
64  step = time.monotonic()
65
66  while True:
67      # PicoMax laeuft nach rechts
68      if right == True:
69          if time.monotonic() - step > 0.07:
70              picomax[0] = m
71              m += 1
72              picomax.x += 4
73              if m == 4:
74                  m = 1
75              step = time.monotonic()
76      # PicoMax laeuft nach links
77      if left == True:
78          if time.monotonic() - step > 0.07:
79              picomax[0] = m
80              m += 1
81              picomax.x -= 4
82              if m == 8:
83                  m = 5
84              step = time.monotonic()
85      # pruefen ob PicoMax rechts oder links angekommen ist
86      if picomax.x >= 240:
87          backgr_group[6, 3] = 7
88          backgr_group[1, 2] = 7
89          picomax.y = 130
90          right = False
91          left = True
92          m = 5
93      if picomax.x <= 50:
94          picomax[0] = 0
95          backgr_group[1, 2] = 3
96          backgr_group[1, 4] = 0
97          time.sleep(0.2)
98          picomax.y = 90
99          picomax[0] = 1
100         #backgr_group[1, 2] = 0
101         right = True
102         left = False
103         m = 1
104     if picomax.x < 215 and picomax.x > 210 and left:
105         backgr_group[6, 3] = 6
106         backgr_group[1, 4] = 3
107        picomax.y = 170
  

PicoMax läuft nach rechts, betritt die Brücke; diese stürzt ein und er fällt nach unten. Zum Glück öffnet sich wie von Geisterhand die 'Fahrstuhltür, mit dem er wieder nach oben gelangt. Auch die Brücke ist wieder o.k.; aber nur von kurzer Dauer . . .

So sieht es aus:



Spielbar wird das Ganze, wenn wir im nächsten Teil die Tasten 'aktivieren' und für das Einsammeln von Geldkisten, Pilzen oder Fragezeichen Punkte vergeben. Aber Vorsicht! Manchmal begegnet PicoMax auch der Hinterlassenschaft eines Hundes oder wird sogar von ihm gebissen. Dann werden ihm Punkte abgezogen oder er verliert ein Leben.

Viel Spass und Erfolg beim Ausprobieren.