Browse Source

change brightness with controller. tweak tetris.

Thomas Buck 1 year 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
 m.add(Solid(t, 1.0))
69
 m.add(Solid(t, 1.0))
70
 
70
 
71
 m.restart()
71
 m.restart()
72
-t.loop(m.draw)
72
+util.loop(t, m.draw)

+ 10
- 6
camp_small.py View File

25
 #url = "http://ubabot.frubar.net"
25
 #url = "http://ubabot.frubar.net"
26
 url = "http://www.xythobuz.de"
26
 url = "http://www.xythobuz.de"
27
 
27
 
28
+scroll_speed = 15
29
+
28
 # Need to import InputWrapper before initializing RGB Matrix on Pi
30
 # Need to import InputWrapper before initializing RGB Matrix on Pi
29
 i = InputWrapper()
31
 i = InputWrapper()
30
 
32
 
31
-t = util.getTarget()
33
+t = util.getTarget(i)
32
 
34
 
33
 # Loading fonts and graphics takes a while.
35
 # Loading fonts and graphics takes a while.
34
 # So show a splash screen while the user waits.
36
 # So show a splash screen while the user waits.
41
 success = Manager(t)
43
 success = Manager(t)
42
 success.add(ImageScreen(t, "drinka.gif", 0.2, 2, 20.0, (0, 0, 0)))
44
 success.add(ImageScreen(t, "drinka.gif", 0.2, 2, 20.0, (0, 0, 0)))
43
 success.add(Solid(t, 1.0))
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
 success.add(Solid(t, 1.0))
49
 success.add(Solid(t, 1.0))
46
 
50
 
47
 # UbaBot is offline
51
 # UbaBot is offline
48
 fail = Manager(t)
52
 fail = Manager(t)
49
 fail.add(ImageScreen(t, "attention.gif", 0.2, 2, 20.0, (0, 0, 0)))
53
 fail.add(ImageScreen(t, "attention.gif", 0.2, 2, 20.0, (0, 0, 0)))
50
 fail.add(Solid(t, 1.0))
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
 fail.add(Solid(t, 1.0))
56
 fail.add(Solid(t, 1.0))
53
 fail.add(GameOfLife(t, 20, (0, 255, 0), (0, 0, 0), None, 2.0))
57
 fail.add(GameOfLife(t, 20, (0, 255, 0), (0, 0, 0), None, 2.0))
54
 fail.add(Solid(t, 1.0))
58
 fail.add(Solid(t, 1.0))
60
 
64
 
61
 # Main "Menu"
65
 # Main "Menu"
62
 m = Manager(t, i)
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
 m.add(Solid(t, 1.0))
68
 m.add(Solid(t, 1.0))
65
 m.add(ImageScreen(t, "Favicon.png", 0, 1, 10.0))
69
 m.add(ImageScreen(t, "Favicon.png", 0, 1, 10.0))
66
 m.add(Solid(t, 1.0))
70
 m.add(Solid(t, 1.0))
68
 m.add(Solid(t, 1.0))
72
 m.add(Solid(t, 1.0))
69
 m.add(Snake(t, i, camp_pink, camp_green))
73
 m.add(Snake(t, i, camp_pink, camp_green))
70
 m.add(Solid(t, 1.0))
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
 m.add(Solid(t, 1.0))
76
 m.add(Solid(t, 1.0))
73
 
77
 
74
 m.restart()
78
 m.restart()
75
-t.loop(m.draw)
79
+util.loop(t, m.draw)

+ 1
- 1
gamepad.py View File

87
                         self.keys["r"] = v
87
                         self.keys["r"] = v
88
                     elif (event.code == ecodes.BTN_TOP2) or (event.code == ecodes.KEY_A):
88
                     elif (event.code == ecodes.BTN_TOP2) or (event.code == ecodes.KEY_A):
89
                         self.keys["l"] = v
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
                         self.keys["start"] = v
91
                         self.keys["start"] = v
92
                     elif event.code == ecodes.BTN_BASE3:
92
                     elif event.code == ecodes.BTN_BASE3:
93
                         self.keys["select"] = v
93
                         self.keys["select"] = v

+ 1
- 1
image.py View File

164
                 print()
164
                 print()
165
 
165
 
166
     m.restart()
166
     m.restart()
167
-    t.loop(m.draw)
167
+    util.loop(t, m.draw)

+ 1
- 1
life.py View File

151
             g.restart()
151
             g.restart()
152
         g.draw()
152
         g.draw()
153
 
153
 
