Browse Source

change brightness with controller. tweak tetris.

Thomas Buck 10 months ago
parent
commit
d3f4c9c9a4
18 changed files with 282 additions and 132 deletions
  1. 1
    1
      camp_pico.py
  2. 10
    6
      camp_small.py
  3. 1
    1
      gamepad.py
  4. 1
    1
      image.py
  5. 1
    1
      life.py
  6. 9
    4
      manager.py
  7. 81
    35
      mapper.py
  8. 1
    1
      net.py
  9. 4
    9
      pi.py
  10. 4
    13
      pico.py
  11. 7
    4
      qr.py
  12. 1
    1
      scroll.py
  13. 17
    9
      snake.py
  14. 1
    1
      solid.py
  15. 1
    1
      splash.py
  16. 4
    13
      test.py
  17. 124
    27
      tetris.py
  18. 14
    4
      util.py

+ 1
- 1
camp_pico.py View File

@@ -69,4 +69,4 @@ m.add(PicoBatt(t, 5.0, 5.0))
69 69
 m.add(Solid(t, 1.0))
70 70
 
71 71
 m.restart()
72
-t.loop(m.draw)
72
+util.loop(t, m.draw)

+ 10
- 6
camp_small.py View File

@@ -25,10 +25,12 @@ import util
25 25
 #url = "http://ubabot.frubar.net"
26 26
 url = "http://www.xythobuz.de"
27 27
 
28
+scroll_speed = 15
29
+
28 30
 # Need to import InputWrapper before initializing RGB Matrix on Pi
29 31
 i = InputWrapper()
30 32
 
31
-t = util.getTarget()
33
+t = util.getTarget(i)
32 34
 
33 35
 # Loading fonts and graphics takes a while.
34 36
 # So show a splash screen while the user waits.
@@ -41,14 +43,16 @@ t.loop_end()
41 43
 success = Manager(t)
42 44
 success.add(ImageScreen(t, "drinka.gif", 0.2, 2, 20.0, (0, 0, 0)))
43 45
 success.add(Solid(t, 1.0))
44
-success.add(QRScreen(t, url, 30.0, "Drinks:", "tom-thumb", (255, 255, 255), (0, 0, 0)))
46
+success.add(ScrollText(t, "Visit the UbaBot Cocktail machine at FruBar village for drinks!", "lemon", 2, scroll_speed, camp_green))
47
+success.add(Solid(t, 1.0))
48
+success.add(QRScreen(t, url, 30.0, "Drinks:", "tom-thumb", camp_pink, (0, 0, 0)))
45 49
 success.add(Solid(t, 1.0))
46 50
 
47 51
 # UbaBot is offline
48 52
 fail = Manager(t)
49 53
 fail.add(ImageScreen(t, "attention.gif", 0.2, 2, 20.0, (0, 0, 0)))
50 54
 fail.add(Solid(t, 1.0))
51
-fail.add(ScrollText(t, "The UbaBot Cocktail machine is currently closed. Please come back later for more drinks!", "lemon", 2, 75, camp_pink))
55
+fail.add(ScrollText(t, "The UbaBot Cocktail machine is currently closed. Please come back later for more drinks!", "lemon", 2, scroll_speed, camp_pink))
52 56
 fail.add(Solid(t, 1.0))
53 57
 fail.add(GameOfLife(t, 20, (0, 255, 0), (0, 0, 0), None, 2.0))
54 58
 fail.add(Solid(t, 1.0))
@@ -60,7 +64,7 @@ d.fail(fail)
60 64
 
61 65
 # Main "Menu"
62 66
 m = Manager(t, i)
63
-m.add(ScrollText(t, "#CCCAMP23", "lemon", 1, 75, camp_green))
67
+m.add(ScrollText(t, "#CCCAMP23", "lemon", 1, scroll_speed, camp_green))
64 68
 m.add(Solid(t, 1.0))
65 69
 m.add(ImageScreen(t, "Favicon.png", 0, 1, 10.0))
66 70
 m.add(Solid(t, 1.0))
@@ -68,8 +72,8 @@ m.add(d) # HTTP Check, either "success" or "fail"
68 72
 m.add(Solid(t, 1.0))
69 73
 m.add(Snake(t, i, camp_pink, camp_green))
70 74
 m.add(Solid(t, 1.0))
