Browse Source

game of life, initial pi support

Thomas Buck 1 year ago
parent
commit
749f6748e2
8 changed files with 225 additions and 28 deletions
  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 View File

1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2
 
2
 
3
 from bdfparser import Font
3
 from bdfparser import Font
4
 from PIL import Image
4
 from PIL import Image
19
                 continue
19
                 continue
20
 
20
 
21
             font = Font(os.path.join(fontDir, filename))
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
             # TODO hard-coded per-font offsets
26
             # TODO hard-coded per-font offsets
27
             offset = 0
27
             offset = 0
67
         self.speed = 1.0 / s
67
         self.speed = 1.0 / s
68
 
68
 
69
         self.width = self.drawer.text(self.text)
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
     def restart(self):
72
     def restart(self):
75
         self.offset = -self.gui.width
73
         self.offset = -self.gui.width
91
         self.drawer.text(self.text, self.offset)
89
         self.drawer.text(self.text, self.offset)
92
 
90
 
93
 if __name__ == "__main__":
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
     d = ScrollText(t, "Hello, World!")
100
     d = ScrollText(t, "Hello, World!")
97
     t.debug_loop(d.draw)
101
     t.debug_loop(d.draw)

+ 107
- 0
life.py View File

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 View File

1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2
 
2
 
3
 import time
3
 import time
4
 
4
 
29
                 self.screens[self.index][0].restart()
29
                 self.screens[self.index][0].restart()
30
 
30
 
31
 if __name__ == "__main__":
31
 if __name__ == "__main__":
32
-    from test import TestGUI
33
     from splash import SplashScreen
32
     from splash import SplashScreen
34
     #from weather import WeatherScreen
33
     #from weather import WeatherScreen
35
     from draw import ScrollText
34
     from draw import ScrollText
36
     from solid import Solid
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
     m = Manager(t)
47
     m = Manager(t)
40
 
48
 
41
     m.add(SplashScreen(t), 2)
49
     m.add(SplashScreen(t), 2)
42
-    m.add(Solid(t, 3.0))
50
+    m.add(Solid(t, 1.0))
43
 
51
 
44
     #m.add(WeatherScreen(t), 4)
52
     #m.add(WeatherScreen(t), 4)
45
-    #m.add(Solid(t, 3.0))
53
+    #m.add(Solid(t, 1.0))
46
 
54
 
47
     m.add(ScrollText(t, "This appears once"))
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
     m.add(ScrollText(t, "And this twice...", 2))
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
     t.debug_loop(m.loop)
64
     t.debug_loop(m.loop)

+ 54
- 0
pi.py View File

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 View File

1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2
 
2
 
3
 import time
3
 import time
4
 
4
 
7
         self.gui = g
7
         self.gui = g
8
         self.time = t
8
         self.time = t
9
         self.color = c
9
         self.color = c
10
-        self.start = time.time()
10
+        self.restart()
11
 
11
 
12
     def restart(self):
12
     def restart(self):
13
         self.start = time.time()
13
         self.start = time.time()
21
                 self.gui.set_pixel(x, y, self.color)
21
                 self.gui.set_pixel(x, y, self.color)
22
 
22
 
23
 if __name__ == "__main__":
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
     d = ScrollText(t, "Hello, World!")
32
     d = ScrollText(t, "Hello, World!")
27
     t.debug_loop(d.draw)
33
     t.debug_loop(d.draw)

+ 9
- 3
splash.py View File

1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2
 
2
 
3
 class SplashScreen:
3
 class SplashScreen:
4
     def __init__(self, g, width = 32, height = 32):
4
     def __init__(self, g, width = 32, height = 32):
25
         pass
25
         pass
26
 
26
 
27
 if __name__ == "__main__":
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
     s = SplashScreen(t)
36
     s = SplashScreen(t)
31
     s.draw()
37
     s.draw()
32
     t.debug_loop(s.draw)
38
     t.debug_loop(s.draw)

+ 4
- 1
test.py View File

1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2
 
2
 
3
 import pygame
3
 import pygame
4
 
4
 
38
         self.exit()
38
         self.exit()
39
 
39
 
40
     def set_pixel(self, x, y, color):
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
         pygame.draw.rect(self.screen, color, pygame.Rect(x * self.multiplier, y * self.multiplier, self.multiplier, self.multiplier))
44
         pygame.draw.rect(self.screen, color, pygame.Rect(x * self.multiplier, y * self.multiplier, self.multiplier, self.multiplier))
42
 
45
 
43
 if __name__ == "__main__":
46
 if __name__ == "__main__":

+ 10
- 4
weather.py View File

1
-#!/usr/bin/env python
1
+#!/usr/bin/env python3
2
 
2
 
3
 from pyowm.owm import OWM
3
 from pyowm.owm import OWM
4
 from pyowm.utils.config import get_default_config
4
 from pyowm.utils.config import get_default_config
5
 
5
 
6
 import time
6
 import time
7
 
7
 
8
-api_key = "API_KEY_HERE"
8
+api_key = "7de9d39fd4476f811000ceecbbe69376"
9
 
9
 
10
 class WeatherScreen:
10
 class WeatherScreen:
11
     def __init__(self, gui, latitude = 47.7174, longitude = 9.3924, language = "de", refresh = 600, width = 32, height = 32):
11
     def __init__(self, gui, latitude = 47.7174, longitude = 9.3924, language = "de", refresh = 600, width = 32, height = 32):
59
         pass
59
         pass
60
 
60
 
61
 if __name__ == "__main__":
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
     s = WeatherScreen(t)
70
     s = WeatherScreen(t)
65
     s.draw()
71
     s.draw()
66
     t.debug_loop(s.draw)
72
     t.debug_loop(s.draw)

Loading…
Cancel
Save