154
-    t.loop(helper)
154
+    util.loop(t, helper)

+ 9
- 4
manager.py View File

72
 
72
 
73
     def switch_to(self, i, update_flag):
73
     def switch_to(self, i, update_flag):
74
         self.lastTime = time.time()
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
         if update_flag:
76
         if update_flag:
80
             self.done = (self.index == 0)
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
         self.screens[self.index][0].restart()
87
         self.screens[self.index][0].restart()
83
 
88
 
84
     def draw(self):
89
     def draw(self):
131
     m.add(Solid(t, 1.0))
136
     m.add(Solid(t, 1.0))
132
 
137
 
133
     m.restart()
138
     m.restart()
134
-    t.loop(m.draw)
139
+    util.loop(t, m.draw)

+ 81
- 35
mapper.py View File

34
     def batteryCache(self, refresh = False):
34
     def batteryCache(self, refresh = False):
35
         return self.gui.batteryCache(refresh)
35
         return self.gui.batteryCache(refresh)
36
 
36
 
37
+    def exit(self):
38
+        self.gui.exit()
39
+
37
     def loop_start(self):
40
     def loop_start(self):
38
         return self.gui.loop_start()
41
         return self.gui.loop_start()
39
 
42
 
40
     def loop_end(self):
43
     def loop_end(self):
41
         self.gui.loop_end()
44
         self.gui.loop_end()
42
 
45
 
43
-    def loop(self, func = None):
44
-        self.gui.loop(func)
45
-
46
     def set_pixel(self, x, y, color):
46
     def set_pixel(self, x, y, color):
47
         self.gui.set_pixel(x, y, color)
47
         self.gui.set_pixel(x, y, color)
48
 
48
 
98
 # this needs to be the "first" element of the mapper chain.
98
 # this needs to be the "first" element of the mapper chain.
99
 # Otherwise special handling for PicoText will not work.
99
 # Otherwise special handling for PicoText will not work.
100
 class MapperReduceBrightness(MapperNull):
100
 class MapperReduceBrightness(MapperNull):
101
-    def __init__(self, g):
101
+    def __init__(self, g, i = None):
102
         super().__init__(g)
102
         super().__init__(g)
103
+        self.input = i
103
         self.last = None
104
         self.last = None
104
         self.connected = False
105
         self.connected = False
105
         self.refresh = 60 * 60 * 6
106
         self.refresh = 60 * 60 * 6
106
         self.factor = 1.0
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
     def fetch(self):
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
         # (year, month, day, hour, minute, second, ?, ?)
149
         # (year, month, day, hour, minute, second, ?, ?)
137
         now = time.localtime()
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
         if (now > morning) and (now < night):
166
         if (now > morning) and (now < night):
146
             self.factor = 1.0
167
             self.factor = 1.0
147
         else:
168
         else:
148
             self.factor = 0.42
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
     def adjust(self, color):
185
     def adjust(self, color):
151
         return (int(color[0] * self.factor), int(color[1] * self.factor), int(color[2] * self.factor))
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
     def loop_end(self):
194
     def loop_end(self):
154
         super().loop_end()
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
     def set_pixel(self, x, y, color):
203
     def set_pixel(self, x, y, color):
158
         color = self.adjust(color)
204
         color = self.adjust(color)

+ 1
- 1
net.py View File

122
     d.success(Solid(t, 1.0, (0, 255, 0)))
122
     d.success(Solid(t, 1.0, (0, 255, 0)))
123
     d.fail(Solid(t, 1.0, (255, 0, 0)))
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
 
69
 
70
         self.loop_start() # initialize with blank image for ScrollText constructor
70
         self.loop_start() # initialize with blank image for ScrollText constructor
71
 
71
 
72
+    def exit(self):
73
+        pass
74
+
72
     def loop_start(self):
75
     def loop_start(self):
73
         self.image = Image.new('RGB', (self.width, self.height))
76
         self.image = Image.new('RGB', (self.width, self.height))
74
         return False # no input, never quit on our own
77
         return False # no input, never quit on our own
76
     def loop_end(self):
79
     def loop_end(self):
77
         self.matrix.SetImage(self.image.convert('RGB'))
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
     def set_pixel(self, x, y, color):
82
     def set_pixel(self, x, y, color):
88
         if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
83
         if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
89
             return
84
             return
92
 
87
 
93
 if __name__ == "__main__":
88
 if __name__ == "__main__":
94
     t = PiMatrix(32, 32)
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
 
77
 