71
-m.add(ScrollText(t, "Your advertisement could appear here. Open a Pull Request on git.xythobuz.de/thomas/rgb-matrix-visualizer or send an e-mail to thomas@xythobuz.de", "iv18x16u", 2, 70, camp_green))
75
+m.add(ScrollText(t, "Your advertisement could appear here. Open a Pull Request on git.xythobuz.de/thomas/rgb-matrix-visualizer or send an e-mail to thomas@xythobuz.de", "iv18x16u", 2, scroll_speed, camp_green))
72 76
 m.add(Solid(t, 1.0))
73 77
 
74 78
 m.restart()
75
-t.loop(m.draw)
79
+util.loop(t, m.draw)

+ 1
- 1
gamepad.py View File

@@ -87,7 +87,7 @@ class InputWrapper:
87 87
                         self.keys["r"] = v
88 88
                     elif (event.code == ecodes.BTN_TOP2) or (event.code == ecodes.KEY_A):
89 89
                         self.keys["l"] = v
90
-                    elif event.code == ecodes.BTN_BASE4:
90
+                    elif (event.code == ecodes.BTN_BASE4) or (event.code == ecodes.KEY_BACKSPACE):
91 91
                         self.keys["start"] = v
92 92
                     elif event.code == ecodes.BTN_BASE3:
93 93
                         self.keys["select"] = v

+ 1
- 1
image.py View File

@@ -164,4 +164,4 @@ if __name__ == "__main__":
164 164
                 print()
165 165
 
166 166
     m.restart()
167
-    t.loop(m.draw)
167
+    util.loop(t, m.draw)

+ 1
- 1
life.py View File

@@ -151,4 +151,4 @@ if __name__ == "__main__":
151 151
             g.restart()
152 152
         g.draw()
153 153
 
154
-    t.loop(helper)
154
+    util.loop(t, helper)

+ 9
- 4
manager.py View File

@@ -72,13 +72,18 @@ class Manager:
72 72
 
73 73
     def switch_to(self, i, update_flag):
74 74
         self.lastTime = time.time()
75
-        self.index = int((int(self.index / self.step_size) + i) * self.step_size) % len(self.screens)
76
-
77
-        #print("Manager ", len(self.screens), " switch to ", self.index, update_flag)
78 75
 
79 76
         if update_flag:
80 77
             self.done = (self.index == 0)
81 78
 
79
+            # go through all for normal operation
80
+            self.index = (self.index + i) % len(self.screens)
81
+        else:
82
+            # use step_size for button presses
83
+            self.index = int((int(self.index / self.step_size) + i) * self.step_size) % len(self.screens)
84
+
85
+        #print("Manager ", len(self.screens), " switch to ", self.index, update_flag)
86
+
82 87
         self.screens[self.index][0].restart()
83 88
 
84 89
     def draw(self):
@@ -131,4 +136,4 @@ if __name__ == "__main__":
131 136
     m.add(Solid(t, 1.0))
132 137
 
133 138
     m.restart()
134
-    t.loop(m.draw)
139
+    util.loop(t, m.draw)

+ 81
- 35
mapper.py View File

@@ -34,15 +34,15 @@ class MapperNull:
34 34
     def batteryCache(self, refresh = False):
35 35
         return self.gui.batteryCache(refresh)
36 36
 
37
+    def exit(self):
38
+        self.gui.exit()
39
+
37 40
     def loop_start(self):
38 41
         return self.gui.loop_start()
39 42
 
40 43
     def loop_end(self):
41 44
         self.gui.loop_end()
42 45
 
43
-    def loop(self, func = None):
44
-        self.gui.loop(func)
45
-
46 46
     def set_pixel(self, x, y, color):
47 47
         self.gui.set_pixel(x, y, color)
48 48
 
@@ -98,61 +98,107 @@ class MapperStripToRect(MapperNull):
98 98
 # this needs to be the "first" element of the mapper chain.
99 99
 # Otherwise special handling for PicoText will not work.
100 100
 class MapperReduceBrightness(MapperNull):
101
-    def __init__(self, g):
101
+    def __init__(self, g, i = None):
102 102
         super().__init__(g)
103
+        self.input = i
103 104
         self.last = None
104 105
         self.connected = False
105 106
         self.refresh = 60 * 60 * 6
106 107
         self.factor = 1.0
108
+        self.user_mod = None
109
+        self.old_keys = {
110
+            "left": False,
111
+            "right": False,
112
+            "up": False,
113
+            "down": False,
114
+            "a": False,
115
+            "b": False,
116
+            "x": False,
117
+            "y": False,
118
+            "l": False,
119
+            "r": False,
120
+            "start": False,
121
+            "select": False,
122
+        }
107 123
 
