ic master
authorFrank DeMarco <if.self.end@gmail.com>
Tue, 28 Jan 2020 04:25:20 +0000 (23:25 -0500)
committerFrank DeMarco <if.self.end@gmail.com>
Tue, 28 Jan 2020 04:25:20 +0000 (23:25 -0500)
12 files changed:
.gitignore [new file with mode: 0644]
.gitmodules [new file with mode: 0644]
Cantarell.ttf [new file with mode: 0755]
MANIFEST.in [new file with mode: 0644]
OPEN-GAME [new file with mode: 0755]
SwimmyBoys.py [new file with mode: 0644]
config [new file with mode: 0644]
fish/fish-1.png [new file with mode: 0644]
fish/fish-2.png [new file with mode: 0644]
lib/__init__.py [new file with mode: 0644]
lib/pgfw [new submodule]
setup.py [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..52cc826
--- /dev/null
@@ -0,0 +1,4 @@
+MANIFEST
+*.pyc
+__pycache__
+dist/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..66a83be
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "lib/pgfw"]
+       path = lib/pgfw
+       url = makar:/var/www/git/pgfw
diff --git a/Cantarell.ttf b/Cantarell.ttf
new file mode 100755 (executable)
index 0000000..ff7a11d
Binary files /dev/null and b/Cantarell.ttf differ
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644 (file)
index 0000000..9933166
--- /dev/null
@@ -0,0 +1 @@
+include SwimmyBoys.py
diff --git a/OPEN-GAME b/OPEN-GAME
new file mode 100755 (executable)
index 0000000..3104822
--- /dev/null
+++ b/OPEN-GAME
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+from os import environ, execvp, chdir, getcwd
+from os.path import exists, join, dirname
+from sys import version_info, argv
+
+def can_import(module_name):
+    try:
+        __import__(module_name)
+    except ImportError:
+        return False
+    else:
+        return True
+
+def is_python_3():
+    return version_info[0] >= 3
+
+def is_current_version(file_name):
+    version = map(int, file_name.replace("python", "").split("."))
+    return version == list(version_info)[:2]
+
+def launch_alternative(alternatives):
+    for alternative in alternatives:
+        if not is_current_version(alternative):
+            for root in environ["PATH"].split(":"):
+                if exists(join(root, alternative)):
+                    execvp(alternative, [alternative] + argv)
+
+def move_to_executable():
+    chdir(dirname(argv[0]))
+
+# if is_python_3():
+#     launch_alternative(["python2", "python2.7", "python2.6"])
+
+# if maxint >> 33:
+#     launch_alternative(["python-32", "python2-32", "python2.7-32", "python2.6-32"])
+
+# if not can_import("pygame"):
+#     launch_alternative(["python2.7", "python2.6"])
+
+if "--go-to-dir" in argv:
+    move_to_executable()
+
+from SwimmyBoys import SwimmyBoys
+
+SwimmyBoys().run()
diff --git a/SwimmyBoys.py b/SwimmyBoys.py
new file mode 100644 (file)
index 0000000..9053d19
--- /dev/null
@@ -0,0 +1,265 @@
+import random, pygame, math
+
+from lib.pgfw.pgfw.Game import Game
+from lib.pgfw.pgfw.Sprite import Sprite
+from lib.pgfw.pgfw.Note import Note, Chord
+from lib.pgfw.pgfw.Vector import Vector
+from lib.pgfw.pgfw.extension import *
+
+class SwimmyBoys(Game):
+
+    def __init__(self):
+        pygame.mixer.pre_init(44100, -16, 2, 4096)
+        Game.__init__(self)
+        pygame.mixer.set_num_channels(64)
+        self.nodes = []
+        channel_count = pygame.mixer.get_num_channels()
+        for ii in range(channel_count):
+            self.nodes.append(Node(self, pygame.mixer.Channel(ii), float(ii) / ((channel_count - 1) / 2) - 1))
+        self.notes = {}
+        self.shapes = Note.SQUARE, Note.TRIANGLE, Note.SAW, Note.SINE, Note.DIRTY
+        for octave in range(8):
+            self.notes[octave] = {}
+            for name in Note.names:
+                self.notes[octave][name] = Note(name, octave, shape=Note.SQUARE, volume=.8)
+        self.register(self.inc, self.chime, self.shuffle, self.circle, self.sine,
+                      self.move_sine, self.increase_t, self.cluster, self.explode, self.fall,
+                      self.collapse, self.center, self.leave)
+        self.octave = 0
+        self.t = 0
+        self.wave_t = 0
+        self.period = 32
+        self.title = Sprite(self)
+        font = pygame.font.Font("Cantarell.ttf", 48)
+        frame = font.render("swimmy boys", True, (255, 255, 0))
+        self.title.add_frame(frame)
+        self.title.location.center = self.get_display_surface().get_rect().center
+        self.play(self.center, delay=5000, play_once=True)
+        self.play(self.circle, delay=14000, play_once=True)
+        self.play(self.sine, delay=18000, play_once=True)
+        self.play(self.move_sine, delay=25000)
+        self.play(self.increase_t, delay=34000)
+        self.play(self.cluster, delay=50000, play_once=True)
+        self.play(self.explode, delay=62000, play_once=True)
+        self.play(self.fall, delay=70000, play_once=True)
+        self.play(self.collapse, delay=76000, play_once=True)
+        self.play(self.leave, delay=82000, play_once=True)
+        # self.play(self.show_title, delay=80000, play_once=True)
+        # self.play(self.explode, delay=0, play_once=True)
+
+    def leave(self):
+        self.mainloop.stop()
+
+    def center(self):
+        self.title.hide()
+        for node in self.nodes:
+            node.set_note(0, random.choice(Note.names))
+            node.play_note()
+            node.speed = .01
+            node.go(Vector(0, 0))
+
+    def circle(self):
+        for ii in range(len(self.nodes)):
+            angle = float(ii) / len(self.nodes) * 360
+            self.nodes[ii].speed = .02
+            self.nodes[ii].go(get_endpoint(self.nodes[ii].position, angle, .7))
+
+    def sine(self):
+        for node in self.nodes:
+            node.speed = .015
+        self.set_to_sine()
+
+    def move_sine(self):
+        self.t += 1
+        for node in self.nodes:
+            node.speed = .1
+        self.period = 16
+        self.set_to_sine()
+
+    def set_to_sine(self):
+        for ii in range(len(self.nodes)):
+            x = float(ii) / ((len(self.nodes) - 1) / 2.0) - 1
+            y = math.sin((self.t + ii) * 2.0 * math.pi / self.period) * 1
+            self.nodes[ii].go(Vector(x, y))
+
+    def increase_t(self):
+        self.t *= 1.2
+
+    def cluster(self):
+        self.halt(self.move_sine)
+        self.halt(self.increase_t)
+        for ii in range(len(self.nodes)):
+            cluster = ii % 4
+            self.nodes[ii].speed = .01
+            if cluster == 0:
+                self.nodes[ii].go(Vector(-.5, .5))
+            elif cluster == 1:
+                self.nodes[ii].go(Vector(.5, .5))
+            elif cluster == 2:
+                self.nodes[ii].go(Vector(.5, -.5))
+            elif cluster == 3:
+                self.nodes[ii].go(Vector(-.5, -.5))
+
+    def explode(self):
+        for node in self.nodes:
+            node.exploding = True
+            node.speed = random.random() * .2 + .1
+            node.direction = random.randint(0, 360)
+
+    def fall(self):
+        for node in self.nodes:
+            node.speed = .05
+            node.go(Vector(node.position.x, -1))
+
+    def collapse(self):
+        self.title.unhide()
+        for node in self.nodes:
+            node.speed = .07
+            node.exploding = False
+            node.go(Vector(node.position.x, -1))
+
+    def inc(self):
+        index = Note.names.index(self.name) + 1
+        if index >= len(Note.names):
+            self.name = Note.names[0]
+            self.octave += 1
+            if self.octave >= len(self.notes.keys()):
+                self.octave = 0
+        else:
+            self.name = Note.names[index]
+
+    def shuffle(self):
+        for channel in self.channels:
+            channel.play(self.notes[self.octave][random.choice(Note.names)], -1)
+        self.octave = (self.octave + 1) % 8
+
+    def reset(self):
+        self.octave = 0
+        self.name = "C"
+
+    def chime(self):
+        note = self.notes[self.octave][self.name]
+        note.play(fade_in=800, fadeout=800)
+        for _ in range(random.randint(0, 5)):
+            self.inc()
+
+    def update(self):
+        # self.get_display_surface().fill((80, 80, 80))
+        ds = self.get_display_surface()
+        dsr = ds.get_rect()
+        for ii in range(6):
+            limit = (-100, 40, 110, 200, 280, 340)[ii]
+            # amplitude = (40, 20, 30, 12, 20, 12)[ii]
+            # period = (-100, 40, 110, 200, 280, 340)[ii]
+            amplitude = 16
+            period = 132
+            step = 1
+            color = ((100, 190, 255), (90, 170, 255), (80, 150, 245), (70, 130, 230), (60, 110, 215), (50, 90, 190))[ii]
+            # color = pygame.Color(*color)
+            # hue, sat, light, alpha = color.hsla
+            # color = get_hsla_color(int((hue - 60) % 360), sat, light - 10, alpha)
+            for x in range(0, dsr.w, step):
+                top = int(round(math.sin((self.wave_t + ii * .25 + x) * 2.0 * math.pi / period) * amplitude + limit + amplitude / 2.0))
+                ds.fill(color, (x, top, step, dsr.bottom - top))
+        self.wave_t -= 2
+        self.title.update()
+        for node in self.nodes:
+            node.update()
+
+
+class Node(Sprite):
+
+    def __init__(self, parent, channel, x):
+        Sprite.__init__(self, parent, 300)
+        self.channel = channel
+        self.position = Vector(x, -1)
+        width = 21
+        center = width // 2, width // 2
+        # for angle in range(0, 360, 5):
+        #     frame = pygame.Surface((width, width), SRCALPHA)
+        #     points = get_endpoint(center, angle, width // 2), \
+        #         get_endpoint(center, angle + 120, width // 2), \
+        #         get_endpoint(center, angle + 240, width // 2)
+        #     pygame.draw.polygon(frame, (0, 0, 0), points, 1)
+        #     self.add_frame(frame)
+        self.load_from_path("fish", True)
+        self.note = None
+        self.walking_to = None
+        self.speed = .002
+        self.exploding = False
+        self.direction = None
+        self.register(self.walk)
+
+    def set_note(self, octave, name):
+        self.note = self.get_game().notes[octave][name]
+
+    def inc(self, amount=1):
+        for _ in range(abs(amount)):
+            self.step(amount > 0)
+        self.play_note()
+
+    def step(self, up=True):
+        name, octave = self.note.name, self.note.octave
+        index = Note.names.index(name) + [-1, 1][up]
+        notes = self.get_game().notes
+        if index >= len(Note.names):
+            index = 0
+            octave += 1
+            if octave >= len(notes.keys()):
+                octave = 0
+        elif index < 0:
+            index = len(Note.names) - 1
+            octave -= 1
+            if octave < 0:
+                octave = len(notes.keys()) - 1
+        name = Note.names[index]
+        self.set_note(octave, name)
+
+    def play_note(self, fade=0):
+        self.channel.play(self.note, -1)
+
+    def get_panning(self, position):
+        position = (position + 1) / 2.0
+        return 1 - max(0, ((position - .5) * 2)), \
+               1 + min(0, ((position - .5) * 2))
+
+    def get_closest_note(self):
+        notes = self.get_game().notes
+        frequency = math.exp((self.position.y + 1) / 2.0 * (8.28 - 2.79) + 2.79)
+        closest_distance = None
+        closest_note = None
+        for octave in sorted(notes.keys()):
+            for name in Note.names:
+                distance = abs(frequency - notes[octave][name].frequency)
+                if closest_distance is None or distance < closest_distance:
+                    closest_distance = distance
+                    closest_note = notes[octave][name]
+        return closest_note
+
+    def go(self, position):
+        self.walking_to = position
+        self.step = get_step(self.position, self.walking_to, self.speed)
+        self.play(self.walk)
+
+    def walk(self):
+        self.position.move(*self.step)
+        if get_distance(self.position, self.walking_to) <= self.speed:
+            self.position = self.walking_to.copy()
+            self.halt(self.walk)
+
+    def update(self):
+        closest = self.get_closest_note()
+        if self.note is None or self.note != closest:
+            self.note = closest
+            self.play_note()
+        self.channel.set_volume(*self.get_panning(self.position.x))
+        ds = self.get_display_surface()
+        dsr = ds.get_rect()
+        if self.exploding:
+            self.position.move(*get_delta(self.direction, self.speed))
+            if self.position.x > 1 or self.position.x < -1:
+                self.direction = -self.direction
+            if self.position.y > 1 or self.position.y < -1:
+                self.direction = 180 - self.direction
+        self.location.center = (self.position.x + 1) / 2.0 * dsr.w, (self.position.y * -1 + 1) / 2.0 * dsr.h
+        Sprite.update(self)
diff --git a/config b/config
new file mode 100644 (file)
index 0000000..19acb17
--- /dev/null
+++ b/config
@@ -0,0 +1,14 @@
+[setup]
+title = swimmy boys
+url = http://shampoo.ooo/
+version = 0.1
+init-script = OPEN-GAME
+additional-packages = lib
+data-exclude = local/, *.pyc, __pycache__, dist/
+
+[display]
+caption = swimmy boys
+dimensions = 720, 405
+
+[mouse]
+visible = no
diff --git a/fish/fish-1.png b/fish/fish-1.png
new file mode 100644 (file)
index 0000000..caca195
Binary files /dev/null and b/fish/fish-1.png differ
diff --git a/fish/fish-2.png b/fish/fish-2.png
new file mode 100644 (file)
index 0000000..914fbf5
Binary files /dev/null and b/fish/fish-2.png differ
diff --git a/lib/__init__.py b/lib/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/pgfw b/lib/pgfw
new file mode 160000 (submodule)
index 0000000..7a4f318
--- /dev/null
+++ b/lib/pgfw
@@ -0,0 +1 @@
+Subproject commit 7a4f318ac2fca2f9c5d533a50b85e094de29b3ad
diff --git a/setup.py b/setup.py
new file mode 100644 (file)
index 0000000..23945ef
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,31 @@
+from sys import platform
+
+
+if __name__ == "__main__":
+    if platform == "darwin":
+        from setuptools import setup, find_packages
+        from lib.pgfw.pgfw.Configuration import Configuration
+        from lib.pgfw.pgfw.Setup import Setup
+        config = Configuration()
+        setup_obj = Setup()
+        version = config.get_section("setup")["version"]
+        name = setup_obj.translate_title()
+        plist = dict(
+            CFBundleIconFile=name,
+            CFBundleName=name,
+            CFBundleShortVersionString=version,
+            CFBundleGetInfoString=' '.join([name, version]),
+            CFBundleExecutable=name,
+            CFBundleIdentifier='org.' + name.lower())
+        setup(name=name,
+              version=version,
+              app=[dict(script="OPEN-GAME", plist=plist)],
+              setup_requires=["py2app"],
+              options=dict(py2app=dict(arch="i386",)),
+              data_files=["OPEN-GAME", "Cakewalk.py", "resource", "lib", "config"])
+    elif platform == "win32":
+        from lib.pgfw.pgfw.SetupWin import SetupWin
+        SetupWin().setup()
+    else:
+        from lib.pgfw.pgfw.Setup import Setup
+        Setup().setup()