78
         self.loop_start() # initialize with blank image for ScrollText constructor
78
         self.loop_start() # initialize with blank image for ScrollText constructor
79
 
79
 
80
+    def exit(self):
81
+        self.matrix.stop()
82
+
80
     def battery(self):
83
     def battery(self):
81
         n = const(10)
84
         n = const(10)
82
         bits = const(10)
85
         bits = const(10)
152
         # update battery if necessary
155
         # update battery if necessary
153
         self.batteryCache(False)
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
     def set_pixel(self, x, y, color):
158
     def set_pixel(self, x, y, color):
168
         if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
159
         if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
169
             return
160
             return
303
         else:
294
         else:
304
             s.text("Drinks:", "bitmap8", 0)
295
             s.text("Drinks:", "bitmap8", 0)
305
 
296
 
306
-    t.loop(helper)
297
+    util.loop(t, helper)

+ 7
- 4
qr.py View File

49
                     self.c1 = (255, 255, 255)
49
                     self.c1 = (255, 255, 255)
50
                     self.c2 = (0, 0, 0)
50
                     self.c2 = (0, 0, 0)
51
                 else:
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
             else:
54
             else:
54
                 self.image = qr.make_image(fill_color = self.c1, back_color = self.c2)
55
                 self.image = qr.make_image(fill_color = self.c1, back_color = self.c2)
55
         else:
56
         else:
91
                     self.gui.set_pixel(x + self.xOff + self.image.width, y + self.yOff, self.c2)
92
                     self.gui.set_pixel(x + self.xOff + self.image.width, y + self.yOff, self.c2)
92
 
93
 
93
         if self.heading != None:
94
         if self.heading != None:
94
-            off = -10
95
+            off = 0
95
             if self.font == "bitmap6":
96
             if self.font == "bitmap6":
96
-                off -= 3
97
+                off = -14
98
+            elif self.font == "tom-thumb":
99
+                off = -11
97
 
100
 
98
             self.text.text(self.heading, self.font, 0, True, off)
101
             self.text.text(self.heading, self.font, 0, True, off)
99
 
102
 
135
             print(e)
138
             print(e)
136
             print()
139
             print()
137
 
140
 
138
-    t.loop(d.draw)
141
+    util.loop(t, d.draw)

+ 1
- 1
scroll.py View File

80
         m.add(ScrollText(t, s, fontName, 1, 75, (0, 255, 0), (0, 0, 25)))
80
         m.add(ScrollText(t, s, fontName, 1, 75, (0, 255, 0), (0, 0, 25)))
81
 
81
 
82
     m.restart()
82
     m.restart()
83
-    t.loop(m.draw)
83
+    util.loop(t, m.draw)

+ 17
- 9
snake.py View File

21
         self.speedup = su
21
         self.speedup = su
22
 
22
 
23
         self.winText = ScrollText(self.gui, "You Won!", "uushi",
23
         self.winText = ScrollText(self.gui, "You Won!", "uushi",
24
-                                  2, 75, (0, 255, 0))
24
+                                  2, 50, (0, 255, 0))
25
         self.loseText = ScrollText(self.gui, "Game Over!", "uushi",
25
         self.loseText = ScrollText(self.gui, "Game Over!", "uushi",
26
-                                   2, 75, (255, 0, 0))
26
+                                   2, 50, (255, 0, 0))
27
         self.scoreText = ScrollText(self.gui, "Score:", "uushi",
27
         self.scoreText = ScrollText(self.gui, "Score:", "uushi",
28
-                                    2, 75, sc)
28
+                                    2, 50, sc)
29
 
29
 
30
         random.seed()
30
         random.seed()
31
         self.restart()
31
         self.restart()
46
             "right": False,
46
             "right": False,
47
             "up": False,
47
             "up": False,
48
             "down": False,
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
         self.placeDot()
59
         self.placeDot()
71
     def buttons(self):
79
     def buttons(self):
72
         keys = self.input.get()
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
             self.directionTmp = "l"
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
             self.directionTmp = "r"
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
             self.directionTmp = "u"
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
             self.directionTmp = "d"
89
             self.directionTmp = "d"
82
         elif (keys["select"] and keys["start"] and (not self.old_keys["start"])) or (keys["start"] and keys["select"] and (not self.old_keys["select"])):
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
             self.restart()
91
             self.restart()
175
     i = InputWrapper()
183
     i = InputWrapper()
176
 
184
 
177
     import util
185
     import util
178
-    t = util.getTarget()
186
+    t = util.getTarget(i)
179
 