108 124
     def fetch(self):
109
-        self.factor = 1.0
110
-
111
-        if not useNTP:
112
-            return
113
-
114
-        if not self.connected:
115
-            self.connected = util.connectToWiFi()
116
-
117
-        if self.connected:
118
-            now = time.time()
119
-            if (self.last == None) or ((now - self.last) >= self.refresh) or (now < self.last):
120
-                self.last = now
121
-
122
-                try:
123
-                    print("Before sync: " + str(time.localtime()))
124
-                    ntptime.settime()
125
-                    print("After sync: "  + str(time.localtime()))
126
-                except Exception as e:
127
-                    print()
128
-                    if hasattr(sys, "print_exception"):
129
-                        sys.print_exception(e)
130
-                    else:
131
-                        print(e)
132
-                    print()
133
-
134
-                    return
125
+        if useNTP:
126
+            if not self.connected:
127
+                self.connected = util.connectToWiFi()
128
+            if self.connected:
129
+                now = time.time()
130
+                if (self.last == None) or ((now - self.last) >= self.refresh) or (now < self.last):
131
+                    self.last = now
132
+                    try:
133
+                        print("Before sync: " + str(time.localtime()))
134
+                        ntptime.settime()
135
+                        print("After sync: "  + str(time.localtime()))
136
+                    except Exception as e:
137
+                        print()
138
+                        if hasattr(sys, "print_exception"):
139
+                            sys.print_exception(e)
140
+                        else:
141
+                            print(e)
142
+                        print()
143
+                        return
144
+        else:
145
+            if self.last == None:
146
+                self.last = time.time()
147
+                print("Time: " + str(time.localtime()))
135 148
 
136 149
         # (year, month, day, hour, minute, second, ?, ?)
137 150
         now = time.localtime()
138 151
 
139
-        # 8pm utc == 22pm dst germany
140
-        night = (now[0], now[1], now[2], 20, 0, 0, 0, 0)
152
+        # TODO ntptime is setting to UTC, host is on proper timezone
153
+        if useNTP:
154
+            # 8pm utc == 10pm cest germany
155
+            night = (now[0], now[1], now[2], 20, 0, 0, 0, 0)
141 156
 
142
-        # 5am utc == 7am dst germany
143
-        morning = (now[0], now[1], now[2], 5, 0, 0, 0, 0)
157
+            # 5am utc == 7am cest germany
158
+            morning = (now[0], now[1], now[2], 5, 0, 0, 0, 0)
159
+        else:
160
+            # 10pm cest germany
161
+            night = (now[0], now[1], now[2], 22, 0, 0, 0, 0)
162
+
163
+            # 7am cest germany
164
+            morning = (now[0], now[1], now[2], 7, 0, 0, 0, 0)
144 165
 
145 166
         if (now > morning) and (now < night):
146 167
             self.factor = 1.0
147 168
         else:
148 169
             self.factor = 0.42
149 170
 
171
+    def buttons(self):
172
+        keys = self.input.get()
173
+
174
+        if (keys["select"] and keys["up"] and (not self.old_keys["up"])) or (keys["up"] and keys["select"] and (not self.old_keys["select"])):
175
+            self.factor += 0.05
176
+            self.factor = min(self.factor, 0.95)
177
+            self.user_mod = time.time()
178
+        elif (keys["select"] and keys["down"] and (not self.old_keys["down"])) or (keys["down"] and keys["select"] and (not self.old_keys["select"])):
179
+            self.factor -= 0.05
180
+            self.factor = max(self.factor, 0.05)
181
+            self.user_mod = time.time()
182
+
183
+        self.old_keys = keys.copy()
184
+
150 185
     def adjust(self, color):
151 186
         return (int(color[0] * self.factor), int(color[1] * self.factor), int(color[2] * self.factor))
152 187
 
188
+    def loop_start(self):
189
+        if self.input != None:
190
+            self.buttons()
191
+
192
+        return super().loop_start()
193
+
153 194
     def loop_end(self):
154 195
         super().loop_end()
155
-        self.fetch()
196
+
197
+        if self.user_mod == None:
198
+            self.fetch()
199
+        elif (time.time() - self.user_mod) > self.refresh:
200
+            # fall back from user-modified factor after 6h
201
+            self.user_mod = None
156 202
 
