Przeglądaj źródła

game of life, initial pi support

Thomas Buck 1 rok temu
rodzic
commit
749f6748e2
8 zmienionych plików z 225 dodań i 28 usunięć
  1. 13
    9
      draw.py
  2. 107
    0
      life.py
  3. 18
    7
      manager.py
  4. 54
    0
      pi.py
  5. 10
    4
      solid.py
  6. 9
    3
      splash.py
  7. 4
    1
      test.py
  8. 10
    4
      weather.py

+ 13
- 9
draw.py Wyświetl plik

@@ -1,4 +1,4 @@
1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2 2
 
3 3
 from bdfparser import Font
4 4
 from PIL import Image
@@ -19,9 +19,9 @@ class DrawText:
19 19
                 continue
20 20
 
21 21
             font = Font(os.path.join(fontDir, filename))
22
-            print(f"{filename} global size is "
23
-                f"{font.headers['fbbx']} x {font.headers['fbby']} (pixel), "
24
-                f"it contains {len(font)} glyphs.")
22
+            #print(f"{filename} global size is "
23
+            #    f"{font.headers['fbbx']} x {font.headers['fbby']} (pixel), "
24
+            #    f"it contains {len(font)} glyphs.")
25 25
 
26 26
             # TODO hard-coded per-font offsets
27 27
             offset = 0
@@ -67,9 +67,7 @@ class ScrollText:
67 67
         self.speed = 1.0 / s
68 68
 
69 69
         self.width = self.drawer.text(self.text)
70
-        self.offset = -self.gui.width
71
-        self.last = time.time()
72
-        self.count = 0
70
+        self.restart()
73 71
 
74 72
     def restart(self):
75 73
         self.offset = -self.gui.width
@@ -91,7 +89,13 @@ class ScrollText:
91 89
         self.drawer.text(self.text, self.offset)
92 90
 
93 91
 if __name__ == "__main__":
94
-    from test import TestGUI
95
-    t = TestGUI(32, 32)
92
+    import platform
93
+    t = None
94
+    if platform.machine() == "armv7l":
95
+        from pi import PiMatrix
96
+        t = PiMatrix()
97
+    else:
98
+        from test import TestGUI
99
+        t = TestGUI()
96 100
     d = ScrollText(t, "Hello, World!")
97 101
     t.debug_loop(d.draw)

+ 107
- 0
life.py Wyświetl plik

@@ -0,0 +1,107 @@
1
+#!/usr/bin/env python3
2
+
3
+import time
4
+import random
5
+
6
+class GameOfLife:
7
+    def __init__(self, g, f = 20, c1 = (255, 255, 255), c2 = (0, 0, 0), t = 30.0):
8
+        self.gui = g
9
+        self.interval = 1.0 / f
10
+        self.colorFG = c1
11
+        self.colorBG = c2
12
+        self.timeout = t
13
+        random.seed()
14
+        self.restart()
15
+
16
+    def restart(self):
17
+        self.data = self.init()
18
+        self.start = time.time()
19
+        self.last = time.time()
20
+        self.done = False
21
+
22
+    def init(self):
23
+        data = []
24
+        for x in range(0, self.gui.width):
25
+            d = []
26
+            for y in range(0, self.gui.height):
27
+                v = False
28
+                if random.randrange(0, 2) == 1:
29
+                    v = True
30
+
31
+                d.append(v)
32
+            data.append(d)
33
+        return data
34
+
35
+    def finished(self):
36
+        if self.done or ((time.time() - self.start) > self.timeout):
37
+            return True
38
+        return False
39
+
40
+    def alive(self, data, x, y):
41
+        if (x < 0) or (y < 0) or (x >= self.gui.width) or (y >= self.gui.height):
42
+            return False
43
+        return data[x][y]
44
+
45
+    def live_neighbours(self, data, x, y):
46
+        c = 0
47
+        for xOff in range(-1, 2):
48
+            for yOff in range(-1, 2):
49
+                if (xOff == 0) and (yOff == 0):
50
+                    continue
51
+                if self.alive(data, x + xOff, y + yOff):
52
+                    c += 1
53
+        return c
54
+
55
+    def step(self):
56
+        # deep copy
57
+        old = [x[:] for x in self.data]
58
+
59
+        for x in range(0, self.gui.width):
60
+            for y in range(0, self.gui.height):
61
+                ln = self.live_neighbours(old, x, y)
62
+                if old[x][y] and ((ln == 2) or (ln == 3)):
63
+                    # Any live cell with two or three live neighbours survives.
64
+                    self.data[x][y] = True
65
+                elif (not old[x][y]) and (ln == 3):
66
+                    # Any dead cell with three live neighbours becomes a live cell.
67
+                    self.data[x][y] = True
68
+                else:
69
+                    # All other live cells die in the next generation. Similarly, all other dead cells stay dead.
70
+                    self.data[x][y] = False
71
+
72
+        # compare new and old states
73
+        same = True
74
+        for x in range(0, self.gui.width):
75
+            for y in range(0, self.gui.height):
76
+                if self.data[x][y] != old[x][y]:
77
+                    same = False
78
+                    break
79
+        self.done = same
80
+
81
+    def draw(self):
82
+        if (time.time() - self.last) > self.interval:
83
+            self.step()
84
+            self.last = time.time()
85
+
86
+        for x in range(0, self.gui.width):
87
+            for y in range(0, self.gui.height):
88
+                if self.data[x][y]:
89
+                    self.gui.set_pixel(x, y, self.colorFG)
90
+                else:
91
+                    self.gui.set_pixel(x, y, self.colorBG)
92
+
93
+if __name__ == "__main__":
94
+    import platform
95
+    t = None
96
+    if platform.machine() == "armv7l":
97
+        from pi import PiMatrix
98
+        t = PiMatrix()
99
+    else:
100
+        from test import TestGUI
101
+        t = TestGUI()
102
+    g = GameOfLife(t)
103
+    def helper():
104
+        if g.finished():
105
+            g.restart()
106
+        g.draw()
107
+    t.debug_loop(helper)

