diff --git a/audiosys.py b/audiosys.py index 56ce38e..101cc28 100644 --- a/audiosys.py +++ b/audiosys.py @@ -1,7 +1,75 @@ -import simpleaudio -class sound: +import simpleaudio as sa +import wave +import base64 +import os + +# channels OK +# bytes per sample OK +# sample rate OK + +class handler: def __init__(self): - raise NotImplementedError() + self.storage = {} + def loadfromstring(self, target): + # decode frames from b64 + frames = base64.b64decode(target[1]) + # rebuild tuple + temp = (frames, target[2], target[3], target[4]) + self.storage[target[0]] = temp + def loadsound(self, target): + if target == None: return + with wave.open(target, 'r') as fd: + frames = fd.readframes(-1) + channels = fd.getnchannels() + bytespersample = fd.getsampwidth() + frequency = fd.getframerate() + self.storage[os.path.basename(target.split(".")[0])] = (frames, channels, bytespersample, frequency) + # frames, channels, bytespersample, frequency + return os.path.basename(target.split(".")[0]) + + def getsound(self, target): + if not target in self.storage: raise ValueError(f"Sound {target} not loaded!") + else: return sound(self.storage[target]) + + def tostring(self, target): + if not target in self.storage: raise ValueError(f"Sound {target} not loaded!") + data = self.storage[target] + # encode frames to b64 + frames = str(base64.b64encode(data[0]), "ascii", "ignore") + # rebuild tuple + out = (target, frames, data[1], data[2], data[3]) + # name, frames, channels, bytespersample, frequency + return out +class sound: + def __init__(self, data): + self.frames = data[0] + self.channels = data[1] + self.bps = data[2] + self.freq = data[3] + self._playing = False + self._soundobj = None + + def play(self): + if self._playing == True and self._soundobj.is_playing(): return + self._soundobj = sa.play_buffer(self.frames, self.channels, self.bps, self.freq) + self._playing = True + + def stop(self): + if self._playing == False: return + self._soundobj.stop() + self._playing = False + + def wait(self): + if self._playing == False: return + self._soundobj.wait_done() + self._playing = False + +if __name__ == "__main__": + temp = handler() + print(temp.loadsound("sounds/joyride.wav")) + tsound = temp.getsound("joyride") + tsound.play() + tsound.wait() \ No newline at end of file diff --git a/hashengine.py b/hashengine.py index 1201354..dd5ce9a 100644 --- a/hashengine.py +++ b/hashengine.py @@ -1,10 +1,13 @@ import mtTkinter as tk -from HEMD import color3, vector2, event, enum, NULL +from HEMD import color3, vector2, event, NULL +import audiosys +from loadbar import loadbar import random import string import math import time import threading +import pickle #import itertools #import multiprocessing @@ -22,10 +25,20 @@ class obj: self.id = NULL() self.color = color3() self.colliding = event() - self.parent = NULL() + self._parent = NULL() self.children = [] self.ignorecollision = [] + @property + def parent(self): + return self._parent + + @parent.setter + def parent(self, value): + self._parent.children.remove(self) + self._parent = value + self._parent.children.append(self) + class game: def __init__(self, canvas: tk.Canvas, pixelsize=3): self._canvas = canvas @@ -39,6 +52,10 @@ class game: self._camera.position = vector2() self._camera.zoom = pixelsize self._OAPUPDATING = False + self._handler = audiosys.handler() + self._threads = [] + self._root = obj() + self._scripts = [] """self._workers = [] self._processes = 2 # total number of processes. for i in range(self._processes): @@ -92,6 +109,8 @@ class game: if physics: self._objects[temp] = target self._visobjects[temp] = target target.id = temp + target._parent = self._root + self._root.children.append(target) self.addtooap(target) def removeobj(self, target: obj): @@ -171,20 +190,83 @@ class game: self.calcphysobj(i) return time.time()-start + def savegame(self): + print("pickling root...") + outobjects = pickle.dumps(self._root) + print("copying scripts...") + outscripts = [] + TLB = loadbar(20, len(self._scripts)) + for i in self._scripts: + outscripts.append(i) + TLB.current += 1 + TLB.render() + print("encoding sounds...") + outsounds = [] + TLB = loadbar(20, len(self._handler.storage)) + for i in self._handler.storage: + outsounds.append(self._handler.tostring(i)) + TLB.current += 1 + TLB.render() + return {"obj": outobjects, "scripts": outscripts, "sounds": outsounds} + + def readdobj(self, target, TLB): + TLB.repeat += len(target) + TLB.steps = TLB.repeat/TLB.length + for i in target.copy(): + self.addobj(i, True, i.id) + if len(i.children) > 0: self.readdobj(i.children, TLB) + TLB.current += 1 + TLB.render() + + def loadgame(self, target): + print("loading objects...") + self._root = pickle.loads(target["obj"]) + print("loading scripts...") + self._scripts = [] + TLB = loadbar(20, len(target["scripts"])) + for i in target["scripts"]: + self._scripts.append(i) + TLB.current += 1 + TLB.render() + print() + print("loading sounds...") + self._handler.storage = {} + TLB = loadbar(20, len(target["sounds"])) + for i in target["sounds"]: + self._handler.loadfromstring(i) + TLB.current += 1 + TLB.render() + print("readding objects...") + self._OAP = {} + self._objects = {} + self._visobjects = {} + TLB = loadbar(20, 0) + self.readdobj(self._root.children, TLB) + if not "__CMD__" in globals(): + from PIL import Image + from tkinter import filedialog root = tk.Tk() canvas = tk.Canvas(root) canvas.grid() temp = game(canvas) - for i in range(10): - tempobj = obj() - tempobj.position = vector2(5, i) - tempobj.anchored = False - tempobj.velocity.x = 1 - tempobj.collide = True - temp.addobj(tempobj) - while True: - took = temp.updobjs() - temp.render() - root.update() - time.sleep(0.1-took) \ No newline at end of file + tempimg = Image.open(filedialog.askopenfilename()) + tempimg = tempimg.resize((temp._width, temp._height)) + for y in range(temp._height): + for x in range(temp._width): + tempobj = obj() + tempobj.position = vector2(x, y) + tempcolor = tempimg.getpixel((x, y)) + tempobj.color = color3(tempcolor[0], tempcolor[1], tempcolor[2]) + temp.addobj(tempobj) + print(f"{y}/{temp._height}", end="\r", flush=True) + tempstate = temp.savegame() + print("resetting...") + temp.__init__(canvas) + input("press enter to reload state") + print("loading...") + temp.loadgame(tempstate) + temp.render() + root.update() + print() + input("press enter to exit.") \ No newline at end of file diff --git a/loadbar.py b/loadbar.py new file mode 100644 index 0000000..1c49c9c --- /dev/null +++ b/loadbar.py @@ -0,0 +1,9 @@ +class loadbar: + def __init__(self, length=10, full=10): + self.steps = full/length + self.length = length + self.repeat = full + self.current = 0 + + def render(self): + print("["+("#"*int(self.current/self.steps))+(" "*(self.length-int(self.current/self.steps)))+"]"+f" {self.current}/{self.repeat}", end="\r", flush=True) \ No newline at end of file diff --git a/sounds/intro.wav b/sounds/intro.wav new file mode 100644 index 0000000..e73f54e Binary files /dev/null and b/sounds/intro.wav differ diff --git a/sounds/joyride.wav b/sounds/joyride.wav new file mode 100644 index 0000000..8fd9ae9 Binary files /dev/null and b/sounds/joyride.wav differ