157 203
     def set_pixel(self, x, y, color):
158 204
         color = self.adjust(color)

+ 1
- 1
net.py View File

@@ -122,4 +122,4 @@ if __name__ == "__main__":
122 122
     d.success(Solid(t, 1.0, (0, 255, 0)))
123 123
     d.fail(Solid(t, 1.0, (255, 0, 0)))
124 124
 
125
-    t.loop(d.draw)
125
+    util.loop(t, d.draw)

+ 4
- 9
pi.py View File

@@ -69,6 +69,9 @@ class PiMatrix:
69 69
 
70 70
         self.loop_start() # initialize with blank image for ScrollText constructor
71 71
 
72
+    def exit(self):
73
+        pass
74
+
72 75
     def loop_start(self):
73 76
         self.image = Image.new('RGB', (self.width, self.height))
74 77
         return False # no input, never quit on our own
@@ -76,14 +79,6 @@ class PiMatrix:
76 79
     def loop_end(self):
77 80
         self.matrix.SetImage(self.image.convert('RGB'))
78 81
 
79
-    def loop(self, func = None):
80
-        while True:
81
-            if self.loop_start():
82
-                break
83
-            if func != None:
84
-                func()
85
-            self.loop_end()
86
-
87 82
     def set_pixel(self, x, y, color):
88 83
         if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
89 84
             return
@@ -92,4 +87,4 @@ class PiMatrix:
92 87
 
93 88
 if __name__ == "__main__":
94 89
     t = PiMatrix(32, 32)
95
-    t.loop(lambda: t.set_pixel(15, 15, (255, 255, 255)))
90
+    util.loop(t, lambda: t.set_pixel(15, 15, (255, 255, 255)))

+ 4
- 13
pico.py View File

@@ -77,6 +77,9 @@ class PicoMatrix:
77 77
 
78 78
         self.loop_start() # initialize with blank image for ScrollText constructor
79 79
 
80
+    def exit(self):
81
+        self.matrix.stop()
82
+
80 83
     def battery(self):
81 84
         n = const(10)
82 85
         bits = const(10)
@@ -152,18 +155,6 @@ class PicoMatrix:
152 155
         # update battery if necessary
153 156
         self.batteryCache(False)
154 157
 
155
-    def loop(self, func = None):
156
-        while True:
157
-            if self.loop_start():
158
-                break
159
-
160
-            if func != None:
161
-                func()
162
-
163
-            self.loop_end()
164
-
165
-        self.matrix.stop()
166
-
167 158
     def set_pixel(self, x, y, color):
168 159
         if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
169 160
             return
@@ -303,4 +294,4 @@ if __name__ == "__main__":
303 294
         else:
304 295
             s.text("Drinks:", "bitmap8", 0)
305 296
 
306
-    t.loop(helper)
297
+    util.loop(t, helper)

+ 7
- 4
qr.py View File

@@ -49,7 +49,8 @@ class QRScreen:
49 49
                     self.c1 = (255, 255, 255)
50 50
                     self.c2 = (0, 0, 0)
51 51
                 else:
52
-                    raise RuntimeError("QR colors other than black/white not supported on Pi")
52
+                    # Use default colors for QR code, and colors for text
53
+                    self.image = qr.make_image(fill_color = "white", back_color = "black")
53 54
             else:
54 55
                 self.image = qr.make_image(fill_color = self.c1, back_color = self.c2)
55 56
         else:
@@ -91,9 +92,11 @@ class QRScreen:
91 92
                     self.gui.set_pixel(x + self.xOff + self.image.width, y + self.yOff, self.c2)
92 93
 
93 94
         if self.heading != None:
94
-            off = -10
95
+            off = 0
95 96
             if self.font == "bitmap6":
96
-                off -= 3
97
+                off = -14
98
+            elif self.font == "tom-thumb":
99
+                off = -11
97 100
 
98 101
             self.text.text(self.heading, self.font, 0, True, off)
99 102
 
@@ -135,4 +138,4 @@ if __name__ == "__main__":
135 138
             print(e)
136 139
             print()
137 140
 
138
-    t.loop(d.draw)
141
+    util.loop(t, d.draw)

+ 1
- 1
scroll.py View File

@@ -80,4 +80,4 @@ if __name__ == "__main__":
80 80
         m.add(ScrollText(t, s, fontName, 1, 75, (0, 255, 0), (0, 0, 25)))