+ 18
- 7
manager.py Wyświetl plik

@@ -1,4 +1,4 @@
1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2 2
 
3 3
 import time
4 4
 
@@ -29,25 +29,36 @@ class Manager:
29 29
                 self.screens[self.index][0].restart()
30 30
 
31 31
 if __name__ == "__main__":
32
-    from test import TestGUI
33 32
     from splash import SplashScreen
34 33
     #from weather import WeatherScreen
35 34
     from draw import ScrollText
36 35
     from solid import Solid
36
+    from life import GameOfLife
37
+
38
+    import platform
39
+    t = None
40
+    if platform.machine() == "armv7l":
41
+        from pi import PiMatrix
42
+        t = PiMatrix()
43
+    else:
44
+        from test import TestGUI
45
+        t = TestGUI()
37 46
 
38
-    t = TestGUI(32, 32)
39 47
     m = Manager(t)
40 48
 
41 49
     m.add(SplashScreen(t), 2)
42
-    m.add(Solid(t, 3.0))
50
+    m.add(Solid(t, 1.0))
43 51
 
44 52
     #m.add(WeatherScreen(t), 4)
45
-    #m.add(Solid(t, 3.0))
53
+    #m.add(Solid(t, 1.0))
46 54
 
47 55
     m.add(ScrollText(t, "This appears once"))
48
-    m.add(Solid(t, 3.0))
56
+    m.add(Solid(t, 1.0))
49 57
 
50 58
     m.add(ScrollText(t, "And this twice...", 2))
51
-    m.add(Solid(t, 3.0))
59
+    m.add(Solid(t, 1.0))
60
+
61
+    m.add(GameOfLife(t, 20, (0, 255, 0), (0, 0, 0), 20.0))
62
+    m.add(Solid(t, 1.0))
52 63
 
53 64
     t.debug_loop(m.loop)

+ 54
- 0
pi.py Wyświetl plik

@@ -0,0 +1,54 @@
1
+#!/usr/bin/env python3
2
+
3
+from rgbmatrix import RGBMatrix, RGBMatrixOptions
4
+from PIL import Image
5
+
6
+class PiMatrix:
7
+    def __init__(self):
8
+        # TODO configurable
9
+        self.width = 32
10
+        self.height = 32
11
+
12
+        options = RGBMatrixOptions()
13
+        options.rows = 32
14
+        options.cols = 32
15
+        options.chain_length = 1
16
+        options.parallel = 1
17
+        options.row_address_type = 0
18
+        options.multiplexing = 0
19
+        options.pwm_bits = 11
20
+        options.brightness = 100
21
+        options.pwm_lsb_nanoseconds = 130
22
+        options.led_rgb_sequence = 'RGB'
23
+        #options.hardware_mapping = 'regular'  # If you have an Adafruit HAT: 'adafruit-hat'
24
+        options.gpio_slowdown = 2
25
+        options.pixel_mapper_config = "Rotate:270"
26
+
27
+        self.matrix = RGBMatrix(options = options)
28
+
29
+        self.loop_start() # initialize with blank image for ScrollText constructor
30
+
31
+    def loop_start(self):
32
+        self.image = Image.new('RGB', (self.width, self.height))
33
+        return False # no input, never quit on our own
34
+
35
+    def loop_end(self):
36
+        self.matrix.SetImage(self.image.convert('RGB'))
37
+
38
+    def debug_loop(self, func = None):
39
+        while True:
40
+            if self.loop_start():
41
+                break
42
+            if func != None:
43
+                func()
44
+            self.loop_end()
45
+
46
+    def set_pixel(self, x, y, color):
47
+        if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
48
+            return
49
+
50
+        self.image.putpixel((int(x), int(y)), color)
51
+
52
+if __name__ == "__main__":
53
+    t = PiMatrix()
54
+    t.debug_loop(lambda: t.set_pixel(15, 15, (255, 255, 255)))