187
 
180
     d = Snake(t, i)
188
     d = Snake(t, i)
181
-    t.loop(d.draw)
189
+    util.loop(t, d.draw)

+ 1
- 1
solid.py View File

71
 
71
 
72
         d.draw()
72
         d.draw()
73
 
73
 
74
-    t.loop(helper)
74
+    util.loop(t, helper)

+ 1
- 1
splash.py View File

41
     import util
41
     import util
42
     t = util.getTarget()
42
     t = util.getTarget()
43
     s = SplashScreen(t)
43
     s = SplashScreen(t)
44
-    t.loop(s.draw)
44
+    util.loop(t, s.draw)

+ 4
- 13
test.py View File

13
 import pygame
13
 import pygame
14
 
14
 
15
 class TestGUI:
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
         self.width = width
17
         self.width = width
18
         self.height = height
18
         self.height = height
19
         self.multiplier = multiplier
19
         self.multiplier = multiplier
20
 
20
 
21
         # compatibility to PiMatrix
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
         pygame.display.init()
25
         pygame.display.init()
26
         self.screen = pygame.display.set_mode((self.width * self.multiplier, self.height * self.multiplier))
26
         self.screen = pygame.display.set_mode((self.width * self.multiplier, self.height * self.multiplier))
45
         pygame.display.flip()
45
         pygame.display.flip()
46
         self.clock.tick(30)
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
     def set_pixel(self, x, y, color):
48
     def set_pixel(self, x, y, color):
58
         if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
49
         if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
59
             return
50
             return
62
 
53
 
63
 if __name__ == "__main__":
54
 if __name__ == "__main__":
64
     t = TestGUI(32, 32)
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
 from scroll import ScrollText
10
 from scroll import ScrollText
11
 import time
11
 import time
12
 import random
12
 import random
13
+import util
13
 
14
 
14
 class Tetris:
15
 class Tetris:
15
     def __init__(self, g, i, ts = 0.5, to = 60.0, w = 10, h = 22):
16
     def __init__(self, g, i, ts = 0.5, to = 60.0, w = 10, h = 22):
20
         self.width = min(w, self.gui.width)
21
         self.width = min(w, self.gui.width)
21
         self.height = min(h, self.gui.height)
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
         self.endText = ScrollText(self.gui, "Game Over!", "uushi",
24
         self.endText = ScrollText(self.gui, "Game Over!", "uushi",
27
-                                   2, 75, (251, 72, 196))
25
+                                   2, 50, (251, 72, 196))
28
         self.scoreText = ScrollText(self.gui, "Score:", "uushi",
26
         self.scoreText = ScrollText(self.gui, "Score:", "uushi",
29
-                                    2, 75, (63, 255, 33))
27
+                                    2, 50, (63, 255, 33))
30
 
28
 
31
         self.bg = (0, 0, 0)
29
         self.bg = (0, 0, 0)