81 81
 
82 82
     m.restart()
83
-    t.loop(m.draw)
83
+    util.loop(t, m.draw)

+ 17
- 9
snake.py View File

@@ -21,11 +21,11 @@ class Snake:
21 21
         self.speedup = su
22 22
 
23 23
         self.winText = ScrollText(self.gui, "You Won!", "uushi",
24
-                                  2, 75, (0, 255, 0))
24
+                                  2, 50, (0, 255, 0))
25 25
         self.loseText = ScrollText(self.gui, "Game Over!", "uushi",
26
-                                   2, 75, (255, 0, 0))
26
+                                   2, 50, (255, 0, 0))
27 27
         self.scoreText = ScrollText(self.gui, "Score:", "uushi",
28
-                                    2, 75, sc)
28
+                                    2, 50, sc)
29 29
 
30 30
         random.seed()
31 31
         self.restart()
@@ -46,6 +46,14 @@ class Snake:
46 46
             "right": False,
47 47
             "up": False,
48 48
             "down": False,
49
+            "a": False,
50
+            "b": False,
51
+            "x": False,
52
+            "y": False,
53
+            "l": False,
54
+            "r": False,
55
+            "start": False,
56
+            "select": False,
49 57
         }
50 58
 
51 59
         self.placeDot()
@@ -71,13 +79,13 @@ class Snake:
71 79
     def buttons(self):
72 80
         keys = self.input.get()
73 81
 
74
-        if keys["left"] and (not self.old_keys["left"]):
82
+        if keys["left"] and (not self.old_keys["left"]) and (not self.old_keys["select"]):
75 83
             self.directionTmp = "l"
76
-        elif keys["right"] and (not self.old_keys["right"]):
84
+        elif keys["right"] and (not self.old_keys["right"]) and (not self.old_keys["select"]):
77 85
             self.directionTmp = "r"
78
-        elif keys["up"] and (not self.old_keys["up"]):
86
+        elif keys["up"] and (not self.old_keys["up"]) and (not self.old_keys["select"]):
79 87
             self.directionTmp = "u"
80
-        elif keys["down"] and (not self.old_keys["down"]):
88
+        elif keys["down"] and (not self.old_keys["down"]) and (not self.old_keys["select"]):
81 89
             self.directionTmp = "d"
82 90
         elif (keys["select"] and keys["start"] and (not self.old_keys["start"])) or (keys["start"] and keys["select"] and (not self.old_keys["select"])):
83 91
             self.restart()
@@ -175,7 +183,7 @@ if __name__ == "__main__":
175 183
     i = InputWrapper()
176 184
 
177 185
     import util
178
-    t = util.getTarget()
186
+    t = util.getTarget(i)
179 187
 
180 188
     d = Snake(t, i)
181
-    t.loop(d.draw)
189
+    util.loop(t, d.draw)

+ 1
- 1
solid.py View File

@@ -71,4 +71,4 @@ if __name__ == "__main__":
71 71
 
72 72
         d.draw()
73 73
 
74
-    t.loop(helper)
74
+    util.loop(t, helper)

+ 1
- 1
splash.py View File

@@ -41,4 +41,4 @@ if __name__ == "__main__":
41 41
     import util
42 42
     t = util.getTarget()
43 43
     s = SplashScreen(t)
44
-    t.loop(s.draw)
44
+    util.loop(t, s.draw)

+ 4
- 13
test.py View File

@@ -13,14 +13,14 @@
13 13
 import pygame
14 14
 
15 15
 class TestGUI:
16
-    def __init__(self, width = 32, height = 32, multiplier = 16):
16
+    def __init__(self, width = 32 * 2, height = 32, multiplier = 16):
17 17
         self.width = width
18 18
         self.height = height
19 19
         self.multiplier = multiplier
20 20
 
21 21
         # compatibility to PiMatrix
22
-        self.panelW = self.width
23
-        self.panelH = self.height
22
+        self.panelW = 32
23
+        self.panelH = 32
24 24
 
25 25
         pygame.display.init()
26 26
         self.screen = pygame.display.set_mode((self.width * self.multiplier, self.height * self.multiplier))
@@ -45,15 +45,6 @@ class TestGUI:
45 45
         pygame.display.flip()
46 46
         self.clock.tick(30)
47 47
 