+ 10
- 4
solid.py Wyświetl plik

@@ -1,4 +1,4 @@
1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2 2
 
3 3
 import time
4 4
 
@@ -7,7 +7,7 @@ class Solid:
7 7
         self.gui = g
8 8
         self.time = t
9 9
         self.color = c
10
-        self.start = time.time()
10
+        self.restart()
11 11
 
12 12
     def restart(self):
13 13
         self.start = time.time()
@@ -21,7 +21,13 @@ class Solid:
21 21
                 self.gui.set_pixel(x, y, self.color)
22 22
 
23 23
 if __name__ == "__main__":
24
-    from test import TestGUI
25
-    t = TestGUI(32, 32)
24
+    import platform
25
+    t = None
26
+    if platform.machine() == "armv7l":
27
+        from pi import PiMatrix
28
+        t = PiMatrix()
29
+    else:
30
+        from test import TestGUI
31
+        t = TestGUI()
26 32
     d = ScrollText(t, "Hello, World!")
27 33
     t.debug_loop(d.draw)

+ 9
- 3
splash.py Wyświetl plik

@@ -1,4 +1,4 @@
1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2 2
 
3 3
 class SplashScreen:
4 4
     def __init__(self, g, width = 32, height = 32):
@@ -25,8 +25,14 @@ class SplashScreen:
25 25
         pass
26 26
 
27 27
 if __name__ == "__main__":
28
-    from test import TestGUI
29
-    t = TestGUI()
28
+    import platform
29
+    t = None
30
+    if platform.machine() == "armv7l":
31
+        from pi import PiMatrix
32
+        t = PiMatrix()
33
+    else:
34
+        from test import TestGUI
35
+        t = TestGUI()
30 36
     s = SplashScreen(t)
31 37
     s.draw()
32 38
     t.debug_loop(s.draw)

+ 4
- 1
test.py Wyświetl plik

@@ -1,4 +1,4 @@
1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2 2
 
3 3
 import pygame
4 4
 
@@ -38,6 +38,9 @@ class TestGUI:
38 38
         self.exit()
39 39
 
40 40
     def set_pixel(self, x, y, color):
41
+        if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
42
+            return
43
+
41 44
         pygame.draw.rect(self.screen, color, pygame.Rect(x * self.multiplier, y * self.multiplier, self.multiplier, self.multiplier))
42 45
 
43 46
 if __name__ == "__main__":

+ 10
- 4
weather.py Wyświetl plik

@@ -1,11 +1,11 @@
1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2 2
 
3 3
 from pyowm.owm import OWM
4 4
 from pyowm.utils.config import get_default_config
5 5
 
6 6
 import time
7 7
 
8
-api_key = "API_KEY_HERE"
8
+api_key = "7de9d39fd4476f811000ceecbbe69376"
9 9
 
10 10
 class WeatherScreen:
11 11
     def __init__(self, gui, latitude = 47.7174, longitude = 9.3924, language = "de", refresh = 600, width = 32, height = 32):
@@ -59,8 +59,14 @@ class WeatherScreen:
59 59
         pass
60 60
 
61 61
 if __name__ == "__main__":
62
-    from test import TestGUI
63
-    t = TestGUI()
62
+    import platform
63
+    t = None
64
+    if platform.machine() == "armv7l":
65
+        from pi import PiMatrix
66
+        t = PiMatrix()
67
+    else:
68
+        from test import TestGUI
69
+        t = TestGUI()
64 70
     s = WeatherScreen(t)
65 71
     s.draw()
66 72
     t.debug_loop(s.draw)

Ładowanie…
Anuluj
Zapisz