32
         self.colors = [
30
         self.colors = [
41
             #(255, 255, 255),
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
         # all [y][x] sub-lists must be the same length
49
         # all [y][x] sub-lists must be the same length
45
         self.pieces = [
50
         self.pieces = [
46
             # "I"
51
             # "I"
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
         random.seed()
114
         random.seed()
94
         self.restart()
115
         self.restart()
95
 
116
 
101
         self.done = False
122
         self.done = False
102
         self.data = [[self.bg for y in range(self.height)] for x in range(self.width)]
123
         self.data = [[self.bg for y in range(self.height)] for x in range(self.width)]
103
         self.piece = None
124
         self.piece = None
125
+        self.next_piece = None
104
         self.old_keys = {
126
         self.old_keys = {
105
             "left": False,
127
             "left": False,
106
             "right": False,
128
             "right": False,
107
             "up": False,
129
             "up": False,
108
             "down": False,
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
     def finished(self):
142
     def finished(self):
112
         if self.input == None:
143
         if self.input == None:
198
         return board_clear
229
         return board_clear
199
 
230
 
200
     def step(self):
231
     def step(self):
201
-        if self.piece == None:
202
-            justPlaced = True
203
-
232
+        if self.next_piece == None:
204
             # select a new piece type and color
233
             # select a new piece type and color
205
-            self.piece = [
234
+            self.next_piece = [
206
                 self.pieces[random.randrange(0, len(self.pieces))], # piece
235
                 self.pieces[random.randrange(0, len(self.pieces))], # piece
207
                 self.colors[random.randrange(0, len(self.colors))], # color
236
                 self.colors[random.randrange(0, len(self.colors))], # color
208
                 0, # x
237
                 0, # x
210
             ]
239
             ]
211
 
240
 
212
             # center the piece on top of the playing board
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
             if self.collision():
253
             if self.collision():
216
                 # new piece immediately collided. game over!
254
                 # new piece immediately collided. game over!
270
     def buttons(self):
308
     def buttons(self):
271
         keys = self.input.get()
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
             self.button = "l"
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
             self.button = "r"
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
             self.button = "u"
316
             self.button = "u"
279
-        elif keys["down"]:
317
+        elif keys["down"] and (not self.old_keys["select"]):
280
             self.button = "d"
318
             self.button = "d"
281
         elif (keys["select"] and keys["start"] and (not self.old_keys["start"])) or (keys["start"] and keys["select"] and (not self.old_keys["select"])):
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
             self.restart()
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
         self.old_keys = keys.copy()
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
     def draw(self):
345
     def draw(self):
346
+        if self.input != None:
347
+            self.buttons()
348
+        else:
349
+            # TODO "AI"
350
+            self.button = None
351
+
287
         if self.done:
352
         if self.done:
288
             if self.endText.finished():
353
             if self.endText.finished():
289
                 self.scoreText.draw()
354
                 self.scoreText.draw()
292
                 self.scoreText.restart()
357
                 self.scoreText.restart()
293
             return
358
             return
294
 
359
 
295
-        if self.input != None:
296
-            self.buttons()
297
-        else:
298
-            # TODO "AI"
299
-            self.button = None
300
-
301
         now = time.time()
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
             # don't let user stop falling pieces by moving/rotating endlessly
362
             # don't let user stop falling pieces by moving/rotating endlessly
304
             if (self.button != "l") and (self.button != "r") and (self.button != "u"):
363
             if (self.button != "l") and (self.button != "r") and (self.button != "u"):
305
                 self.last = now
364
                 self.last = now
310
                 self.scoreText.setText("Score: " + str(self.score), "uushi")
369
                 self.scoreText.setText("Score: " + str(self.score), "uushi")
311
                 self.endText.restart()
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
         for x in range(-1, self.width + 1):
378
         for x in range(-1, self.width + 1):
315
             for y in range(-1, self.height + 1):
379
             for y in range(-1, self.height + 1):
316
-                c = (255, 255, 255)
380
+                c = self.colors[1] # border color
317
                 if (x >= 0) and (y >= 0) and (x < self.width) and (y < self.height):
381
                 if (x >= 0) and (y >= 0) and (x < self.width) and (y < self.height):
318
                     c = self.data[x][y]
382
                     c = self.data[x][y]
319
-
320
                 self.gui.set_pixel(x + 1 + self.x_off, y + 1 + self.y_off, c)
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
 if __name__ == "__main__":
413
 if __name__ == "__main__":
323
     # Need to import InputWrapper before initializing RGB Matrix on Pi
414
     # Need to import InputWrapper before initializing RGB Matrix on Pi
324
     from gamepad import InputWrapper
415
     from gamepad import InputWrapper
325
     i = InputWrapper()
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
     d = Tetris(t, i)
427
     d = Tetris(t, i)
331
-    t.loop(d.draw)
428
+    util.loop(t, d.draw)

+ 14
- 4
util.py View File

29
 
29
 
30
     return targetPlatform == "pico"
30
     return targetPlatform == "pico"
31
 
31
 
32
-def getTarget():
32
+def getTarget(i = None):
33
     global targetPlatform, cachedTarget
33
     global targetPlatform, cachedTarget
34
 
34
 
35
     if cachedTarget != None:
35
     if cachedTarget != None:
42
         pi = PiMatrix()
42
         pi = PiMatrix()
43
 
43
 
44
         # TODO hard-coded adjustments
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
         #target = MapperStripToRect(col)
48
         #target = MapperStripToRect(col)
48
         target = col
49
         target = col
49
 
50
 
68
 
69
 
69
             # TODO hard-coded adjustments
70
             # TODO hard-coded adjustments
70
             from mapper import MapperReduceBrightness
71
             from mapper import MapperReduceBrightness
71
-            target = MapperReduceBrightness(pico)
72
+            target = MapperReduceBrightness(pico, i)
72
 
73
 
73
             if targetPlatform == None:
74
             if targetPlatform == None:
74
                 # only print once
75
                 # only print once
223
         return PicoText
224
         return PicoText
224
 
225
 
225
     return None
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