48
-    def loop(self, func = None):
49
-        while True:
50
-            if self.loop_start():
51
-                break
52
-            if func != None:
53
-                func()
54
-            self.loop_end()
55
-        self.exit()
56
-
57 48
     def set_pixel(self, x, y, color):
58 49
         if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
59 50
             return
@@ -62,4 +53,4 @@ class TestGUI:
62 53
 
63 54
 if __name__ == "__main__":
64 55
     t = TestGUI(32, 32)
65
-    t.loop(lambda: t.set_pixel(15, 15, (255, 255, 255)))
56
+    util.loop(t, lambda: t.set_pixel(15, 15, (255, 255, 255)))

+ 124
- 27
tetris.py View File

@@ -10,6 +10,7 @@
10 10
 from scroll import ScrollText
11 11
 import time
12 12
 import random
13
+import util
13 14
 
14 15
 class Tetris:
15 16
     def __init__(self, g, i, ts = 0.5, to = 60.0, w = 10, h = 22):
@@ -20,13 +21,10 @@ class Tetris:
20 21
         self.width = min(w, self.gui.width)
21 22
         self.height = min(h, self.gui.height)
22 23
 
23
-        self.x_off = int((self.gui.panelW - self.width - 2) / 2)
24
-        self.y_off = int((self.gui.panelH - self.height - 2) / 2)
25
-
26 24
         self.endText = ScrollText(self.gui, "Game Over!", "uushi",
27
-                                   2, 75, (251, 72, 196))
25
+                                   2, 50, (251, 72, 196))
28 26
         self.scoreText = ScrollText(self.gui, "Score:", "uushi",
29
-                                    2, 75, (63, 255, 33))
27
+                                    2, 50, (63, 255, 33))
30 28
 
31 29
         self.bg = (0, 0, 0)
32 30
         self.colors = [
@@ -41,6 +39,13 @@ class Tetris:
41 39
             #(255, 255, 255),
42 40
         ]
43 41
 
42
+        DrawText = util.getTextDrawer()
43
+        self.text = []
44
+        self.text.append(DrawText(self.gui, self.colors[1]))
45
+        self.text.append(DrawText(self.gui, self.colors[0]))
46
+        self.text.append(DrawText(self.gui, self.colors[4]))
47
+        self.text.append(DrawText(self.gui, self.colors[5]))
48
+
44 49
         # all [y][x] sub-lists must be the same length
45 50
         self.pieces = [
46 51
             # "I"
@@ -90,6 +95,22 @@ class Tetris:
90 95
             ],
91 96
         ]
92 97
 
98
+        self.max_width = 0
99
+        self.max_height = 0
100
+        for piece in self.pieces:
101
+            if len(piece) > self.max_height:
102
+                self.max_height = len(piece)
103
+            if len(piece[0]) > self.max_width:
104
+                self.max_width = len(piece[0])
105
+        self.max_width += 2
106
+        self.max_height += 2
107
+
108
+        self.x_off = 1
109
+        self.y_off = self.gui.height - self.height - 3
110
+
111
+        self.next_x_off = self.gui.panelW - self.max_width - 3
112
+        self.next_y_off = self.gui.panelH - self.max_height - 3
113
+
93 114
         random.seed()
94 115
         self.restart()
95 116
 
@@ -101,12 +122,22 @@ class Tetris:
101 122
         self.done = False
102 123
         self.data = [[self.bg for y in range(self.height)] for x in range(self.width)]
103 124
         self.piece = None
125
+        self.next_piece = None
104 126
         self.old_keys = {
105 127
             "left": False,
106 128
             "right": False,
107 129
             "up": False,
108 130
             "down": False,
131
+            "a": False,
132
+            "b": False,
133
+            "x": False,
134
+            "y": False,
135
+            "l": False,
136
+            "r": False,
137
+            "start": False,
138
+            "select": False,
109 139
         }
140
+        self.pause = False
110 141
 
111 142
     def finished(self):
112 143
         if self.input == None:
@@ -198,11 +229,9 @@ class Tetris:
198 229
         return board_clear
199 230
 
200 231
     def step(self):
201
-        if self.piece == None:
202
-            justPlaced = True
203
-
232
+        if self.next_piece == None:
204 233
             # select a new piece type and color
