import tkinter as tk import string import random import threading import time import wave import os class stdrend: def __init__(self, size, cam): self._size = size self._grid = {} self._win = tk.Tk() tkeys = list(string.ascii_letters) self._keys = {} for i in tkeys: self._keys[i] = False self._win.bind("", self.keypupd) self._win.bind("", self.keydupd) for y in range(size[1]): for x in range(size[0]): temp = tk.Label(text=" ") temp.grid(row=y, column=x) self._win.update() self._grid[f"{x}:{y}"] = temp def keypupd(self, event): event = event.char if event in self._keys: self._keys[event] = True def keydupd(self, event): event = event.char if event in self._keys: self._keys[event] = False def getkeys(self): return self._keys def coltohex(self, target): colors = [] target = [target.r, target.g, target.b] for i in target: colors.append(("0"*(2-len(hex(i)[2:])))+hex(i)[2:]) out = "" for i in colors: out = out + i return "#"+out def update(self): self._win.update() def pix(self, x, y, text, bcolor, fcolor): if f"{x}:{y}" in self._grid: self._grid[f"{x}:{y}"].config(text=text, bg=self.coltohex(bcolor), fg=self.coltohex(fcolor)) class color3: def __init__(self, r=0, g=0, b=0): self.r = r self.g = g self.b = b self._type = "color3" def __add__(self, v): temp = color3(self.r+v.r, self.g+v.g, self.b+v.b) temp.r = temp.r%255 temp.g = temp.g%255 temp.b = temp.b%255 return temp def __sub__(self, v): temp = color3(self.r-v.r, self.g-v.g, self.b-v.b) temp.r = temp.r%255 temp.g = temp.g%255 temp.b = temp.b%255 return temp def __mul__(self, v): temp = color3(self.r*v.r, self.g*v.g, self.b*v.b) temp.r = temp.r%255 temp.g = temp.g%255 temp.b = temp.b%255 return temp def __iadd__(self, v): temp = color3(self.r+v.r, self.g+v.g, self.b+v.b) temp.r = temp.r%255 temp.g = temp.g%255 temp.b = temp.b%255 return temp def __isub__(self, v): temp = color3(self.r-v.r, self.g-v.g, self.b-v.b) temp.r = temp.r%255 temp.g = temp.g%255 temp.b = temp.b%255 return temp def __imul__(self, v): temp = color3(self.r*v.r, self.g*v.g, self.b*v.b) temp.r = temp.r%255 temp.g = temp.g%255 temp.b = temp.b%255 return temp class vector2: def __init__(self, x=0, y=0): self.x = x self.y = y self._type = "vector2" def _magnitude(self): return abs(self.x+self.y) def __add__(self, v): return vector2(self.x+v.x, self.y+v.y) def __sub__(self, v): return vector2(self.x-v.x, self.y-v.y) def __mul__(self, v): return vector2(self.x*v.x, self.y*v.y) def __iadd__(self, v): return vector2(self.x+v.x, self.y+v.y) def __isub__(self, v): return vector2(self.x-v.x, self.y-v.y) def __imul__(self, v): return vector2(self.x*v.x, self.y*v.y) class NULL: def __init__(self): return None class enum: def __init__(self, sel): self._sel = dict(sel) for i in self._sel: setattr(self, i, self._sel[i]) def getposssel(self): return list(self._sel.keys()) def loadsound(path): with wave.open(path) as fd: frames = fd.readframes(1000000000) return frames cammode = enum({"editable": 0, "follow": 1}) class event: def __init__(self): self._attached = [] def execute(self): threads = [] for i in self._attached: temp = threading.Thread(target=i) temp.start() threads.append(temp) return threads def attach(self, target): self._attached.append(target) class obj: def __init__(self): self.position = vector2() self.char = " " self.ID = 0 self.gravity = 0 self.acceleration = vector2() self.velocity = vector2() self.friction = 0 self.collide = True self.anchored = False self.bcolor = color3(255, 255, 255) self.fcolor = color3() self._touching = event() class model: def __init__(self, objects): self._objects = objects self.ID = 0 class camera(obj): def __init__(self): super().__init__() self.mode = cammode.editable self.subject = None self.collide = False self.touch = False self.char = " " def update(self): if self.mode == cammode.follow and self.subject: self.position = self.subject.position class game: def __init__(self, size=[10, 10], renderer=stdrend, sounddir=""): if renderer == None: raise TypeError("Renderer class needed!") self.sounds = {} self.currentsounds = [] for i in os.listdir(sounddir): if not "." in i: continue if i.split(".")[1] != "wav": continue self.sounds[i.split(".")[0]] = loadsound(sounddir+"/"+i) self._size = size self._objects = {} self.camera = camera() self._renderer = renderer(size, self.camera) self._threads = [] def isdown(self, key): temp = self._renderer.getkeys() if key in temp: return temp[key] def collidingpos(self, pos, ignore): out = [] for i in self._objects: i = self._objects[i] if i in ignore: continue if (i.position-pos)._magnitude() < 1 and i.collide == True: out.append(i) return out def colliding(self, target): out = [] if target.collide == False: return [] out = self.collidingpos(target.position, [target,]) return out def handlecollision(self, target: obj, target2: obj): if target2.anchored == True: target.velocity = vector2() else: half = vector2(target.velocity.x/2, target.velocity.y/2) target.velocity = vector2(half.x, half.y) target2.velocity = half self._threads.extend(target._touching.execute()) self._threads.extend(target2._touching.execute()) def calcphysobj(self, target: obj): opos = vector2(target.position.x, target.position.y) collide = False if target.anchored == True: return [opos, collide] if target.collide == True: colliding = self.collidingpos(target.position+target.velocity, [target,]) for i in colliding: target._touching.execute() i._touching.execute() self.handlecollision(target, i) collide = True target.position += target.velocity target.velocity += vector2(0, target.gravity) target.velocity += target.acceleration temp = 2 if target.friction != 0: temp = 2 / target.friction x = target.velocity.x y = target.velocity.y if x != 0: x = x/temp if y != 0: y = y/temp target.velocity = vector2(x, y) return [opos, collide] def calcphysmodel(self, target: model): for i in target._objects: self.calcphysobj(i) def addobj(self, obj): id = "" for i in range(256): id = id + random.choice(list(string.ascii_letters)) obj.ID = id self._objects[id] = obj def removeobj(self, obj): self._objects.pop(obj.ID) obj.ID = NULL() def removeobjbyid(self, id): self._objects.pop(id).ID = NULL() def between(self, min, max, target): if min < target < max: return True return False def getobjbyid(self, id): return self._objects[id] def render(self): tochange = [] for x in range(self._size[0]): for y in range(self._size[1]): tochange.append((x, y)) #self._renderer.pix(x, y, " ", color3(255, 255, 255), color3(255, 255, 255)) for i in list(self._objects.values()): if isinstance(i, obj): pos = i.position + self.camera.position if not self.between(-1, self._size[0], pos.x) or not self.between(-1, self._size[1], pos.y): continue# pos = vector2(round(pos.x), round(pos.y)) self._renderer.pix(pos.x, pos.y, i.char, i.bcolor, i.fcolor) if (pos.x, pos.y) in tochange: tochange.remove((pos.x, pos.y)) if isinstance(i, model): for tobj in i._objects: pos = tobj.position + self.camera.position if not self.between(-1, self._size[0], pos.x) or not self.between(-1, self._size[1], pos.y): continue# pos = vector2(round(pos.x), round(pos.y)) self._renderer.pix(pos.x, pos.y, tobj.char, tobj.bcolor, tobj.fcolor) if (pos.x, pos.y) in tochange: tochange.remove((pos.x, pos.y)) for i in tochange: self._renderer.pix(i[0], i[1], " ", color3(255, 255, 255), color3(255, 255, 255)) self._renderer.update() def startscript(self, target): temp = threading.Thread(target=target) temp.start() self._threads.append(temp) def stopscripts(self): for i in self._threads: i.join(.0) def stopsounds(self): for i in self.currentsounds: i.stop() if __name__ == "__main__": testgame = game(sounddir="testsound") object = obj() object.char = "#" object.anchored = False object.position = vector2(5, 5) object.gravity = 1 floor = obj() floor.char = "#" floor.anchored = True floor.position = vector2(5, 9) floor.gravity = 0 floor.bcolor = color3(255, 255, 255) testgame.addobj(object) testgame.addobj(floor) testgame.render() print(object.ID) while True: testgame.calcphysobj(object) testgame.calcphysobj(floor) testgame.render() time.sleep(0)