205
-            self.piece = [
234
+            self.next_piece = [
206 235
                 self.pieces[random.randrange(0, len(self.pieces))], # piece
207 236
                 self.colors[random.randrange(0, len(self.colors))], # color
208 237
                 0, # x
@@ -210,7 +239,16 @@ class Tetris:
210 239
             ]
211 240
 
212 241
             # center the piece on top of the playing board
213
-            self.piece[2] = int((self.width - len(self.piece[0][0])) / 2)
242
+            self.next_piece[2] = int((self.width - len(self.next_piece[0][0])) / 2)
243
+
244
+            # offsets for drawing the next piece
245
+            self.piece_x_off = int((self.max_width - len(self.next_piece[0][0])) / 2)
246
+            self.piece_y_off = int((self.max_height - len(self.next_piece[0])) / 2)
247
+
248
+        if self.piece == None:
249
+            justPlaced = True
250
+            self.piece = self.next_piece
251
+            self.next_piece = None
214 252
 
215 253
             if self.collision():
216 254
                 # new piece immediately collided. game over!
@@ -270,20 +308,47 @@ class Tetris:
270 308
     def buttons(self):
271 309
         keys = self.input.get()
272 310
 
273
-        if keys["left"] and (not self.old_keys["left"]):
311
+        if keys["left"] and (not self.old_keys["left"]) and (not self.old_keys["select"]):
274 312
             self.button = "l"
275
-        elif keys["right"] and (not self.old_keys["right"]):
313
+        elif keys["right"] and (not self.old_keys["right"]) and (not self.old_keys["select"]):
276 314
             self.button = "r"
277
-        elif keys["up"] and (not self.old_keys["up"]):
315
+        elif keys["up"] and (not self.old_keys["up"]) and (not self.old_keys["select"]):
278 316
             self.button = "u"
279
-        elif keys["down"]:
317
+        elif keys["down"] and (not self.old_keys["select"]):
280 318
             self.button = "d"
281 319
         elif (keys["select"] and keys["start"] and (not self.old_keys["start"])) or (keys["start"] and keys["select"] and (not self.old_keys["select"])):
282 320
             self.restart()
321
+        elif keys["start"] and (not self.old_keys["start"]) and (not self.old_keys["select"]):
322
+            self.pause = not self.pause
323
+        elif self.done and keys["start"] and (not self.old_keys["start"]):
324
+            self.restart()
325
+        elif self.done and keys["a"] and (not self.old_keys["a"]):
326
+            self.restart()
327
+        elif self.done and keys["b"] and (not self.old_keys["b"]):
328
+            self.restart()
329
+        elif self.done and keys["x"] and (not self.old_keys["x"]):
330
+            self.restart()
331
+        elif self.done and keys["y"] and (not self.old_keys["y"]):
332
+            self.restart()
283 333
 
284 334
         self.old_keys = keys.copy()
285 335
 
336
+    def draw_stats(self, off):
337
+        x_off, y_off = off
338
+
339
+        self.text[0].text("Score:", "tom-thumb", -x_off - 2, True, y_off - 11)
340
+        self.text[1].text(str(self.score), "tom-thumb", -x_off - 2, True, y_off - 5)
341
+
342
+        if self.pause:
343
+            self.text[2].text("Paused", "tom-thumb", -x_off - 2, True, -y_off + 11)
344
+
286 345
     def draw(self):
346
+        if self.input != None:
347
+            self.buttons()
348
+        else:
349
+            # TODO "AI"
350
+            self.button = None
351
+
287 352
         if self.done:
288 353
             if self.endText.finished():
289 354
                 self.scoreText.draw()
@@ -292,14 +357,8 @@ class Tetris:
292 357
                 self.scoreText.restart()
293 358
             return
294 359
 
295
-        if self.input != None:
296
-            self.buttons()
297
-        else:
298
-            # TODO "AI"
299
-            self.button = None
300
-
301 360
         now = time.time()
302
-        if (self.button != None) or ((now - self.last) >= self.timestep) or (now < self.last):
361
+        if (not self.pause) and ((self.button != None) or ((now - self.last) >= self.timestep) or (now < self.last)):
303 362
             # don't let user stop falling pieces by moving/rotating endlessly
304 363
             if (self.button != "l") and (self.button != "r") and (self.button != "u"):
305 364
                 self.last = now
@@ -310,22 +369,60 @@ class Tetris:
310 369
                 self.scoreText.setText("Score: " + str(self.score), "uushi")
311 370
                 self.endText.restart()
312 371
 
313
-        # TODO placement of play area
372
+        # static text
373
+        self.text[1].text("Tetris", "tom-thumb", -2, True, -11)
374
+        self.text[3].text("next", "tom-thumb", -14, True, 5)
375
+        self.text[3].text("up", "tom-thumb", -14, True, 12)
376
+
377
+        # draw play area and border
314 378
         for x in range(-1, self.width + 1):
315 379
             for y in range(-1, self.height + 1):
316
-                c = (255, 255, 255)
380
+                c = self.colors[1] # border color
317 381
                 if (x >= 0) and (y >= 0) and (x < self.width) and (y < self.height):
318 382
                     c = self.data[x][y]
319
-
320 383
                 self.gui.set_pixel(x + 1 + self.x_off, y + 1 + self.y_off, c)
321 384
 
385
+        # draw next piece and border
386
+        for x in range(-1, self.max_width + 1):
387
+            for y in range(-1, self.max_height + 1):
388
+                c = self.colors[0] # border color
389
+                if (x >= 0) and (y >= 0) and (x < self.max_width) and (y < self.max_height):
390
+                    if self.next_piece == None:
391
+                        c = (0, 0, 0)
392
+                    else:
393
+                        if (y >= self.piece_y_off) and (y < (len(self.next_piece[0]) + self.piece_y_off)) and (x >= self.piece_x_off) and (x < (len(self.next_piece[0][0]) + self.piece_x_off)):
394
+                            if self.next_piece[0][y - self.piece_y_off][x - self.piece_x_off] != 0:
395
+                                c = self.next_piece[1]
396
+                            else:
397
+                                c = (0, 0, 0)
398
+                        else:
399
+                            c = (0, 0, 0)
400
+                self.gui.set_pixel(x + 1 + self.next_x_off, y + 1 + self.next_y_off, c)
401
+
402
+        # find position for stats
403
+        stats_off = None
404
+        if self.gui.width > self.gui.panelW:
405
+            stats_off = (self.gui.panelW, 0)
406
+        elif self.gui.height > self.gui.panelH:
407
+            stats_off = (0, self.gui.panelH)
408
+
409
+        # second screen with stats
410
+        if stats_off != None:
411
+            self.draw_stats(stats_off)
412
+
322 413
 if __name__ == "__main__":
323 414
     # Need to import InputWrapper before initializing RGB Matrix on Pi
324 415
     from gamepad import InputWrapper
325 416
     i = InputWrapper()
326 417
 
327
-    import util
328
-    t = util.getTarget()
418
+    t = util.getTarget(i)
419
+
420
+    # show splash screen while initializing
421
+    from splash import SplashScreen
422
+    splash = SplashScreen(t)
423
+    t.loop_start()
424
+    splash.draw()
425
+    t.loop_end()
329 426
 
330 427
     d = Tetris(t, i)
331
-    t.loop(d.draw)
428
+    util.loop(t, d.draw)

+ 14
- 4
util.py View File

@@ -29,7 +29,7 @@ def isPico():
29 29
 
30 30
     return targetPlatform == "pico"
31 31
 
32
-def getTarget():
32
+def getTarget(i = None):
33 33
     global targetPlatform, cachedTarget
34 34
 
35 35
     if cachedTarget != None:
@@ -42,8 +42,9 @@ def getTarget():
42 42
         pi = PiMatrix()
43 43
 
44 44
         # TODO hard-coded adjustments
45
-        from mapper import MapperColorAdjust, MapperStripToRect
46
-        col = MapperColorAdjust(pi)
45
+        from mapper import MapperReduceBrightness, MapperColorAdjust, MapperStripToRect
46
+        bright = MapperReduceBrightness(pi, i)
47
+        col = MapperColorAdjust(bright)
47 48
         #target = MapperStripToRect(col)
48 49
         target = col
49 50
 
@@ -68,7 +69,7 @@ def getTarget():
68 69
 
69 70
             # TODO hard-coded adjustments
70 71
             from mapper import MapperReduceBrightness
71
-            target = MapperReduceBrightness(pico)
72
+            target = MapperReduceBrightness(pico, i)
72 73
 
73 74
             if targetPlatform == None:
74 75
                 # only print once
@@ -223,3 +224,12 @@ def getTextDrawer():
223 224
         return PicoText
224 225
 
225 226
     return None
227
+
228
+def loop(gui, func = None):
229
+    while True:
230
+        if gui.loop_start():
231
+            break
232
+        if func != None:
233
+            func()
234
+        gui.loop_end()
235
+    gui.exit()

Loading…
Cancel
Save