added new building system, added sound, added keyboard
parent
ae80270d71
commit
f540626b4b
|
@ -3,12 +3,22 @@ import string
|
||||||
import random
|
import random
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import wave
|
||||||
|
import os
|
||||||
|
|
||||||
class stdrend:
|
class stdrend:
|
||||||
def __init__(self, size, cam):
|
def __init__(self, size, cam):
|
||||||
self._size = size
|
self._size = size
|
||||||
self._grid = {}
|
self._grid = {}
|
||||||
self._win = tk.Tk()
|
self._win = tk.Tk()
|
||||||
|
|
||||||
|
tkeys = list(string.ascii_letters)
|
||||||
|
self._keys = {}
|
||||||
|
for i in tkeys:
|
||||||
|
self._keys[i] = False
|
||||||
|
self._win.bind("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", self.keydupd)
|
||||||
|
|
||||||
for y in range(size[1]):
|
for y in range(size[1]):
|
||||||
for x in range(size[0]):
|
for x in range(size[0]):
|
||||||
temp = tk.Label(text=" ")
|
temp = tk.Label(text=" ")
|
||||||
|
@ -16,6 +26,19 @@ class stdrend:
|
||||||
self._win.update()
|
self._win.update()
|
||||||
self._grid[f"{x}:{y}"] = temp
|
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):
|
def coltohex(self, target):
|
||||||
colors = []
|
colors = []
|
||||||
target = [target.r, target.g, target.b]
|
target = [target.r, target.g, target.b]
|
||||||
|
@ -122,6 +145,11 @@ class enum:
|
||||||
def getposssel(self):
|
def getposssel(self):
|
||||||
return list(self._sel.keys())
|
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})
|
cammode = enum({"editable": 0, "follow": 1})
|
||||||
|
|
||||||
class event:
|
class event:
|
||||||
|
@ -168,14 +196,25 @@ class camera(obj):
|
||||||
self.position = self.subject.position
|
self.position = self.subject.position
|
||||||
|
|
||||||
class game:
|
class game:
|
||||||
def __init__(self, size=[10, 10], renderer=stdrend):
|
def __init__(self, size=[10, 10], renderer=stdrend, sounddir=""):
|
||||||
if renderer == None: raise TypeError("Renderer class needed!")
|
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._size = size
|
||||||
self._objects = {}
|
self._objects = {}
|
||||||
self.camera = camera()
|
self.camera = camera()
|
||||||
self._renderer = renderer(size, self.camera)
|
self._renderer = renderer(size, self.camera)
|
||||||
self._threads = []
|
self._threads = []
|
||||||
|
|
||||||
|
def isdown(self, key):
|
||||||
|
temp = self._renderer.getkeys()
|
||||||
|
if key in temp:
|
||||||
|
return temp[key]
|
||||||
|
|
||||||
def collidingpos(self, pos, ignore):
|
def collidingpos(self, pos, ignore):
|
||||||
out = []
|
out = []
|
||||||
for i in self._objects:
|
for i in self._objects:
|
||||||
|
@ -243,13 +282,19 @@ class game:
|
||||||
return self._objects[id]
|
return self._objects[id]
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
|
tochange = []
|
||||||
for x in range(self._size[0]):
|
for x in range(self._size[0]):
|
||||||
for y in range(self._size[1]):
|
for y in range(self._size[1]):
|
||||||
self._renderer.pix(x, y, " ", color3(255, 255, 255), color3(255, 255, 255))
|
tochange.append((x, y))
|
||||||
|
#self._renderer.pix(x, y, " ", color3(255, 255, 255), color3(255, 255, 255))
|
||||||
for i in list(self._objects.values()):
|
for i in list(self._objects.values()):
|
||||||
pos = i.position + self.camera.position
|
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
|
if not self.between(-1, self._size[0], pos.x) or not self.between(-1, self._size[1], pos.y): continue#
|
||||||
self._renderer.pix(round(pos.x), round(pos.y), i.char, i.bcolor, i.fcolor)
|
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))
|
||||||
|
for i in tochange:
|
||||||
|
self._renderer.pix(i[0], i[1], " ", color3(255, 255, 255), color3(255, 255, 255))
|
||||||
self._renderer.update()
|
self._renderer.update()
|
||||||
|
|
||||||
def startscript(self, target):
|
def startscript(self, target):
|
||||||
|
@ -261,8 +306,12 @@ class game:
|
||||||
for i in self._threads:
|
for i in self._threads:
|
||||||
i.join(.0)
|
i.join(.0)
|
||||||
|
|
||||||
|
def stopsounds(self):
|
||||||
|
for i in self.currentsounds:
|
||||||
|
i.stop()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
testgame = game()
|
testgame = game(sounddir="testsound")
|
||||||
object = obj()
|
object = obj()
|
||||||
object.char = "#"
|
object.char = "#"
|
||||||
object.anchored = False
|
object.anchored = False
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 213 B |
Binary file not shown.
After Width: | Height: | Size: 213 B |
|
@ -28,4 +28,5 @@
|
||||||
"stest": "Test stoppen",
|
"stest": "Test stoppen",
|
||||||
"building": "Bauen",
|
"building": "Bauen",
|
||||||
"build": "Bauen",
|
"build": "Bauen",
|
||||||
|
"sound": "Sound",
|
||||||
}
|
}
|
|
@ -28,4 +28,5 @@
|
||||||
"stest": "Stop execution",
|
"stest": "Stop execution",
|
||||||
"building": "Building",
|
"building": "Building",
|
||||||
"build": "Build",
|
"build": "Build",
|
||||||
|
"sound": "Sound",
|
||||||
}
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
Log file start!
|
||||||
|
Preparing API...
|
||||||
|
Done!
|
||||||
|
main game initalised!
|
||||||
|
copying sounds...
|
||||||
|
objects transferred!
|
||||||
|
game test started!!!
|
||||||
|
---------------------
|
|
@ -0,0 +1,8 @@
|
||||||
|
Log file start!
|
||||||
|
Preparing API...
|
||||||
|
Done!
|
||||||
|
main game initalised!
|
||||||
|
copying sounds...
|
||||||
|
objects transferred!
|
||||||
|
game test started!!!
|
||||||
|
---------------------
|
254
main.py
254
main.py
|
@ -6,31 +6,41 @@ from tkinter import ttk as tkk
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
from tkinter import filedialog
|
from tkinter import filedialog
|
||||||
import copy
|
import copy
|
||||||
import PCPL
|
import hashengine
|
||||||
import langsys
|
global LH
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import PCPL
|
||||||
|
import langsys
|
||||||
|
PCPL.interpreter.ENG = hashengine
|
||||||
|
LH = langsys.langhandler()
|
||||||
|
lang = open("clang", 'r')
|
||||||
|
lang = lang.read()
|
||||||
|
LH.setlang(lang)
|
||||||
|
# LH.string("")
|
||||||
|
else:
|
||||||
|
class rLH:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
def string(self, target):
|
||||||
|
return target
|
||||||
|
LH = rLH()
|
||||||
import ast
|
import ast
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import hashengine
|
|
||||||
import shutil
|
import shutil
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import easygui
|
import easygui
|
||||||
|
import base64
|
||||||
|
import simpleaudio as sa
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
global LH
|
|
||||||
global gamedata
|
global gamedata
|
||||||
global cooldown
|
global cooldown
|
||||||
cooldown = False
|
cooldown = False
|
||||||
gamedata = {}
|
gamedata = {}
|
||||||
LH = langsys.langhandler()
|
|
||||||
lang = open("clang", 'r')
|
|
||||||
lang = lang.read()
|
|
||||||
LH.setlang(lang)
|
|
||||||
# LH.string("")
|
|
||||||
|
|
||||||
PCPL.interpreter.ENG = hashengine
|
|
||||||
|
|
||||||
def prepgamedata():
|
def prepgamedata():
|
||||||
out = []
|
out = []
|
||||||
|
@ -50,11 +60,14 @@ def prepgamedata():
|
||||||
tempargs = {}
|
tempargs = {}
|
||||||
tosearch = {}
|
tosearch = {}
|
||||||
for arg in i["args"]:
|
for arg in i["args"]:
|
||||||
if not arg in extypes and not arg in ignoreat:
|
if not arg in extypes and not arg in ignoreat and arg != "sdata":
|
||||||
tosearch[arg] = i["args"][arg]
|
tosearch[arg] = i["args"][arg]
|
||||||
continue
|
continue
|
||||||
if arg in ignoreat: continue
|
if arg in ignoreat and arg != "sdata": continue
|
||||||
|
if arg != "sdata":
|
||||||
tempargs[arg] = i["args"][arg]
|
tempargs[arg] = i["args"][arg]
|
||||||
|
else:
|
||||||
|
tempargs[arg] = str(base64.b64encode(i["args"][arg]), "ascii", "ignore")
|
||||||
for argname in tosearch:
|
for argname in tosearch:
|
||||||
arg = tosearch[argname]
|
arg = tosearch[argname]
|
||||||
temp2 = getattributes(arg)
|
temp2 = getattributes(arg)
|
||||||
|
@ -89,6 +102,14 @@ class previewrend:
|
||||||
self._ycam = tk.Label(self._posframe, text="-")
|
self._ycam = tk.Label(self._posframe, text="-")
|
||||||
self._xcam.grid(row=size[1], column=0)
|
self._xcam.grid(row=size[1], column=0)
|
||||||
self._ycam.grid(row=size[1]+1, column=0)
|
self._ycam.grid(row=size[1]+1, column=0)
|
||||||
|
|
||||||
|
tkeys = list(string.ascii_letters)
|
||||||
|
self._keys = {}
|
||||||
|
for i in tkeys:
|
||||||
|
self._keys[i] = False
|
||||||
|
self._win.bind("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", self.keydupd)
|
||||||
|
|
||||||
for y in range(size[1]):
|
for y in range(size[1]):
|
||||||
for x in range(size[0]):
|
for x in range(size[0]):
|
||||||
temp = tk.Label(self._frame, text=" ", borderwidth=1, relief=tk.GROOVE, width=3)
|
temp = tk.Label(self._frame, text=" ", borderwidth=1, relief=tk.GROOVE, width=3)
|
||||||
|
@ -98,6 +119,19 @@ class previewrend:
|
||||||
self._posframe.grid()
|
self._posframe.grid()
|
||||||
self._frame.grid()
|
self._frame.grid()
|
||||||
|
|
||||||
|
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):
|
def coltohex(self, target):
|
||||||
colors = []
|
colors = []
|
||||||
target = [target.r, target.g, target.b]
|
target = [target.r, target.g, target.b]
|
||||||
|
@ -117,6 +151,80 @@ class previewrend:
|
||||||
if f"{x}:{y}" in self._grid:
|
if f"{x}:{y}" in self._grid:
|
||||||
self._grid[f"{x}:{y}"].config(text=text, bg=self.coltohex(bcolor), fg=self.coltohex(fcolor))
|
self._grid[f"{x}:{y}"].config(text=text, bg=self.coltohex(bcolor), fg=self.coltohex(fcolor))
|
||||||
|
|
||||||
|
class render:
|
||||||
|
def __init__(self, size, cam, container, offset):
|
||||||
|
self._size = size
|
||||||
|
self._grid = {}
|
||||||
|
self._win = container
|
||||||
|
self._frame = tk.Frame(container)
|
||||||
|
self._posframe = tk.Frame(self._frame)
|
||||||
|
self._cam = cam
|
||||||
|
self._xcam = tk.Label(self._posframe, text="-")
|
||||||
|
self._ycam = tk.Label(self._posframe, text="-")
|
||||||
|
#self._xcam.grid(row=size[1], column=0)
|
||||||
|
#self._ycam.grid(row=size[1]+1, column=0)
|
||||||
|
|
||||||
|
tkeys = list(string.ascii_letters)
|
||||||
|
self._keys = {}
|
||||||
|
for i in tkeys:
|
||||||
|
self._keys[i] = False
|
||||||
|
self._win.bind("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", self.keydupd)
|
||||||
|
|
||||||
|
for y in range(size[1]):
|
||||||
|
for x in range(size[0]):
|
||||||
|
temp = tk.Label(self._frame, text=" ", width=3)
|
||||||
|
temp.grid(row=y+offset[1], column=x+offset[0]+1)
|
||||||
|
self._win.update()
|
||||||
|
self._grid[f"{x}:{y}"] = temp
|
||||||
|
self._posframe.grid()
|
||||||
|
self._frame.grid()
|
||||||
|
|
||||||
|
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(int(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):
|
||||||
|
self._xcam.config(text=LH.string("xcam")+str(self._cam.position.x))
|
||||||
|
self._ycam.config(text=LH.string("ycam")+str(self._cam.position.y))
|
||||||
|
if f"{x}:{y}" in self._grid:
|
||||||
|
self._grid[f"{x}:{y}"].config(text=text, bg=self.coltohex(bcolor), fg=self.coltohex(fcolor))
|
||||||
|
|
||||||
|
class nullrend:
|
||||||
|
def __init__(self, size, cam):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getkeys(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pix(self, x, y, text, bcolor, fcolor):
|
||||||
|
pass
|
||||||
|
|
||||||
def selectlang(new):
|
def selectlang(new):
|
||||||
lang = open("clang", 'w')
|
lang = open("clang", 'w')
|
||||||
lang.write(new)
|
lang.write(new)
|
||||||
|
@ -136,12 +244,12 @@ def add(objtype):
|
||||||
chars = list(string.ascii_letters)
|
chars = list(string.ascii_letters)
|
||||||
for i in range(255):
|
for i in range(255):
|
||||||
id = id + random.choice(chars)
|
id = id + random.choice(chars)
|
||||||
objtree.insert("", tk.END, text=LH.string(objtype), image=icons[objtype], iid=id, tags=("objsel"))
|
if GUIe == True: objtree.insert("", tk.END, text=LH.string(objtype), image=icons[objtype], iid=id, tags=("objsel"))
|
||||||
gamedata[id] = temp
|
gamedata[id] = temp
|
||||||
if objtype in crucial:
|
if objtype in crucial:
|
||||||
preview.addobj(obj)
|
preview.addobj(obj)
|
||||||
gamedata[id]["args"]["ID"] = obj.ID
|
gamedata[id]["args"]["ID"] = obj.ID
|
||||||
preview.render()
|
if GUIe == True: preview.render()
|
||||||
return id
|
return id
|
||||||
|
|
||||||
def renameobj():
|
def renameobj():
|
||||||
|
@ -239,11 +347,21 @@ def clear():
|
||||||
preview.camera.position = hashengine.vector2()
|
preview.camera.position = hashengine.vector2()
|
||||||
preview.render()
|
preview.render()
|
||||||
|
|
||||||
|
def importsound(target):
|
||||||
|
oid = add("rawsound")
|
||||||
|
gamedata[oid]["name"] = target["name"]
|
||||||
|
gamedata[oid]["args"]["sdata"] = base64.b64decode(target["args"]["sdata"])
|
||||||
|
gamedata[oid]["args"]["spath"] = target["args"]["spath"]
|
||||||
|
if GUIe == True: objtree.item(oid, text=target["name"])
|
||||||
|
|
||||||
def importobj(target):
|
def importobj(target):
|
||||||
|
if target["id"] == "sound" or target["id"] == "rawsound":
|
||||||
|
importsound(target)
|
||||||
|
return
|
||||||
oid = add(target["id"])
|
oid = add(target["id"])
|
||||||
id = gamedata[oid]
|
id = gamedata[oid]
|
||||||
id["name"] = target["name"]
|
id["name"] = target["name"]
|
||||||
objtree.item(oid, text=target["name"])
|
if GUIe == True: objtree.item(oid, text=target["name"])
|
||||||
#create arguments
|
#create arguments
|
||||||
outargs = {}
|
outargs = {}
|
||||||
for argname in target["args"]:
|
for argname in target["args"]:
|
||||||
|
@ -287,14 +405,41 @@ def load():
|
||||||
|
|
||||||
def log(text, end="\n", flush=False):
|
def log(text, end="\n", flush=False):
|
||||||
global logfile
|
global logfile
|
||||||
|
if not os.path.exists("logs"):
|
||||||
|
os.mkdir("logs")
|
||||||
file = open("logs/"+logfile+".txt", 'a')
|
file = open("logs/"+logfile+".txt", 'a')
|
||||||
file.write(text+end)
|
file.write(str(text)+end)
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
def NULL():
|
def NULL():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class gsound:
|
||||||
|
def __init__(self, data, game):
|
||||||
|
self._playing = False
|
||||||
|
self._data = data
|
||||||
|
game.currentsounds.append(self)
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
if self._playing == True: return
|
||||||
|
self._sound = sa.play_buffer(self._data, 2, 2, 44100)
|
||||||
|
self._playing = True
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.stop()
|
||||||
|
self._playing = False
|
||||||
|
|
||||||
|
def wait(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.wait_done()
|
||||||
|
|
||||||
def testing():
|
def testing():
|
||||||
|
global testproc
|
||||||
|
testproc = multiprocessing.Process(target=execgame, args=(prepgamedata(),))
|
||||||
|
testproc.start()
|
||||||
|
|
||||||
|
def run():
|
||||||
print("preparing log file...")
|
print("preparing log file...")
|
||||||
global logfile
|
global logfile
|
||||||
global maingame
|
global maingame
|
||||||
|
@ -310,9 +455,16 @@ def testing():
|
||||||
log("Done!")
|
log("Done!")
|
||||||
window = tk.Tk()
|
window = tk.Tk()
|
||||||
window.protocol("WM_DELETE_WINDOW", NULL)
|
window.protocol("WM_DELETE_WINDOW", NULL)
|
||||||
maingame = hashengine.game(renderer=lambda size, cam: previewrend(size, cam, window, [0, 0]))
|
maingame = hashengine.game(renderer=lambda size, cam: render(size, cam, window, [0, 0]), sounddir="/")
|
||||||
API["HASHGAME"] = maingame
|
API["HASHGAME"] = maingame
|
||||||
|
API["SOUND"] = lambda data: gsound(data, maingame)
|
||||||
log("main game initalised!")
|
log("main game initalised!")
|
||||||
|
log("copying sounds...")
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
if i["id"] != "sound" and i["id"] != "rawsound": continue
|
||||||
|
maingame.sounds[i["args"]["spath"]] = i["args"]["sdata"]
|
||||||
|
print(i["args"]["spath"])
|
||||||
objects = copy.deepcopy(preview._objects)
|
objects = copy.deepcopy(preview._objects)
|
||||||
maingame._objects = objects
|
maingame._objects = objects
|
||||||
scripts = []
|
scripts = []
|
||||||
|
@ -323,8 +475,6 @@ def testing():
|
||||||
obj = script()
|
obj = script()
|
||||||
obj.code = i
|
obj.code = i
|
||||||
scripts.append(obj)
|
scripts.append(obj)
|
||||||
for i in scripts:
|
|
||||||
maingame.startscript(lambda: i.execute(API))
|
|
||||||
log("objects transferred!")
|
log("objects transferred!")
|
||||||
gamescript = """
|
gamescript = """
|
||||||
global HASHGAME
|
global HASHGAME
|
||||||
|
@ -340,18 +490,23 @@ while True:
|
||||||
maingame.startscript(lambda: gameloopsc.execute(API))
|
maingame.startscript(lambda: gameloopsc.execute(API))
|
||||||
log("game test started!!!")
|
log("game test started!!!")
|
||||||
log("---------------------")
|
log("---------------------")
|
||||||
|
for i in scripts:
|
||||||
|
maingame.startscript(lambda: i.execute(API))
|
||||||
|
window.mainloop()
|
||||||
|
|
||||||
def muladd(target):
|
def muladd(target):
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
add(target)
|
add(target)
|
||||||
|
|
||||||
def stoptest():
|
def stoptest():
|
||||||
maingame.stopscripts()
|
global testproc
|
||||||
window.destroy()
|
testproc.terminate()
|
||||||
|
|
||||||
def build():
|
def build():
|
||||||
print("asking user for output directory...")
|
print("asking user for output directory...")
|
||||||
target = filedialog.askdirectory()
|
target = filedialog.askdirectory()
|
||||||
|
os.mkdir(target+"/out")
|
||||||
|
target = target+"/out"
|
||||||
print("building started")
|
print("building started")
|
||||||
print("generating HEGF file...")
|
print("generating HEGF file...")
|
||||||
hegf = str(prepgamedata())
|
hegf = str(prepgamedata())
|
||||||
|
@ -360,10 +515,20 @@ def build():
|
||||||
file.close()
|
file.close()
|
||||||
print("done.")
|
print("done.")
|
||||||
print("copying files...")
|
print("copying files...")
|
||||||
tocopy = ["mtTkinter.py", "player.py", "hashengine.py"]
|
tocopy = ["mtTkinter.py", "hashengine.py"]
|
||||||
for i in tocopy:
|
for i in tocopy:
|
||||||
print(f"copying {i}...")
|
print(f"copying {i}...")
|
||||||
shutil.copyfile(i, target+"/"+i)
|
shutil.copyfile(i, target+"/"+i)
|
||||||
|
shutil.copyfile(__file__, target+"/"+"player.py")
|
||||||
|
file = open(target+"/main.py", 'w')
|
||||||
|
file.write("""
|
||||||
|
import player
|
||||||
|
import ast
|
||||||
|
file = open("game.HEGF", 'r')
|
||||||
|
file = file.read()
|
||||||
|
file = ast.literal_eval(file)
|
||||||
|
player.execgame(file)
|
||||||
|
""")
|
||||||
print("done.")
|
print("done.")
|
||||||
print("building finished!")
|
print("building finished!")
|
||||||
|
|
||||||
|
@ -374,6 +539,8 @@ def GUIinit():
|
||||||
global atritree
|
global atritree
|
||||||
global currentat
|
global currentat
|
||||||
global preview
|
global preview
|
||||||
|
global GUIe
|
||||||
|
GUIe = True
|
||||||
container = tk.Tk()
|
container = tk.Tk()
|
||||||
container.bind("<KeyPress>", updatepreviewcam)
|
container.bind("<KeyPress>", updatepreviewcam)
|
||||||
|
|
||||||
|
@ -384,7 +551,7 @@ def GUIinit():
|
||||||
icons[i.split(".")[0]] = tk.PhotoImage(file=f"icons/{i}")
|
icons[i.split(".")[0]] = tk.PhotoImage(file=f"icons/{i}")
|
||||||
|
|
||||||
#preview init
|
#preview init
|
||||||
preview = hashengine.game(renderer=lambda size, cam: previewrend(size, cam, container=container, offset=[0, 0]))
|
preview = hashengine.game(renderer=lambda size, cam: previewrend(size, cam, container=container, offset=[0, 0]), sounddir="/")
|
||||||
|
|
||||||
#tree init
|
#tree init
|
||||||
objtree = tkk.Treeview(container, selectmode="browse", columns=("-"))
|
objtree = tkk.Treeview(container, selectmode="browse", columns=("-"))
|
||||||
|
@ -422,6 +589,7 @@ def GUIinit():
|
||||||
menu.add_cascade(label=LH.string("add"), menu=addmenu)
|
menu.add_cascade(label=LH.string("add"), menu=addmenu)
|
||||||
addmenu.add_command(label=LH.string("obj"), command=lambda: add("obj"))
|
addmenu.add_command(label=LH.string("obj"), command=lambda: add("obj"))
|
||||||
addmenu.add_command(label=LH.string("script"), command=lambda: add("script"))
|
addmenu.add_command(label=LH.string("script"), command=lambda: add("script"))
|
||||||
|
addmenu.add_command(label=LH.string("sound"), command=lambda: add("sound"))
|
||||||
#addmenu.add_command(label=LH.string("obj"), command=lambda: muladd("obj"))
|
#addmenu.add_command(label=LH.string("obj"), command=lambda: muladd("obj"))
|
||||||
|
|
||||||
testmenu = tk.Menu(menu)
|
testmenu = tk.Menu(menu)
|
||||||
|
@ -481,6 +649,35 @@ def acode(old):
|
||||||
else:
|
else:
|
||||||
return old
|
return old
|
||||||
|
|
||||||
|
def apath(old, ext):
|
||||||
|
new = filedialog.askopenfilename(defaultextension=ext, filetypes=(ext))
|
||||||
|
if new:
|
||||||
|
return new
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def aNULL(old):
|
||||||
|
return old
|
||||||
|
|
||||||
|
def execgame(gametree):
|
||||||
|
global GUIe
|
||||||
|
global preview
|
||||||
|
preview = hashengine.game(renderer=nullrend, sounddir="/")
|
||||||
|
GUIe = False
|
||||||
|
for i in gametree:
|
||||||
|
importobj(i)
|
||||||
|
run()
|
||||||
|
|
||||||
|
class rsound:
|
||||||
|
def __init__(self):
|
||||||
|
self.spath = ""
|
||||||
|
self.sdata = b""
|
||||||
|
|
||||||
|
class sound():
|
||||||
|
def __init__(self, new):
|
||||||
|
self.spath = os.path.basename(new).split(".")[0]
|
||||||
|
self.sdata = hashengine.loadsound(new)
|
||||||
|
|
||||||
global types
|
global types
|
||||||
global ignoreat
|
global ignoreat
|
||||||
global valtypes
|
global valtypes
|
||||||
|
@ -488,8 +685,8 @@ global extypes
|
||||||
global attypes
|
global attypes
|
||||||
global crucial
|
global crucial
|
||||||
crucial = ["obj"]
|
crucial = ["obj"]
|
||||||
types = hashengine.enum({"obj": hashengine.obj, "script": script})
|
types = hashengine.enum({"obj": hashengine.obj, "script": script, "rawsound": rsound, "sound": lambda: sound(apath("", [("Wave files", ".wave .wav")]))})
|
||||||
ignoreat = ["ID", "execute"]
|
ignoreat = ["ID", "execute", "sdata"]
|
||||||
"""self.position = vector2()
|
"""self.position = vector2()
|
||||||
self.char = " "
|
self.char = " "
|
||||||
self.ID = 0
|
self.ID = 0
|
||||||
|
@ -516,10 +713,13 @@ valtypes = {
|
||||||
"touch": abool,
|
"touch": abool,
|
||||||
"anchored": abool,
|
"anchored": abool,
|
||||||
"code": acode,
|
"code": acode,
|
||||||
|
"spath": aNULL,
|
||||||
}
|
}
|
||||||
|
#lambda old: apath(old, [("Wave files", ".wave .wav")])
|
||||||
extypes = list(valtypes.keys())
|
extypes = list(valtypes.keys())
|
||||||
attypes = {
|
attypes = {
|
||||||
"vector2": hashengine.vector2,
|
"vector2": hashengine.vector2,
|
||||||
"color3": hashengine.color3,
|
"color3": hashengine.color3,
|
||||||
}
|
}
|
||||||
GUIinit()
|
if __name__ == "__main__":
|
||||||
|
GUIinit()
|
|
@ -0,0 +1,336 @@
|
||||||
|
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("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", 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 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
|
||||||
|
|
||||||
|
def calcphysobj(self, target: obj):
|
||||||
|
if target.anchored == True: return
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
|
||||||
|
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()):
|
||||||
|
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))
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
Log file start!
|
||||||
|
Preparing API...
|
||||||
|
Done!
|
||||||
|
main game initalised!
|
||||||
|
copying sounds...
|
||||||
|
objects transferred!
|
||||||
|
game test started!!!
|
||||||
|
---------------------
|
|
@ -0,0 +1,8 @@
|
||||||
|
Log file start!
|
||||||
|
Preparing API...
|
||||||
|
Done!
|
||||||
|
main game initalised!
|
||||||
|
copying sounds...
|
||||||
|
objects transferred!
|
||||||
|
game test started!!!
|
||||||
|
---------------------
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
import player
|
||||||
|
import ast
|
||||||
|
file = open("game.HEGF", 'r')
|
||||||
|
file = file.read()
|
||||||
|
file = ast.literal_eval(file)
|
||||||
|
player.execgame(file)
|
|
@ -0,0 +1,664 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.dont_write_bytecode = True
|
||||||
|
import mtTkinter as tk
|
||||||
|
from tkinter import ttk as tkk
|
||||||
|
from tkinter import messagebox
|
||||||
|
from tkinter import filedialog
|
||||||
|
import copy
|
||||||
|
import hashengine
|
||||||
|
global LH
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import PCPL
|
||||||
|
import langsys
|
||||||
|
PCPL.interpreter.ENG = hashengine
|
||||||
|
LH = langsys.langhandler()
|
||||||
|
lang = open("clang", 'r')
|
||||||
|
lang = lang.read()
|
||||||
|
LH.setlang(lang)
|
||||||
|
# LH.string("")
|
||||||
|
else:
|
||||||
|
class rLH:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
def string(self, target):
|
||||||
|
return target
|
||||||
|
LH = rLH()
|
||||||
|
import ast
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import easygui
|
||||||
|
import base64
|
||||||
|
import simpleaudio as sa
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
global gamedata
|
||||||
|
global cooldown
|
||||||
|
cooldown = False
|
||||||
|
gamedata = {}
|
||||||
|
|
||||||
|
def prepgamedata():
|
||||||
|
out = []
|
||||||
|
tempwin = tk.Tk()
|
||||||
|
bar = tkk.Progressbar(tempwin)
|
||||||
|
bar.place(width=200)
|
||||||
|
ptext = tk.Label(tempwin, text="NONE")
|
||||||
|
ptext.place()
|
||||||
|
count = 1
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
ptext.config(text=i["name"])
|
||||||
|
bar.step(count/len(gamedata))
|
||||||
|
count += 1
|
||||||
|
tempwin.update()
|
||||||
|
temp = {"id": i["id"], "name": i["name"]}
|
||||||
|
tempargs = {}
|
||||||
|
tosearch = {}
|
||||||
|
for arg in i["args"]:
|
||||||
|
if not arg in extypes and not arg in ignoreat and arg != "sdata":
|
||||||
|
tosearch[arg] = i["args"][arg]
|
||||||
|
continue
|
||||||
|
if arg in ignoreat and arg != "sdata": continue
|
||||||
|
if arg != "sdata":
|
||||||
|
tempargs[arg] = i["args"][arg]
|
||||||
|
else:
|
||||||
|
tempargs[arg] = str(base64.b64encode(i["args"][arg]), "ascii", "ignore")
|
||||||
|
for argname in tosearch:
|
||||||
|
arg = tosearch[argname]
|
||||||
|
temp2 = getattributes(arg)
|
||||||
|
temp2.update({"ARGID": arg._type})
|
||||||
|
tempargs[argname] = temp2
|
||||||
|
temp["args"] = tempargs
|
||||||
|
out.append(temp)
|
||||||
|
tempwin.destroy()
|
||||||
|
return out
|
||||||
|
|
||||||
|
class script:
|
||||||
|
def __init__(self):
|
||||||
|
self.code = ""
|
||||||
|
|
||||||
|
def execute(self, API):
|
||||||
|
#old code for PCPL code execution, replaced with python code execution
|
||||||
|
"""
|
||||||
|
PCPL.resetvar()
|
||||||
|
PCPL.LIS("HASHBASE")
|
||||||
|
PCPL.run(self.code)"""
|
||||||
|
exec(self.code, API)
|
||||||
|
|
||||||
|
class previewrend:
|
||||||
|
def __init__(self, size, cam, container, offset):
|
||||||
|
self._size = size
|
||||||
|
self._grid = {}
|
||||||
|
self._win = container
|
||||||
|
self._frame = tk.Frame(container)
|
||||||
|
self._posframe = tk.Frame(self._frame)
|
||||||
|
self._cam = cam
|
||||||
|
self._xcam = tk.Label(self._posframe, text="-")
|
||||||
|
self._ycam = tk.Label(self._posframe, text="-")
|
||||||
|
self._xcam.grid(row=size[1], column=0)
|
||||||
|
self._ycam.grid(row=size[1]+1, column=0)
|
||||||
|
|
||||||
|
tkeys = list(string.ascii_letters)
|
||||||
|
self._keys = {}
|
||||||
|
for i in tkeys:
|
||||||
|
self._keys[i] = False
|
||||||
|
self._win.bind("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", self.keydupd)
|
||||||
|
|
||||||
|
for y in range(size[1]):
|
||||||
|
for x in range(size[0]):
|
||||||
|
temp = tk.Label(self._frame, text=" ", borderwidth=1, relief=tk.GROOVE, width=3)
|
||||||
|
temp.grid(row=y+offset[1], column=x+offset[0]+1)
|
||||||
|
self._win.update()
|
||||||
|
self._grid[f"{x}:{y}"] = temp
|
||||||
|
self._posframe.grid()
|
||||||
|
self._frame.grid()
|
||||||
|
|
||||||
|
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(int(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):
|
||||||
|
self._xcam.config(text=LH.string("xcam")+str(self._cam.position.x))
|
||||||
|
self._ycam.config(text=LH.string("ycam")+str(self._cam.position.y))
|
||||||
|
if f"{x}:{y}" in self._grid:
|
||||||
|
self._grid[f"{x}:{y}"].config(text=text, bg=self.coltohex(bcolor), fg=self.coltohex(fcolor))
|
||||||
|
|
||||||
|
class nullrend:
|
||||||
|
def __init__(self, size, cam):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getkeys(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pix(self, x, y, text, bcolor, fcolor):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def selectlang(new):
|
||||||
|
lang = open("clang", 'w')
|
||||||
|
lang.write(new)
|
||||||
|
lang.close()
|
||||||
|
container.quit()
|
||||||
|
subprocess.Popen([sys.executable, __file__])
|
||||||
|
|
||||||
|
def add(objtype):
|
||||||
|
global objtree
|
||||||
|
obj = getattr(types, objtype)()
|
||||||
|
args = {}
|
||||||
|
for i in dir(obj):
|
||||||
|
if i.startswith("_"): continue
|
||||||
|
args[i] = getattr(obj, i)
|
||||||
|
temp = {"id": objtype, "args": args, "name": LH.string(objtype)}
|
||||||
|
id = ""
|
||||||
|
chars = list(string.ascii_letters)
|
||||||
|
for i in range(255):
|
||||||
|
id = id + random.choice(chars)
|
||||||
|
if GUIe == True: objtree.insert("", tk.END, text=LH.string(objtype), image=icons[objtype], iid=id, tags=("objsel"))
|
||||||
|
gamedata[id] = temp
|
||||||
|
if objtype in crucial:
|
||||||
|
preview.addobj(obj)
|
||||||
|
gamedata[id]["args"]["ID"] = obj.ID
|
||||||
|
if GUIe == True: preview.render()
|
||||||
|
return id
|
||||||
|
|
||||||
|
def renameobj():
|
||||||
|
target = objtree.focus()
|
||||||
|
if target == "": return
|
||||||
|
new = easygui.enterbox(LH.string("NN"), LH.string("rename"))
|
||||||
|
if new:
|
||||||
|
objtree.item(target, text=new)
|
||||||
|
gamedata[target]["name"] = new
|
||||||
|
|
||||||
|
def delobj():
|
||||||
|
target = objtree.focus()
|
||||||
|
if target == "": return
|
||||||
|
atritree.delete(*atritree.get_children())
|
||||||
|
objtree.delete(target)
|
||||||
|
temp = gamedata.pop(target)
|
||||||
|
if temp["id"] in crucial:
|
||||||
|
preview.removeobjbyid(temp["args"]["ID"])
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def rpopup(event):
|
||||||
|
try:
|
||||||
|
rmenu.tk_popup(event.x_root, event.y_root)
|
||||||
|
finally:
|
||||||
|
rmenu.grab_release()
|
||||||
|
|
||||||
|
def getattributes(target):
|
||||||
|
out = {}
|
||||||
|
for i in dir(target):
|
||||||
|
if i.startswith("_"): continue
|
||||||
|
out[i] = getattr(target, i)
|
||||||
|
return out
|
||||||
|
|
||||||
|
def updatribute(event):
|
||||||
|
global currentat
|
||||||
|
target = objtree.focus()
|
||||||
|
currentat = target
|
||||||
|
atritree.delete(*atritree.get_children())
|
||||||
|
for i in gamedata[target]["args"]:
|
||||||
|
if i in ignoreat: continue
|
||||||
|
|
||||||
|
if i in valtypes:
|
||||||
|
val = gamedata[target]["args"][i]
|
||||||
|
atritree.insert("", tk.END, text=i, values=(val))
|
||||||
|
else:
|
||||||
|
root = atritree.insert("", tk.END, text=i)
|
||||||
|
temp = getattributes(gamedata[target]["args"][i])
|
||||||
|
for f in temp:
|
||||||
|
atritree.insert(root, tk.END, text=f, values=(temp[f]))
|
||||||
|
|
||||||
|
def halatribute(event):
|
||||||
|
target = atritree.focus()
|
||||||
|
name = atritree.item(target, "text")
|
||||||
|
parent = atritree.parent(target)
|
||||||
|
if name in valtypes:
|
||||||
|
if parent == "":
|
||||||
|
new = valtypes[name](gamedata[currentat]["args"][name])
|
||||||
|
gamedata[currentat]["args"][name] = new
|
||||||
|
if "ID" in gamedata[currentat]["args"]:
|
||||||
|
temp = preview.getobjbyid(gamedata[currentat]["args"]["ID"])
|
||||||
|
setattr(temp, name, new)
|
||||||
|
atritree.item(target, values=(new))
|
||||||
|
else:
|
||||||
|
parent = atritree.item(parent, "text")
|
||||||
|
new = valtypes[name](getattr(gamedata[currentat]["args"][parent], name))
|
||||||
|
setattr(gamedata[currentat]["args"][parent], name, new)
|
||||||
|
atritree.item(target, values=(new))
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def updatepreviewcam(char):
|
||||||
|
global cooldown
|
||||||
|
if cooldown == True: return
|
||||||
|
cooldown = True
|
||||||
|
char = char.char
|
||||||
|
if char == "w": preview.camera.position += hashengine.vector2(y=1)
|
||||||
|
if char == "a": preview.camera.position += hashengine.vector2(x=1)
|
||||||
|
if char == "s": preview.camera.position -= hashengine.vector2(y=1)
|
||||||
|
if char == "d": preview.camera.position -= hashengine.vector2(x=1)
|
||||||
|
preview.render()
|
||||||
|
time.sleep(0)
|
||||||
|
cooldown = False
|
||||||
|
|
||||||
|
def save():
|
||||||
|
target = filedialog.asksaveasfile()
|
||||||
|
target.write(str(prepgamedata()))
|
||||||
|
target.close()
|
||||||
|
messagebox.showinfo(LH.string("suc"), LH.string("save-suc"))
|
||||||
|
|
||||||
|
def clear():
|
||||||
|
global gamedata
|
||||||
|
objtree.delete(*objtree.get_children())
|
||||||
|
atritree.delete(*atritree.get_children())
|
||||||
|
gamedata = {}
|
||||||
|
preview._objects = {}
|
||||||
|
preview.camera.position = hashengine.vector2()
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def importsound(target):
|
||||||
|
oid = add("rawsound")
|
||||||
|
gamedata[oid]["name"] = target["name"]
|
||||||
|
gamedata[oid]["args"]["sdata"] = base64.b64decode(target["args"]["sdata"])
|
||||||
|
gamedata[oid]["args"]["spath"] = target["args"]["spath"]
|
||||||
|
if GUIe == True: objtree.item(oid, text=target["name"])
|
||||||
|
|
||||||
|
def importobj(target):
|
||||||
|
if target["id"] == "sound" or target["id"] == "rawsound":
|
||||||
|
importsound(target)
|
||||||
|
return
|
||||||
|
oid = add(target["id"])
|
||||||
|
id = gamedata[oid]
|
||||||
|
id["name"] = target["name"]
|
||||||
|
if GUIe == True: objtree.item(oid, text=target["name"])
|
||||||
|
#create arguments
|
||||||
|
outargs = {}
|
||||||
|
for argname in target["args"]:
|
||||||
|
arg = target["args"][argname]
|
||||||
|
if isinstance(arg, dict):
|
||||||
|
ID = arg.pop("ARGID")
|
||||||
|
obj = attypes[ID]()
|
||||||
|
for i in arg:
|
||||||
|
setattr(obj, i, arg[i])
|
||||||
|
arg = obj
|
||||||
|
outargs[argname] = arg
|
||||||
|
#apply arguments to obj
|
||||||
|
if target["id"] in crucial:
|
||||||
|
for i in outargs:
|
||||||
|
setattr(preview.getobjbyid(gamedata[oid]["args"]["ID"]), i, outargs[i])
|
||||||
|
id["args"].update(outargs)
|
||||||
|
|
||||||
|
def load():
|
||||||
|
file = filedialog.askopenfile()
|
||||||
|
tempwin = tk.Tk()
|
||||||
|
ptext = tk.Label(tempwin, text="NONE")
|
||||||
|
ptext.place(y=30)
|
||||||
|
stat = tk.Label(tempwin, text="NONE")
|
||||||
|
stat.place(y=50)
|
||||||
|
target = file.read()
|
||||||
|
file.close()
|
||||||
|
target = ast.literal_eval(target)
|
||||||
|
clear()
|
||||||
|
count = 1
|
||||||
|
bar = tkk.Progressbar(tempwin, maximum=len(target))
|
||||||
|
bar.place(width=200)
|
||||||
|
for i in target:
|
||||||
|
ptext.config(text="Current: "+i["name"])
|
||||||
|
bar.step()
|
||||||
|
stat.config(text=f"Object {count}/{len(target)}")
|
||||||
|
tempwin.update()
|
||||||
|
importobj(i)
|
||||||
|
count += 1
|
||||||
|
tempwin.destroy()
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def log(text, end="\n", flush=False):
|
||||||
|
global logfile
|
||||||
|
if not os.path.exists("logs"):
|
||||||
|
os.mkdir("logs")
|
||||||
|
file = open("logs/"+logfile+".txt", 'a')
|
||||||
|
file.write(str(text)+end)
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
def NULL():
|
||||||
|
pass
|
||||||
|
|
||||||
|
class gsound:
|
||||||
|
def __init__(self, data, game):
|
||||||
|
self._playing = False
|
||||||
|
self._data = data
|
||||||
|
game.currentsounds.append(self)
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
if self._playing == True: return
|
||||||
|
self._sound = sa.play_buffer(self._data, 2, 2, 44100)
|
||||||
|
self._playing = True
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.stop()
|
||||||
|
self._playing = False
|
||||||
|
|
||||||
|
def wait(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.wait_done()
|
||||||
|
|
||||||
|
def testing():
|
||||||
|
global testproc
|
||||||
|
testproc = multiprocessing.Process(target=execgame, args=(prepgamedata(),))
|
||||||
|
testproc.start()
|
||||||
|
|
||||||
|
def run():
|
||||||
|
print("preparing log file...")
|
||||||
|
global logfile
|
||||||
|
global maingame
|
||||||
|
global window
|
||||||
|
temp = time.gmtime(time.time())
|
||||||
|
logfile = ""
|
||||||
|
for i in temp:
|
||||||
|
logfile = logfile + "S" + str(i)
|
||||||
|
print("done")
|
||||||
|
log("Log file start!")
|
||||||
|
log("Preparing API...")
|
||||||
|
API = {"print": log, "HASHBASE": hashengine}
|
||||||
|
log("Done!")
|
||||||
|
window = tk.Tk()
|
||||||
|
window.protocol("WM_DELETE_WINDOW", NULL)
|
||||||
|
maingame = hashengine.game(renderer=lambda size, cam: previewrend(size, cam, window, [0, 0]), sounddir="/")
|
||||||
|
API["HASHGAME"] = maingame
|
||||||
|
API["SOUND"] = lambda data: gsound(data, maingame)
|
||||||
|
log("main game initalised!")
|
||||||
|
log("copying sounds...")
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
if i["id"] != "sound" and i["id"] != "rawsound": continue
|
||||||
|
maingame.sounds[i["args"]["spath"]] = i["args"]["sdata"]
|
||||||
|
print(i["args"]["spath"])
|
||||||
|
objects = copy.deepcopy(preview._objects)
|
||||||
|
maingame._objects = objects
|
||||||
|
scripts = []
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
if i["id"] != "script": continue
|
||||||
|
i = i["args"]["code"]
|
||||||
|
obj = script()
|
||||||
|
obj.code = i
|
||||||
|
scripts.append(obj)
|
||||||
|
log("objects transferred!")
|
||||||
|
gamescript = """
|
||||||
|
global HASHGAME
|
||||||
|
import time
|
||||||
|
while True:
|
||||||
|
for i in HASHGAME._objects:
|
||||||
|
i = HASHGAME._objects[i]
|
||||||
|
HASHGAME.calcphysobj(i)
|
||||||
|
HASHGAME.render()
|
||||||
|
"""
|
||||||
|
gameloopsc = script()
|
||||||
|
gameloopsc.code = gamescript
|
||||||
|
maingame.startscript(lambda: gameloopsc.execute(API))
|
||||||
|
log("game test started!!!")
|
||||||
|
log("---------------------")
|
||||||
|
for i in scripts:
|
||||||
|
maingame.startscript(lambda: i.execute(API))
|
||||||
|
window.mainloop()
|
||||||
|
|
||||||
|
def muladd(target):
|
||||||
|
for i in range(10):
|
||||||
|
add(target)
|
||||||
|
|
||||||
|
def stoptest():
|
||||||
|
global testproc
|
||||||
|
testproc.terminate()
|
||||||
|
|
||||||
|
def build():
|
||||||
|
print("asking user for output directory...")
|
||||||
|
target = filedialog.askdirectory()
|
||||||
|
os.mkdir(target+"/out")
|
||||||
|
target = target+"/out"
|
||||||
|
print("building started")
|
||||||
|
print("generating HEGF file...")
|
||||||
|
hegf = str(prepgamedata())
|
||||||
|
file = open(target+"/game.HEGF", 'w')
|
||||||
|
file.write(hegf)
|
||||||
|
file.close()
|
||||||
|
print("done.")
|
||||||
|
print("copying files...")
|
||||||
|
tocopy = ["mtTkinter.py", "hashengine.py"]
|
||||||
|
for i in tocopy:
|
||||||
|
print(f"copying {i}...")
|
||||||
|
shutil.copyfile(i, target+"/"+i)
|
||||||
|
shutil.copyfile(__file__, target+"/"+"player.py")
|
||||||
|
file = open(target+"/main.py", 'w')
|
||||||
|
file.write("""
|
||||||
|
import player
|
||||||
|
import ast
|
||||||
|
file = open("game.HEGF", 'r')
|
||||||
|
file = file.read()
|
||||||
|
file = ast.literal_eval(file)
|
||||||
|
player.execgame(file)
|
||||||
|
""")
|
||||||
|
print("done.")
|
||||||
|
print("building finished!")
|
||||||
|
|
||||||
|
def GUIinit():
|
||||||
|
global container
|
||||||
|
global objtree
|
||||||
|
global rmenu
|
||||||
|
global atritree
|
||||||
|
global currentat
|
||||||
|
global preview
|
||||||
|
global GUIe
|
||||||
|
GUIe = True
|
||||||
|
container = tk.Tk()
|
||||||
|
container.bind("<KeyPress>", updatepreviewcam)
|
||||||
|
|
||||||
|
global icons
|
||||||
|
icons = {}
|
||||||
|
|
||||||
|
for i in os.listdir("icons"):
|
||||||
|
icons[i.split(".")[0]] = tk.PhotoImage(file=f"icons/{i}")
|
||||||
|
|
||||||
|
#preview init
|
||||||
|
preview = hashengine.game(renderer=lambda size, cam: previewrend(size, cam, container=container, offset=[0, 0]), sounddir="/")
|
||||||
|
|
||||||
|
#tree init
|
||||||
|
objtree = tkk.Treeview(container, selectmode="browse", columns=("-"))
|
||||||
|
objtree.heading("#0", text=LH.string("objs"))
|
||||||
|
objtree.tag_bind("objsel", "<<TreeviewSelect>>", updatribute)
|
||||||
|
objtree.grid(row=1, column=0)
|
||||||
|
|
||||||
|
#attribute tree init
|
||||||
|
currentat = "temp"
|
||||||
|
atritree = tkk.Treeview(container, columns=("#1"), selectmode="browse")
|
||||||
|
atritree.heading("#0", text=LH.string("attribute"))
|
||||||
|
atritree.heading("#1", text=LH.string("attribute-val"))
|
||||||
|
atritree.bind("<Double-1>", halatribute)
|
||||||
|
atritree.grid(row=2, column=0)
|
||||||
|
|
||||||
|
#right click menu
|
||||||
|
rmenu = tk.Menu(container, tearoff=0)
|
||||||
|
rmenu.add_command(label=LH.string("rename"), command=renameobj)
|
||||||
|
rmenu.add_command(label=LH.string("delete"), command=delobj)
|
||||||
|
|
||||||
|
objtree.bind("<Button-3>", rpopup)
|
||||||
|
|
||||||
|
#menu init
|
||||||
|
menu = tk.Menu(container)
|
||||||
|
container.config(menu=menu)
|
||||||
|
filemenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("file"), menu=filemenu)
|
||||||
|
filemenu.add_command(label=LH.string("new"), command=clear)
|
||||||
|
filemenu.add_command(label=LH.string("open"), command=load)
|
||||||
|
filemenu.add_command(label=LH.string("save"), command=save)
|
||||||
|
filemenu.add_separator()
|
||||||
|
filemenu.add_command(label=LH.string("exit"), command=container.quit)
|
||||||
|
|
||||||
|
addmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("add"), menu=addmenu)
|
||||||
|
addmenu.add_command(label=LH.string("obj"), command=lambda: add("obj"))
|
||||||
|
addmenu.add_command(label=LH.string("script"), command=lambda: add("script"))
|
||||||
|
addmenu.add_command(label=LH.string("sound"), command=lambda: add("sound"))
|
||||||
|
#addmenu.add_command(label=LH.string("obj"), command=lambda: muladd("obj"))
|
||||||
|
|
||||||
|
testmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("testing"), menu=testmenu)
|
||||||
|
testmenu.add_command(label=LH.string("test"), command=testing, image=icons["test"], compound="left")
|
||||||
|
testmenu.add_command(label=LH.string("stest"), command=stoptest, image=icons["stop-test"], compound="left")
|
||||||
|
|
||||||
|
buildmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("building"), menu=buildmenu)
|
||||||
|
buildmenu.add_command(label=LH.string("build"), command=build, image=icons["build"], compound="left")
|
||||||
|
|
||||||
|
langmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("langs"), menu=langmenu)
|
||||||
|
for i in LH.getlangs():
|
||||||
|
langmenu.add_command(label=i, command=lambda i=i: selectlang(i))
|
||||||
|
|
||||||
|
container.mainloop()
|
||||||
|
|
||||||
|
# attribute changers
|
||||||
|
def ats(mode, old):
|
||||||
|
#mode 0 = string
|
||||||
|
#mode 1 = single character
|
||||||
|
out = easygui.enterbox(LH.string("newval"), LH.string("newval"))
|
||||||
|
if out:
|
||||||
|
if mode == 1 and len(out) != 1:
|
||||||
|
messagebox.showerror(LH.string("error"), LH.string("SCE"))
|
||||||
|
return "N"
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def anum(old):
|
||||||
|
out = easygui.enterbox(LH.string("newval"), LH.string("newval"))
|
||||||
|
if out:
|
||||||
|
if "." in out:
|
||||||
|
try:
|
||||||
|
out = float(out)
|
||||||
|
return out
|
||||||
|
except ValueError:
|
||||||
|
return old
|
||||||
|
else:
|
||||||
|
return int(out)
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def abool(old):
|
||||||
|
out = easygui.boolbox(LH.string("newval"), LH.string("newval"), (LH.string("true"), LH.string("false")))
|
||||||
|
if out:
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def acode(old):
|
||||||
|
out = easygui.textbox(LH.string("newval"), LH.string("newval"), old)
|
||||||
|
if out:
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def apath(old, ext):
|
||||||
|
new = filedialog.askopenfilename(defaultextension=ext, filetypes=(ext))
|
||||||
|
if new:
|
||||||
|
return new
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def aNULL(old):
|
||||||
|
return old
|
||||||
|
|
||||||
|
def execgame(gametree):
|
||||||
|
global GUIe
|
||||||
|
global preview
|
||||||
|
preview = hashengine.game(renderer=nullrend, sounddir="/")
|
||||||
|
GUIe = False
|
||||||
|
for i in gametree:
|
||||||
|
importobj(i)
|
||||||
|
run()
|
||||||
|
|
||||||
|
class rsound:
|
||||||
|
def __init__(self):
|
||||||
|
self.spath = ""
|
||||||
|
self.sdata = b""
|
||||||
|
|
||||||
|
class sound():
|
||||||
|
def __init__(self, new):
|
||||||
|
self.spath = os.path.basename(new).split(".")[0]
|
||||||
|
self.sdata = hashengine.loadsound(new)
|
||||||
|
|
||||||
|
global types
|
||||||
|
global ignoreat
|
||||||
|
global valtypes
|
||||||
|
global extypes
|
||||||
|
global attypes
|
||||||
|
global crucial
|
||||||
|
crucial = ["obj"]
|
||||||
|
types = hashengine.enum({"obj": hashengine.obj, "script": script, "rawsound": rsound, "sound": lambda: sound(apath("", [("Wave files", ".wave .wav")]))})
|
||||||
|
ignoreat = ["ID", "execute", "sdata"]
|
||||||
|
"""self.position = vector2()
|
||||||
|
self.char = " "
|
||||||
|
self.ID = 0
|
||||||
|
self.gravity = 0
|
||||||
|
self.acceleration = vector2()
|
||||||
|
self.velocity = vector2()
|
||||||
|
self.friction = 0
|
||||||
|
self.collide = True
|
||||||
|
self.touch = True
|
||||||
|
self.anchored = False
|
||||||
|
self.bcolor = color3(255, 255, 255)
|
||||||
|
self.fcolor = color3()"""
|
||||||
|
valtypes = {
|
||||||
|
"char": lambda old: ats(1, old),
|
||||||
|
"gravity": anum,
|
||||||
|
"x": anum,
|
||||||
|
"y": anum,
|
||||||
|
"z": anum,
|
||||||
|
"r": anum,
|
||||||
|
"g": anum,
|
||||||
|
"b": anum,
|
||||||
|
"friction": anum,
|
||||||
|
"collide": abool,
|
||||||
|
"touch": abool,
|
||||||
|
"anchored": abool,
|
||||||
|
"code": acode,
|
||||||
|
"spath": aNULL,
|
||||||
|
}
|
||||||
|
#lambda old: apath(old, [("Wave files", ".wave .wav")])
|
||||||
|
extypes = list(valtypes.keys())
|
||||||
|
attypes = {
|
||||||
|
"vector2": hashengine.vector2,
|
||||||
|
"color3": hashengine.color3,
|
||||||
|
}
|
||||||
|
if __name__ == "__main__":
|
||||||
|
GUIinit()
|
|
@ -0,0 +1,336 @@
|
||||||
|
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("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", 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 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
|
||||||
|
|
||||||
|
def calcphysobj(self, target: obj):
|
||||||
|
if target.anchored == True: return
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
|
||||||
|
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()):
|
||||||
|
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))
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
Log file start!
|
||||||
|
Preparing API...
|
||||||
|
Done!
|
||||||
|
main game initalised!
|
||||||
|
copying sounds...
|
||||||
|
objects transferred!
|
||||||
|
game test started!!!
|
||||||
|
---------------------
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
import player
|
||||||
|
import ast
|
||||||
|
file = open("game.HEGF", 'r')
|
||||||
|
file = file.read()
|
||||||
|
file = ast.literal_eval(file)
|
||||||
|
player.execgame(file)
|
|
@ -0,0 +1,725 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.dont_write_bytecode = True
|
||||||
|
import mtTkinter as tk
|
||||||
|
from tkinter import ttk as tkk
|
||||||
|
from tkinter import messagebox
|
||||||
|
from tkinter import filedialog
|
||||||
|
import copy
|
||||||
|
import hashengine
|
||||||
|
global LH
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import PCPL
|
||||||
|
import langsys
|
||||||
|
PCPL.interpreter.ENG = hashengine
|
||||||
|
LH = langsys.langhandler()
|
||||||
|
lang = open("clang", 'r')
|
||||||
|
lang = lang.read()
|
||||||
|
LH.setlang(lang)
|
||||||
|
# LH.string("")
|
||||||
|
else:
|
||||||
|
class rLH:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
def string(self, target):
|
||||||
|
return target
|
||||||
|
LH = rLH()
|
||||||
|
import ast
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import easygui
|
||||||
|
import base64
|
||||||
|
import simpleaudio as sa
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
global gamedata
|
||||||
|
global cooldown
|
||||||
|
cooldown = False
|
||||||
|
gamedata = {}
|
||||||
|
|
||||||
|
def prepgamedata():
|
||||||
|
out = []
|
||||||
|
tempwin = tk.Tk()
|
||||||
|
bar = tkk.Progressbar(tempwin)
|
||||||
|
bar.place(width=200)
|
||||||
|
ptext = tk.Label(tempwin, text="NONE")
|
||||||
|
ptext.place()
|
||||||
|
count = 1
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
ptext.config(text=i["name"])
|
||||||
|
bar.step(count/len(gamedata))
|
||||||
|
count += 1
|
||||||
|
tempwin.update()
|
||||||
|
temp = {"id": i["id"], "name": i["name"]}
|
||||||
|
tempargs = {}
|
||||||
|
tosearch = {}
|
||||||
|
for arg in i["args"]:
|
||||||
|
if not arg in extypes and not arg in ignoreat and arg != "sdata":
|
||||||
|
tosearch[arg] = i["args"][arg]
|
||||||
|
continue
|
||||||
|
if arg in ignoreat and arg != "sdata": continue
|
||||||
|
if arg != "sdata":
|
||||||
|
tempargs[arg] = i["args"][arg]
|
||||||
|
else:
|
||||||
|
tempargs[arg] = str(base64.b64encode(i["args"][arg]), "ascii", "ignore")
|
||||||
|
for argname in tosearch:
|
||||||
|
arg = tosearch[argname]
|
||||||
|
temp2 = getattributes(arg)
|
||||||
|
temp2.update({"ARGID": arg._type})
|
||||||
|
tempargs[argname] = temp2
|
||||||
|
temp["args"] = tempargs
|
||||||
|
out.append(temp)
|
||||||
|
tempwin.destroy()
|
||||||
|
return out
|
||||||
|
|
||||||
|
class script:
|
||||||
|
def __init__(self):
|
||||||
|
self.code = ""
|
||||||
|
|
||||||
|
def execute(self, API):
|
||||||
|
#old code for PCPL code execution, replaced with python code execution
|
||||||
|
"""
|
||||||
|
PCPL.resetvar()
|
||||||
|
PCPL.LIS("HASHBASE")
|
||||||
|
PCPL.run(self.code)"""
|
||||||
|
exec(self.code, API)
|
||||||
|
|
||||||
|
class previewrend:
|
||||||
|
def __init__(self, size, cam, container, offset):
|
||||||
|
self._size = size
|
||||||
|
self._grid = {}
|
||||||
|
self._win = container
|
||||||
|
self._frame = tk.Frame(container)
|
||||||
|
self._posframe = tk.Frame(self._frame)
|
||||||
|
self._cam = cam
|
||||||
|
self._xcam = tk.Label(self._posframe, text="-")
|
||||||
|
self._ycam = tk.Label(self._posframe, text="-")
|
||||||
|
self._xcam.grid(row=size[1], column=0)
|
||||||
|
self._ycam.grid(row=size[1]+1, column=0)
|
||||||
|
|
||||||
|
tkeys = list(string.ascii_letters)
|
||||||
|
self._keys = {}
|
||||||
|
for i in tkeys:
|
||||||
|
self._keys[i] = False
|
||||||
|
self._win.bind("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", self.keydupd)
|
||||||
|
|
||||||
|
for y in range(size[1]):
|
||||||
|
for x in range(size[0]):
|
||||||
|
temp = tk.Label(self._frame, text=" ", borderwidth=1, relief=tk.GROOVE, width=3)
|
||||||
|
temp.grid(row=y+offset[1], column=x+offset[0]+1)
|
||||||
|
self._win.update()
|
||||||
|
self._grid[f"{x}:{y}"] = temp
|
||||||
|
self._posframe.grid()
|
||||||
|
self._frame.grid()
|
||||||
|
|
||||||
|
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(int(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):
|
||||||
|
self._xcam.config(text=LH.string("xcam")+str(self._cam.position.x))
|
||||||
|
self._ycam.config(text=LH.string("ycam")+str(self._cam.position.y))
|
||||||
|
if f"{x}:{y}" in self._grid:
|
||||||
|
self._grid[f"{x}:{y}"].config(text=text, bg=self.coltohex(bcolor), fg=self.coltohex(fcolor))
|
||||||
|
|
||||||
|
class render:
|
||||||
|
def __init__(self, size, cam, container, offset):
|
||||||
|
self._size = size
|
||||||
|
self._grid = {}
|
||||||
|
self._win = container
|
||||||
|
self._frame = tk.Frame(container)
|
||||||
|
self._posframe = tk.Frame(self._frame)
|
||||||
|
self._cam = cam
|
||||||
|
self._xcam = tk.Label(self._posframe, text="-")
|
||||||
|
self._ycam = tk.Label(self._posframe, text="-")
|
||||||
|
#self._xcam.grid(row=size[1], column=0)
|
||||||
|
#self._ycam.grid(row=size[1]+1, column=0)
|
||||||
|
|
||||||
|
tkeys = list(string.ascii_letters)
|
||||||
|
self._keys = {}
|
||||||
|
for i in tkeys:
|
||||||
|
self._keys[i] = False
|
||||||
|
self._win.bind("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", self.keydupd)
|
||||||
|
|
||||||
|
for y in range(size[1]):
|
||||||
|
for x in range(size[0]):
|
||||||
|
temp = tk.Label(self._frame, text=" ", width=3)
|
||||||
|
temp.grid(row=y+offset[1], column=x+offset[0]+1)
|
||||||
|
self._win.update()
|
||||||
|
self._grid[f"{x}:{y}"] = temp
|
||||||
|
self._posframe.grid()
|
||||||
|
self._frame.grid()
|
||||||
|
|
||||||
|
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(int(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):
|
||||||
|
self._xcam.config(text=LH.string("xcam")+str(self._cam.position.x))
|
||||||
|
self._ycam.config(text=LH.string("ycam")+str(self._cam.position.y))
|
||||||
|
if f"{x}:{y}" in self._grid:
|
||||||
|
self._grid[f"{x}:{y}"].config(text=text, bg=self.coltohex(bcolor), fg=self.coltohex(fcolor))
|
||||||
|
|
||||||
|
class nullrend:
|
||||||
|
def __init__(self, size, cam):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getkeys(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pix(self, x, y, text, bcolor, fcolor):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def selectlang(new):
|
||||||
|
lang = open("clang", 'w')
|
||||||
|
lang.write(new)
|
||||||
|
lang.close()
|
||||||
|
container.quit()
|
||||||
|
subprocess.Popen([sys.executable, __file__])
|
||||||
|
|
||||||
|
def add(objtype):
|
||||||
|
global objtree
|
||||||
|
obj = getattr(types, objtype)()
|
||||||
|
args = {}
|
||||||
|
for i in dir(obj):
|
||||||
|
if i.startswith("_"): continue
|
||||||
|
args[i] = getattr(obj, i)
|
||||||
|
temp = {"id": objtype, "args": args, "name": LH.string(objtype)}
|
||||||
|
id = ""
|
||||||
|
chars = list(string.ascii_letters)
|
||||||
|
for i in range(255):
|
||||||
|
id = id + random.choice(chars)
|
||||||
|
if GUIe == True: objtree.insert("", tk.END, text=LH.string(objtype), image=icons[objtype], iid=id, tags=("objsel"))
|
||||||
|
gamedata[id] = temp
|
||||||
|
if objtype in crucial:
|
||||||
|
preview.addobj(obj)
|
||||||
|
gamedata[id]["args"]["ID"] = obj.ID
|
||||||
|
if GUIe == True: preview.render()
|
||||||
|
return id
|
||||||
|
|
||||||
|
def renameobj():
|
||||||
|
target = objtree.focus()
|
||||||
|
if target == "": return
|
||||||
|
new = easygui.enterbox(LH.string("NN"), LH.string("rename"))
|
||||||
|
if new:
|
||||||
|
objtree.item(target, text=new)
|
||||||
|
gamedata[target]["name"] = new
|
||||||
|
|
||||||
|
def delobj():
|
||||||
|
target = objtree.focus()
|
||||||
|
if target == "": return
|
||||||
|
atritree.delete(*atritree.get_children())
|
||||||
|
objtree.delete(target)
|
||||||
|
temp = gamedata.pop(target)
|
||||||
|
if temp["id"] in crucial:
|
||||||
|
preview.removeobjbyid(temp["args"]["ID"])
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def rpopup(event):
|
||||||
|
try:
|
||||||
|
rmenu.tk_popup(event.x_root, event.y_root)
|
||||||
|
finally:
|
||||||
|
rmenu.grab_release()
|
||||||
|
|
||||||
|
def getattributes(target):
|
||||||
|
out = {}
|
||||||
|
for i in dir(target):
|
||||||
|
if i.startswith("_"): continue
|
||||||
|
out[i] = getattr(target, i)
|
||||||
|
return out
|
||||||
|
|
||||||
|
def updatribute(event):
|
||||||
|
global currentat
|
||||||
|
target = objtree.focus()
|
||||||
|
currentat = target
|
||||||
|
atritree.delete(*atritree.get_children())
|
||||||
|
for i in gamedata[target]["args"]:
|
||||||
|
if i in ignoreat: continue
|
||||||
|
|
||||||
|
if i in valtypes:
|
||||||
|
val = gamedata[target]["args"][i]
|
||||||
|
atritree.insert("", tk.END, text=i, values=(val))
|
||||||
|
else:
|
||||||
|
root = atritree.insert("", tk.END, text=i)
|
||||||
|
temp = getattributes(gamedata[target]["args"][i])
|
||||||
|
for f in temp:
|
||||||
|
atritree.insert(root, tk.END, text=f, values=(temp[f]))
|
||||||
|
|
||||||
|
def halatribute(event):
|
||||||
|
target = atritree.focus()
|
||||||
|
name = atritree.item(target, "text")
|
||||||
|
parent = atritree.parent(target)
|
||||||
|
if name in valtypes:
|
||||||
|
if parent == "":
|
||||||
|
new = valtypes[name](gamedata[currentat]["args"][name])
|
||||||
|
gamedata[currentat]["args"][name] = new
|
||||||
|
if "ID" in gamedata[currentat]["args"]:
|
||||||
|
temp = preview.getobjbyid(gamedata[currentat]["args"]["ID"])
|
||||||
|
setattr(temp, name, new)
|
||||||
|
atritree.item(target, values=(new))
|
||||||
|
else:
|
||||||
|
parent = atritree.item(parent, "text")
|
||||||
|
new = valtypes[name](getattr(gamedata[currentat]["args"][parent], name))
|
||||||
|
setattr(gamedata[currentat]["args"][parent], name, new)
|
||||||
|
atritree.item(target, values=(new))
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def updatepreviewcam(char):
|
||||||
|
global cooldown
|
||||||
|
if cooldown == True: return
|
||||||
|
cooldown = True
|
||||||
|
char = char.char
|
||||||
|
if char == "w": preview.camera.position += hashengine.vector2(y=1)
|
||||||
|
if char == "a": preview.camera.position += hashengine.vector2(x=1)
|
||||||
|
if char == "s": preview.camera.position -= hashengine.vector2(y=1)
|
||||||
|
if char == "d": preview.camera.position -= hashengine.vector2(x=1)
|
||||||
|
preview.render()
|
||||||
|
time.sleep(0)
|
||||||
|
cooldown = False
|
||||||
|
|
||||||
|
def save():
|
||||||
|
target = filedialog.asksaveasfile()
|
||||||
|
target.write(str(prepgamedata()))
|
||||||
|
target.close()
|
||||||
|
messagebox.showinfo(LH.string("suc"), LH.string("save-suc"))
|
||||||
|
|
||||||
|
def clear():
|
||||||
|
global gamedata
|
||||||
|
objtree.delete(*objtree.get_children())
|
||||||
|
atritree.delete(*atritree.get_children())
|
||||||
|
gamedata = {}
|
||||||
|
preview._objects = {}
|
||||||
|
preview.camera.position = hashengine.vector2()
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def importsound(target):
|
||||||
|
oid = add("rawsound")
|
||||||
|
gamedata[oid]["name"] = target["name"]
|
||||||
|
gamedata[oid]["args"]["sdata"] = base64.b64decode(target["args"]["sdata"])
|
||||||
|
gamedata[oid]["args"]["spath"] = target["args"]["spath"]
|
||||||
|
if GUIe == True: objtree.item(oid, text=target["name"])
|
||||||
|
|
||||||
|
def importobj(target):
|
||||||
|
if target["id"] == "sound" or target["id"] == "rawsound":
|
||||||
|
importsound(target)
|
||||||
|
return
|
||||||
|
oid = add(target["id"])
|
||||||
|
id = gamedata[oid]
|
||||||
|
id["name"] = target["name"]
|
||||||
|
if GUIe == True: objtree.item(oid, text=target["name"])
|
||||||
|
#create arguments
|
||||||
|
outargs = {}
|
||||||
|
for argname in target["args"]:
|
||||||
|
arg = target["args"][argname]
|
||||||
|
if isinstance(arg, dict):
|
||||||
|
ID = arg.pop("ARGID")
|
||||||
|
obj = attypes[ID]()
|
||||||
|
for i in arg:
|
||||||
|
setattr(obj, i, arg[i])
|
||||||
|
arg = obj
|
||||||
|
outargs[argname] = arg
|
||||||
|
#apply arguments to obj
|
||||||
|
if target["id"] in crucial:
|
||||||
|
for i in outargs:
|
||||||
|
setattr(preview.getobjbyid(gamedata[oid]["args"]["ID"]), i, outargs[i])
|
||||||
|
id["args"].update(outargs)
|
||||||
|
|
||||||
|
def load():
|
||||||
|
file = filedialog.askopenfile()
|
||||||
|
tempwin = tk.Tk()
|
||||||
|
ptext = tk.Label(tempwin, text="NONE")
|
||||||
|
ptext.place(y=30)
|
||||||
|
stat = tk.Label(tempwin, text="NONE")
|
||||||
|
stat.place(y=50)
|
||||||
|
target = file.read()
|
||||||
|
file.close()
|
||||||
|
target = ast.literal_eval(target)
|
||||||
|
clear()
|
||||||
|
count = 1
|
||||||
|
bar = tkk.Progressbar(tempwin, maximum=len(target))
|
||||||
|
bar.place(width=200)
|
||||||
|
for i in target:
|
||||||
|
ptext.config(text="Current: "+i["name"])
|
||||||
|
bar.step()
|
||||||
|
stat.config(text=f"Object {count}/{len(target)}")
|
||||||
|
tempwin.update()
|
||||||
|
importobj(i)
|
||||||
|
count += 1
|
||||||
|
tempwin.destroy()
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def log(text, end="\n", flush=False):
|
||||||
|
global logfile
|
||||||
|
if not os.path.exists("logs"):
|
||||||
|
os.mkdir("logs")
|
||||||
|
file = open("logs/"+logfile+".txt", 'a')
|
||||||
|
file.write(str(text)+end)
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
def NULL():
|
||||||
|
pass
|
||||||
|
|
||||||
|
class gsound:
|
||||||
|
def __init__(self, data, game):
|
||||||
|
self._playing = False
|
||||||
|
self._data = data
|
||||||
|
game.currentsounds.append(self)
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
if self._playing == True: return
|
||||||
|
self._sound = sa.play_buffer(self._data, 2, 2, 44100)
|
||||||
|
self._playing = True
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.stop()
|
||||||
|
self._playing = False
|
||||||
|
|
||||||
|
def wait(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.wait_done()
|
||||||
|
|
||||||
|
def testing():
|
||||||
|
global testproc
|
||||||
|
testproc = multiprocessing.Process(target=execgame, args=(prepgamedata(),))
|
||||||
|
testproc.start()
|
||||||
|
|
||||||
|
def run():
|
||||||
|
print("preparing log file...")
|
||||||
|
global logfile
|
||||||
|
global maingame
|
||||||
|
global window
|
||||||
|
temp = time.gmtime(time.time())
|
||||||
|
logfile = ""
|
||||||
|
for i in temp:
|
||||||
|
logfile = logfile + "S" + str(i)
|
||||||
|
print("done")
|
||||||
|
log("Log file start!")
|
||||||
|
log("Preparing API...")
|
||||||
|
API = {"print": log, "HASHBASE": hashengine}
|
||||||
|
log("Done!")
|
||||||
|
window = tk.Tk()
|
||||||
|
window.protocol("WM_DELETE_WINDOW", NULL)
|
||||||
|
maingame = hashengine.game(renderer=lambda size, cam: render(size, cam, window, [0, 0]), sounddir="/")
|
||||||
|
API["HASHGAME"] = maingame
|
||||||
|
API["SOUND"] = lambda data: gsound(data, maingame)
|
||||||
|
log("main game initalised!")
|
||||||
|
log("copying sounds...")
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
if i["id"] != "sound" and i["id"] != "rawsound": continue
|
||||||
|
maingame.sounds[i["args"]["spath"]] = i["args"]["sdata"]
|
||||||
|
print(i["args"]["spath"])
|
||||||
|
objects = copy.deepcopy(preview._objects)
|
||||||
|
maingame._objects = objects
|
||||||
|
scripts = []
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
if i["id"] != "script": continue
|
||||||
|
i = i["args"]["code"]
|
||||||
|
obj = script()
|
||||||
|
obj.code = i
|
||||||
|
scripts.append(obj)
|
||||||
|
log("objects transferred!")
|
||||||
|
gamescript = """
|
||||||
|
global HASHGAME
|
||||||
|
import time
|
||||||
|
while True:
|
||||||
|
for i in HASHGAME._objects:
|
||||||
|
i = HASHGAME._objects[i]
|
||||||
|
HASHGAME.calcphysobj(i)
|
||||||
|
HASHGAME.render()
|
||||||
|
"""
|
||||||
|
gameloopsc = script()
|
||||||
|
gameloopsc.code = gamescript
|
||||||
|
maingame.startscript(lambda: gameloopsc.execute(API))
|
||||||
|
log("game test started!!!")
|
||||||
|
log("---------------------")
|
||||||
|
for i in scripts:
|
||||||
|
maingame.startscript(lambda: i.execute(API))
|
||||||
|
window.mainloop()
|
||||||
|
|
||||||
|
def muladd(target):
|
||||||
|
for i in range(10):
|
||||||
|
add(target)
|
||||||
|
|
||||||
|
def stoptest():
|
||||||
|
global testproc
|
||||||
|
testproc.terminate()
|
||||||
|
|
||||||
|
def build():
|
||||||
|
print("asking user for output directory...")
|
||||||
|
target = filedialog.askdirectory()
|
||||||
|
os.mkdir(target+"/out")
|
||||||
|
target = target+"/out"
|
||||||
|
print("building started")
|
||||||
|
print("generating HEGF file...")
|
||||||
|
hegf = str(prepgamedata())
|
||||||
|
file = open(target+"/game.HEGF", 'w')
|
||||||
|
file.write(hegf)
|
||||||
|
file.close()
|
||||||
|
print("done.")
|
||||||
|
print("copying files...")
|
||||||
|
tocopy = ["mtTkinter.py", "hashengine.py"]
|
||||||
|
for i in tocopy:
|
||||||
|
print(f"copying {i}...")
|
||||||
|
shutil.copyfile(i, target+"/"+i)
|
||||||
|
shutil.copyfile(__file__, target+"/"+"player.py")
|
||||||
|
file = open(target+"/main.py", 'w')
|
||||||
|
file.write("""
|
||||||
|
import player
|
||||||
|
import ast
|
||||||
|
file = open("game.HEGF", 'r')
|
||||||
|
file = file.read()
|
||||||
|
file = ast.literal_eval(file)
|
||||||
|
player.execgame(file)
|
||||||
|
""")
|
||||||
|
print("done.")
|
||||||
|
print("building finished!")
|
||||||
|
|
||||||
|
def GUIinit():
|
||||||
|
global container
|
||||||
|
global objtree
|
||||||
|
global rmenu
|
||||||
|
global atritree
|
||||||
|
global currentat
|
||||||
|
global preview
|
||||||
|
global GUIe
|
||||||
|
GUIe = True
|
||||||
|
container = tk.Tk()
|
||||||
|
container.bind("<KeyPress>", updatepreviewcam)
|
||||||
|
|
||||||
|
global icons
|
||||||
|
icons = {}
|
||||||
|
|
||||||
|
for i in os.listdir("icons"):
|
||||||
|
icons[i.split(".")[0]] = tk.PhotoImage(file=f"icons/{i}")
|
||||||
|
|
||||||
|
#preview init
|
||||||
|
preview = hashengine.game(renderer=lambda size, cam: previewrend(size, cam, container=container, offset=[0, 0]), sounddir="/")
|
||||||
|
|
||||||
|
#tree init
|
||||||
|
objtree = tkk.Treeview(container, selectmode="browse", columns=("-"))
|
||||||
|
objtree.heading("#0", text=LH.string("objs"))
|
||||||
|
objtree.tag_bind("objsel", "<<TreeviewSelect>>", updatribute)
|
||||||
|
objtree.grid(row=1, column=0)
|
||||||
|
|
||||||
|
#attribute tree init
|
||||||
|
currentat = "temp"
|
||||||
|
atritree = tkk.Treeview(container, columns=("#1"), selectmode="browse")
|
||||||
|
atritree.heading("#0", text=LH.string("attribute"))
|
||||||
|
atritree.heading("#1", text=LH.string("attribute-val"))
|
||||||
|
atritree.bind("<Double-1>", halatribute)
|
||||||
|
atritree.grid(row=2, column=0)
|
||||||
|
|
||||||
|
#right click menu
|
||||||
|
rmenu = tk.Menu(container, tearoff=0)
|
||||||
|
rmenu.add_command(label=LH.string("rename"), command=renameobj)
|
||||||
|
rmenu.add_command(label=LH.string("delete"), command=delobj)
|
||||||
|
|
||||||
|
objtree.bind("<Button-3>", rpopup)
|
||||||
|
|
||||||
|
#menu init
|
||||||
|
menu = tk.Menu(container)
|
||||||
|
container.config(menu=menu)
|
||||||
|
filemenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("file"), menu=filemenu)
|
||||||
|
filemenu.add_command(label=LH.string("new"), command=clear)
|
||||||
|
filemenu.add_command(label=LH.string("open"), command=load)
|
||||||
|
filemenu.add_command(label=LH.string("save"), command=save)
|
||||||
|
filemenu.add_separator()
|
||||||
|
filemenu.add_command(label=LH.string("exit"), command=container.quit)
|
||||||
|
|
||||||
|
addmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("add"), menu=addmenu)
|
||||||
|
addmenu.add_command(label=LH.string("obj"), command=lambda: add("obj"))
|
||||||
|
addmenu.add_command(label=LH.string("script"), command=lambda: add("script"))
|
||||||
|
addmenu.add_command(label=LH.string("sound"), command=lambda: add("sound"))
|
||||||
|
#addmenu.add_command(label=LH.string("obj"), command=lambda: muladd("obj"))
|
||||||
|
|
||||||
|
testmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("testing"), menu=testmenu)
|
||||||
|
testmenu.add_command(label=LH.string("test"), command=testing, image=icons["test"], compound="left")
|
||||||
|
testmenu.add_command(label=LH.string("stest"), command=stoptest, image=icons["stop-test"], compound="left")
|
||||||
|
|
||||||
|
buildmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("building"), menu=buildmenu)
|
||||||
|
buildmenu.add_command(label=LH.string("build"), command=build, image=icons["build"], compound="left")
|
||||||
|
|
||||||
|
langmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("langs"), menu=langmenu)
|
||||||
|
for i in LH.getlangs():
|
||||||
|
langmenu.add_command(label=i, command=lambda i=i: selectlang(i))
|
||||||
|
|
||||||
|
container.mainloop()
|
||||||
|
|
||||||
|
# attribute changers
|
||||||
|
def ats(mode, old):
|
||||||
|
#mode 0 = string
|
||||||
|
#mode 1 = single character
|
||||||
|
out = easygui.enterbox(LH.string("newval"), LH.string("newval"))
|
||||||
|
if out:
|
||||||
|
if mode == 1 and len(out) != 1:
|
||||||
|
messagebox.showerror(LH.string("error"), LH.string("SCE"))
|
||||||
|
return "N"
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def anum(old):
|
||||||
|
out = easygui.enterbox(LH.string("newval"), LH.string("newval"))
|
||||||
|
if out:
|
||||||
|
if "." in out:
|
||||||
|
try:
|
||||||
|
out = float(out)
|
||||||
|
return out
|
||||||
|
except ValueError:
|
||||||
|
return old
|
||||||
|
else:
|
||||||
|
return int(out)
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def abool(old):
|
||||||
|
out = easygui.boolbox(LH.string("newval"), LH.string("newval"), (LH.string("true"), LH.string("false")))
|
||||||
|
if out:
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def acode(old):
|
||||||
|
out = easygui.textbox(LH.string("newval"), LH.string("newval"), old)
|
||||||
|
if out:
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def apath(old, ext):
|
||||||
|
new = filedialog.askopenfilename(defaultextension=ext, filetypes=(ext))
|
||||||
|
if new:
|
||||||
|
return new
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def aNULL(old):
|
||||||
|
return old
|
||||||
|
|
||||||
|
def execgame(gametree):
|
||||||
|
global GUIe
|
||||||
|
global preview
|
||||||
|
preview = hashengine.game(renderer=nullrend, sounddir="/")
|
||||||
|
GUIe = False
|
||||||
|
for i in gametree:
|
||||||
|
importobj(i)
|
||||||
|
run()
|
||||||
|
|
||||||
|
class rsound:
|
||||||
|
def __init__(self):
|
||||||
|
self.spath = ""
|
||||||
|
self.sdata = b""
|
||||||
|
|
||||||
|
class sound():
|
||||||
|
def __init__(self, new):
|
||||||
|
self.spath = os.path.basename(new).split(".")[0]
|
||||||
|
self.sdata = hashengine.loadsound(new)
|
||||||
|
|
||||||
|
global types
|
||||||
|
global ignoreat
|
||||||
|
global valtypes
|
||||||
|
global extypes
|
||||||
|
global attypes
|
||||||
|
global crucial
|
||||||
|
crucial = ["obj"]
|
||||||
|
types = hashengine.enum({"obj": hashengine.obj, "script": script, "rawsound": rsound, "sound": lambda: sound(apath("", [("Wave files", ".wave .wav")]))})
|
||||||
|
ignoreat = ["ID", "execute", "sdata"]
|
||||||
|
"""self.position = vector2()
|
||||||
|
self.char = " "
|
||||||
|
self.ID = 0
|
||||||
|
self.gravity = 0
|
||||||
|
self.acceleration = vector2()
|
||||||
|
self.velocity = vector2()
|
||||||
|
self.friction = 0
|
||||||
|
self.collide = True
|
||||||
|
self.touch = True
|
||||||
|
self.anchored = False
|
||||||
|
self.bcolor = color3(255, 255, 255)
|
||||||
|
self.fcolor = color3()"""
|
||||||
|
valtypes = {
|
||||||
|
"char": lambda old: ats(1, old),
|
||||||
|
"gravity": anum,
|
||||||
|
"x": anum,
|
||||||
|
"y": anum,
|
||||||
|
"z": anum,
|
||||||
|
"r": anum,
|
||||||
|
"g": anum,
|
||||||
|
"b": anum,
|
||||||
|
"friction": anum,
|
||||||
|
"collide": abool,
|
||||||
|
"touch": abool,
|
||||||
|
"anchored": abool,
|
||||||
|
"code": acode,
|
||||||
|
"spath": aNULL,
|
||||||
|
}
|
||||||
|
#lambda old: apath(old, [("Wave files", ".wave .wav")])
|
||||||
|
extypes = list(valtypes.keys())
|
||||||
|
attypes = {
|
||||||
|
"vector2": hashengine.vector2,
|
||||||
|
"color3": hashengine.color3,
|
||||||
|
}
|
||||||
|
if __name__ == "__main__":
|
||||||
|
GUIinit()
|
|
@ -0,0 +1 @@
|
||||||
|
[{'id': 'obj', 'name': 'testobj', 'args': {'anchored': False, 'char': '#', 'collide': True, 'friction': 0, 'gravity': 0, 'acceleration': {'x': 0, 'y': 0, 'ARGID': 'vector2'}, 'bcolor': {'b': 0, 'g': 255, 'r': 255, 'ARGID': 'color3'}, 'fcolor': {'b': 0, 'g': 0, 'r': 255, 'ARGID': 'color3'}, 'position': {'x': 5, 'y': 5, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'script', 'name': 'skript pos test', 'args': {'code': 'import random\nimport time\ntime.sleep(3)\nobjects = list(HASHGAME._objects.values())\nobject = objects[0]\nstartpos = object.position\nwhile True:\n\tobject.position = startpos + HASHBASE.vector2(random.randint(-3, 3), random.randint(-3, 3))\n\ttime.sleep(.01)'}}]
|
|
@ -0,0 +1,175 @@
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
# Python 2
|
||||||
|
from Tkinter import *
|
||||||
|
import Queue as queue
|
||||||
|
else:
|
||||||
|
# Python 3
|
||||||
|
from tkinter import *
|
||||||
|
import queue
|
||||||
|
|
||||||
|
|
||||||
|
class _Tk(object):
|
||||||
|
"""Wrapper for underlying attribute tk of class Tk"""
|
||||||
|
|
||||||
|
def __init__(self, tk, mt_debug=0, mt_check_period=10):
|
||||||
|
"""
|
||||||
|
:param tk: Tkinter.Tk.tk Tk interpreter object
|
||||||
|
:param mt_debug: Determines amount of debug output.
|
||||||
|
0 = No debug output (default)
|
||||||
|
1 = Minimal debug output
|
||||||
|
...
|
||||||
|
9 = Full debug output
|
||||||
|
:param mt_check_period: Amount of time in milliseconds (default
|
||||||
|
10) between checks for out-of-thread events when things are
|
||||||
|
otherwise idle. Decreasing this value can improve GUI
|
||||||
|
responsiveness, but at the expense of consuming more CPU
|
||||||
|
cycles.
|
||||||
|
|
||||||
|
# TODO: Replace custom logging functionality with standard
|
||||||
|
# TODO: logging.Logger for easier access and standardization
|
||||||
|
"""
|
||||||
|
self._tk = tk
|
||||||
|
|
||||||
|
# Create the incoming event queue
|
||||||
|
self._event_queue = queue.Queue(1)
|
||||||
|
|
||||||
|
# Identify the thread from which this object is being created
|
||||||
|
# so we can tell later whether an event is coming from another
|
||||||
|
# thread.
|
||||||
|
self._creation_thread = threading.current_thread()
|
||||||
|
|
||||||
|
# Create attributes for kwargs
|
||||||
|
self._debug = mt_debug
|
||||||
|
self._check_period = mt_check_period
|
||||||
|
# Destroying flag to be set by the .destroy() hook
|
||||||
|
self._destroying = False
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
"""
|
||||||
|
Diverts attribute accesses to a wrapper around the underlying tk
|
||||||
|
object.
|
||||||
|
"""
|
||||||
|
return _TkAttr(self, getattr(self._tk, name))
|
||||||
|
|
||||||
|
|
||||||
|
class _TkAttr(object):
|
||||||
|
"""Thread-safe callable attribute wrapper"""
|
||||||
|
|
||||||
|
def __init__(self, tk, attr):
|
||||||
|
self._tk = tk
|
||||||
|
self._attr = attr
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Thread-safe method invocation. Diverts out-of-thread calls
|
||||||
|
through the event queue. Forwards all other method calls to the
|
||||||
|
underlying tk object directly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Check if we're in the creation thread
|
||||||
|
if threading.current_thread() == self._tk._creation_thread:
|
||||||
|
# We're in the creation thread; just call the event directly
|
||||||
|
if self._tk._debug >= 8 or \
|
||||||
|
self._tk._debug >= 3 and self._attr.__name__ == 'call' and \
|
||||||
|
len(args) >= 1 and args[0] == 'after':
|
||||||
|
print('Calling event directly:', self._attr.__name__, args, kwargs)
|
||||||
|
return self._attr(*args, **kwargs)
|
||||||
|
else:
|
||||||
|
if not self._tk._destroying:
|
||||||
|
# We're in a different thread than the creation thread;
|
||||||
|
# enqueue the event, and then wait for the response.
|
||||||
|
response_queue = queue.Queue(1)
|
||||||
|
if self._tk._debug >= 1:
|
||||||
|
print('Marshalling event:', self._attr.__name__, args, kwargs)
|
||||||
|
self._tk._event_queue.put((self._attr, args, kwargs, response_queue), True, 1)
|
||||||
|
is_exception, response = response_queue.get(True, None)
|
||||||
|
|
||||||
|
# Handle the response, whether it's a normal return value or
|
||||||
|
# an exception.
|
||||||
|
if is_exception:
|
||||||
|
ex_type, ex_value, ex_tb = response
|
||||||
|
raise ex_type(ex_value, ex_tb)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def _Tk__init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Hook for Tkinter.Tk.__init__ method
|
||||||
|
:param self: Tk instance
|
||||||
|
:param args, kwargs: Arguments for Tk initializer
|
||||||
|
"""
|
||||||
|
# We support some new keyword arguments that the original __init__ method
|
||||||
|
# doesn't expect, so separate those out before doing anything else.
|
||||||
|
new_kwnames = ('mt_check_period', 'mt_debug')
|
||||||
|
new_kwargs = {
|
||||||
|
kw_name: kwargs.pop(kw_name) for kw_name in new_kwnames
|
||||||
|
if kwargs.get(kw_name, None) is not None
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the original __init__ method, creating the internal tk member.
|
||||||
|
self.__original__init__mtTkinter(*args, **kwargs)
|
||||||
|
|
||||||
|
# Replace the internal tk member with a wrapper that handles calls from
|
||||||
|
# other threads.
|
||||||
|
self.tk = _Tk(self.tk, **new_kwargs)
|
||||||
|
|
||||||
|
# Set up the first event to check for out-of-thread events.
|
||||||
|
self.after_idle(_check_events, self)
|
||||||
|
|
||||||
|
|
||||||
|
# Define a hook for class Tk's destroy method.
|
||||||
|
def _Tk_destroy(self):
|
||||||
|
self.tk._destroying = True
|
||||||
|
self.__original__destroy()
|
||||||
|
|
||||||
|
|
||||||
|
def _check_events(tk):
|
||||||
|
"""Checks events in the queue on a given Tk instance"""
|
||||||
|
|
||||||
|
used = False
|
||||||
|
try:
|
||||||
|
# Process all enqueued events, then exit.
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# Get an event request from the queue.
|
||||||
|
method, args, kwargs, response_queue = tk.tk._event_queue.get_nowait()
|
||||||
|
except queue.Empty:
|
||||||
|
# No more events to process.
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# Call the event with the given arguments, and then return
|
||||||
|
# the result back to the caller via the response queue.
|
||||||
|
used = True
|
||||||
|
if tk.tk._debug >= 2:
|
||||||
|
print('Calling event from main thread:', method.__name__, args, kwargs)
|
||||||
|
try:
|
||||||
|
response_queue.put((False, method(*args, **kwargs)))
|
||||||
|
except SystemExit:
|
||||||
|
raise # Raises original SystemExit
|
||||||
|
except Exception:
|
||||||
|
# Calling the event caused an exception; return the
|
||||||
|
# exception back to the caller so that it can be raised
|
||||||
|
# in the caller's thread.
|
||||||
|
from sys import exc_info # Python 2 requirement
|
||||||
|
ex_type, ex_value, ex_tb = exc_info()
|
||||||
|
response_queue.put((True, (ex_type, ex_value, ex_tb)))
|
||||||
|
finally:
|
||||||
|
# Schedule to check again. If we just processed an event, check
|
||||||
|
# immediately; if we didn't, check later.
|
||||||
|
if used:
|
||||||
|
tk.after_idle(_check_events, tk)
|
||||||
|
else:
|
||||||
|
tk.after(tk.tk._check_period, _check_events, tk)
|
||||||
|
|
||||||
|
|
||||||
|
"""Perform in-memory modification of Tkinter module"""
|
||||||
|
# Replace Tk's original __init__ with the hook.
|
||||||
|
Tk.__original__init__mtTkinter = Tk.__init__
|
||||||
|
Tk.__init__ = _Tk__init__
|
||||||
|
|
||||||
|
# Replace Tk's original destroy with the hook.
|
||||||
|
Tk.__original__destroy = Tk.destroy
|
||||||
|
Tk.destroy = _Tk_destroy
|
|
@ -0,0 +1 @@
|
||||||
|
[{'id': 'obj', 'name': 'boden', 'args': {'anchored': True, 'char': ' ', 'collide': True, 'friction': 0, 'gravity': 0, 'acceleration': {'x': 0, 'y': 0, 'ARGID': 'vector2'}, 'bcolor': {'b': 0, 'g': 0, 'r': 0, 'ARGID': 'color3'}, 'fcolor': {'b': 0, 'g': 0, 'r': 0, 'ARGID': 'color3'}, 'position': {'x': 5, 'y': 5, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': 'obj', 'args': {'anchored': False, 'char': '#', 'collide': True, 'friction': 0, 'gravity': 1, 'acceleration': {'x': 0, 'y': 0, 'ARGID': 'vector2'}, 'bcolor': {'b': 255, 'g': 255, 'r': 255, 'ARGID': 'color3'}, 'fcolor': {'b': 0, 'g': 0, 'r': 0, 'ARGID': 'color3'}, 'position': {'x': 5, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}]
|
|
@ -0,0 +1,310 @@
|
||||||
|
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()
|
||||||
|
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 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 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 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
|
||||||
|
|
||||||
|
def calcphysobj(self, target: obj):
|
||||||
|
if target.anchored == True: return
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
|
||||||
|
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()):
|
||||||
|
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))
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
# Python 2
|
||||||
|
from Tkinter import *
|
||||||
|
import Queue as queue
|
||||||
|
else:
|
||||||
|
# Python 3
|
||||||
|
from tkinter import *
|
||||||
|
import queue
|
||||||
|
|
||||||
|
|
||||||
|
class _Tk(object):
|
||||||
|
"""Wrapper for underlying attribute tk of class Tk"""
|
||||||
|
|
||||||
|
def __init__(self, tk, mt_debug=0, mt_check_period=10):
|
||||||
|
"""
|
||||||
|
:param tk: Tkinter.Tk.tk Tk interpreter object
|
||||||
|
:param mt_debug: Determines amount of debug output.
|
||||||
|
0 = No debug output (default)
|
||||||
|
1 = Minimal debug output
|
||||||
|
...
|
||||||
|
9 = Full debug output
|
||||||
|
:param mt_check_period: Amount of time in milliseconds (default
|
||||||
|
10) between checks for out-of-thread events when things are
|
||||||
|
otherwise idle. Decreasing this value can improve GUI
|
||||||
|
responsiveness, but at the expense of consuming more CPU
|
||||||
|
cycles.
|
||||||
|
|
||||||
|
# TODO: Replace custom logging functionality with standard
|
||||||
|
# TODO: logging.Logger for easier access and standardization
|
||||||
|
"""
|
||||||
|
self._tk = tk
|
||||||
|
|
||||||
|
# Create the incoming event queue
|
||||||
|
self._event_queue = queue.Queue(1)
|
||||||
|
|
||||||
|
# Identify the thread from which this object is being created
|
||||||
|
# so we can tell later whether an event is coming from another
|
||||||
|
# thread.
|
||||||
|
self._creation_thread = threading.current_thread()
|
||||||
|
|
||||||
|
# Create attributes for kwargs
|
||||||
|
self._debug = mt_debug
|
||||||
|
self._check_period = mt_check_period
|
||||||
|
# Destroying flag to be set by the .destroy() hook
|
||||||
|
self._destroying = False
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
"""
|
||||||
|
Diverts attribute accesses to a wrapper around the underlying tk
|
||||||
|
object.
|
||||||
|
"""
|
||||||
|
return _TkAttr(self, getattr(self._tk, name))
|
||||||
|
|
||||||
|
|
||||||
|
class _TkAttr(object):
|
||||||
|
"""Thread-safe callable attribute wrapper"""
|
||||||
|
|
||||||
|
def __init__(self, tk, attr):
|
||||||
|
self._tk = tk
|
||||||
|
self._attr = attr
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Thread-safe method invocation. Diverts out-of-thread calls
|
||||||
|
through the event queue. Forwards all other method calls to the
|
||||||
|
underlying tk object directly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Check if we're in the creation thread
|
||||||
|
if threading.current_thread() == self._tk._creation_thread:
|
||||||
|
# We're in the creation thread; just call the event directly
|
||||||
|
if self._tk._debug >= 8 or \
|
||||||
|
self._tk._debug >= 3 and self._attr.__name__ == 'call' and \
|
||||||
|
len(args) >= 1 and args[0] == 'after':
|
||||||
|
print('Calling event directly:', self._attr.__name__, args, kwargs)
|
||||||
|
return self._attr(*args, **kwargs)
|
||||||
|
else:
|
||||||
|
if not self._tk._destroying:
|
||||||
|
# We're in a different thread than the creation thread;
|
||||||
|
# enqueue the event, and then wait for the response.
|
||||||
|
response_queue = queue.Queue(1)
|
||||||
|
if self._tk._debug >= 1:
|
||||||
|
print('Marshalling event:', self._attr.__name__, args, kwargs)
|
||||||
|
self._tk._event_queue.put((self._attr, args, kwargs, response_queue), True, 1)
|
||||||
|
is_exception, response = response_queue.get(True, None)
|
||||||
|
|
||||||
|
# Handle the response, whether it's a normal return value or
|
||||||
|
# an exception.
|
||||||
|
if is_exception:
|
||||||
|
ex_type, ex_value, ex_tb = response
|
||||||
|
raise ex_type(ex_value, ex_tb)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def _Tk__init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Hook for Tkinter.Tk.__init__ method
|
||||||
|
:param self: Tk instance
|
||||||
|
:param args, kwargs: Arguments for Tk initializer
|
||||||
|
"""
|
||||||
|
# We support some new keyword arguments that the original __init__ method
|
||||||
|
# doesn't expect, so separate those out before doing anything else.
|
||||||
|
new_kwnames = ('mt_check_period', 'mt_debug')
|
||||||
|
new_kwargs = {
|
||||||
|
kw_name: kwargs.pop(kw_name) for kw_name in new_kwnames
|
||||||
|
if kwargs.get(kw_name, None) is not None
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the original __init__ method, creating the internal tk member.
|
||||||
|
self.__original__init__mtTkinter(*args, **kwargs)
|
||||||
|
|
||||||
|
# Replace the internal tk member with a wrapper that handles calls from
|
||||||
|
# other threads.
|
||||||
|
self.tk = _Tk(self.tk, **new_kwargs)
|
||||||
|
|
||||||
|
# Set up the first event to check for out-of-thread events.
|
||||||
|
self.after_idle(_check_events, self)
|
||||||
|
|
||||||
|
|
||||||
|
# Define a hook for class Tk's destroy method.
|
||||||
|
def _Tk_destroy(self):
|
||||||
|
self.tk._destroying = True
|
||||||
|
self.__original__destroy()
|
||||||
|
|
||||||
|
|
||||||
|
def _check_events(tk):
|
||||||
|
"""Checks events in the queue on a given Tk instance"""
|
||||||
|
|
||||||
|
used = False
|
||||||
|
try:
|
||||||
|
# Process all enqueued events, then exit.
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# Get an event request from the queue.
|
||||||
|
method, args, kwargs, response_queue = tk.tk._event_queue.get_nowait()
|
||||||
|
except queue.Empty:
|
||||||
|
# No more events to process.
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# Call the event with the given arguments, and then return
|
||||||
|
# the result back to the caller via the response queue.
|
||||||
|
used = True
|
||||||
|
if tk.tk._debug >= 2:
|
||||||
|
print('Calling event from main thread:', method.__name__, args, kwargs)
|
||||||
|
try:
|
||||||
|
response_queue.put((False, method(*args, **kwargs)))
|
||||||
|
except SystemExit:
|
||||||
|
raise # Raises original SystemExit
|
||||||
|
except Exception:
|
||||||
|
# Calling the event caused an exception; return the
|
||||||
|
# exception back to the caller so that it can be raised
|
||||||
|
# in the caller's thread.
|
||||||
|
from sys import exc_info # Python 2 requirement
|
||||||
|
ex_type, ex_value, ex_tb = exc_info()
|
||||||
|
response_queue.put((True, (ex_type, ex_value, ex_tb)))
|
||||||
|
finally:
|
||||||
|
# Schedule to check again. If we just processed an event, check
|
||||||
|
# immediately; if we didn't, check later.
|
||||||
|
if used:
|
||||||
|
tk.after_idle(_check_events, tk)
|
||||||
|
else:
|
||||||
|
tk.after(tk.tk._check_period, _check_events, tk)
|
||||||
|
|
||||||
|
|
||||||
|
"""Perform in-memory modification of Tkinter module"""
|
||||||
|
# Replace Tk's original __init__ with the hook.
|
||||||
|
Tk.__original__init__mtTkinter = Tk.__init__
|
||||||
|
Tk.__init__ = _Tk__init__
|
||||||
|
|
||||||
|
# Replace Tk's original destroy with the hook.
|
||||||
|
Tk.__original__destroy = Tk.destroy
|
||||||
|
Tk.destroy = _Tk_destroy
|
|
@ -5,6 +5,9 @@ import string
|
||||||
import threading
|
import threading
|
||||||
import mtTkinter as tk
|
import mtTkinter as tk
|
||||||
import time
|
import time
|
||||||
|
import simpleaudio as sa
|
||||||
|
import os
|
||||||
|
import base64
|
||||||
|
|
||||||
global gamedata
|
global gamedata
|
||||||
gamedata = {}
|
gamedata = {}
|
||||||
|
@ -69,7 +72,17 @@ def add(objtype):
|
||||||
game.addobj(obj)
|
game.addobj(obj)
|
||||||
gamedata[id]["args"]["ID"] = obj.ID
|
gamedata[id]["args"]["ID"] = obj.ID
|
||||||
return id
|
return id
|
||||||
|
|
||||||
|
def importsound(target):
|
||||||
|
oid = add("rawsound")
|
||||||
|
gamedata[oid]["name"] = target["name"]
|
||||||
|
gamedata[oid]["args"]["sdata"] = base64.b64decode(target["args"]["sdata"])
|
||||||
|
gamedata[oid]["args"]["spath"] = target["args"]["spath"]
|
||||||
|
|
||||||
def importobj(target):
|
def importobj(target):
|
||||||
|
if target["id"] == "sound" or target["id"] == "rawsound":
|
||||||
|
importsound(target)
|
||||||
|
return
|
||||||
oid = add(target["id"])
|
oid = add(target["id"])
|
||||||
id = gamedata[oid]
|
id = gamedata[oid]
|
||||||
id["name"] = target["name"]
|
id["name"] = target["name"]
|
||||||
|
@ -106,11 +119,31 @@ def log(text, end="\n", flush=False):
|
||||||
def NULL():
|
def NULL():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class gsound:
|
||||||
|
def __init__(self, data, game):
|
||||||
|
self._playing = False
|
||||||
|
self._data = data
|
||||||
|
game.currentsounds.append(self)
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
if self._playing == True: return
|
||||||
|
self._sound = sa.play_buffer(self._data, 2, 2, 44100)
|
||||||
|
self._playing = True
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.stop()
|
||||||
|
self._playing = False
|
||||||
|
|
||||||
|
def wait(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.wait_done()
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
print("preparing log file...")
|
print("preparing log file...")
|
||||||
global logfile
|
global logfile
|
||||||
global win
|
global maingame
|
||||||
global game
|
global window
|
||||||
temp = time.gmtime(time.time())
|
temp = time.gmtime(time.time())
|
||||||
logfile = ""
|
logfile = ""
|
||||||
for i in temp:
|
for i in temp:
|
||||||
|
@ -120,8 +153,18 @@ def run():
|
||||||
log("Preparing API...")
|
log("Preparing API...")
|
||||||
API = {"print": log, "HASHBASE": hashengine}
|
API = {"print": log, "HASHBASE": hashengine}
|
||||||
log("Done!")
|
log("Done!")
|
||||||
API["HASHGAME"] = game
|
window = tk.Tk()
|
||||||
|
window.protocol("WM_DELETE_WINDOW", NULL)
|
||||||
|
maingame = game
|
||||||
|
API["HASHGAME"] = maingame
|
||||||
|
API["SOUND"] = lambda data: gsound(data, maingame)
|
||||||
log("main game initalised!")
|
log("main game initalised!")
|
||||||
|
log("copying sounds...")
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
if i["id"] != "sound" and i["id"] != "rawsound": continue
|
||||||
|
maingame.sounds[i["args"]["spath"]] = i["args"]["sdata"]
|
||||||
|
print(i["args"]["spath"])
|
||||||
scripts = []
|
scripts = []
|
||||||
for i in gamedata:
|
for i in gamedata:
|
||||||
i = gamedata[i]
|
i = gamedata[i]
|
||||||
|
@ -131,7 +174,8 @@ def run():
|
||||||
obj.code = i
|
obj.code = i
|
||||||
scripts.append(obj)
|
scripts.append(obj)
|
||||||
for i in scripts:
|
for i in scripts:
|
||||||
game.startscript(lambda: i.execute(API))
|
maingame.startscript(lambda: i.execute(API))
|
||||||
|
log("objects transferred!")
|
||||||
gamescript = """
|
gamescript = """
|
||||||
global HASHGAME
|
global HASHGAME
|
||||||
import time
|
import time
|
||||||
|
@ -143,7 +187,7 @@ while True:
|
||||||
"""
|
"""
|
||||||
gameloopsc = script()
|
gameloopsc = script()
|
||||||
gameloopsc.code = gamescript
|
gameloopsc.code = gamescript
|
||||||
game.startscript(lambda: gameloopsc.execute(API))
|
maingame.startscript(lambda: gameloopsc.execute(API))
|
||||||
log("game test started!!!")
|
log("game test started!!!")
|
||||||
log("---------------------")
|
log("---------------------")
|
||||||
|
|
||||||
|
@ -152,6 +196,19 @@ def wait():
|
||||||
load("game.HEGF")
|
load("game.HEGF")
|
||||||
run()
|
run()
|
||||||
|
|
||||||
|
def apath(old, ext):
|
||||||
|
return "/"
|
||||||
|
|
||||||
|
class rsound:
|
||||||
|
def __init__(self):
|
||||||
|
self.spath = ""
|
||||||
|
self.sdata = b""
|
||||||
|
|
||||||
|
class sound():
|
||||||
|
def __init__(self, new):
|
||||||
|
self.spath = os.path.basename(new).split(".")[0]
|
||||||
|
self.sdata = hashengine.loadsound(new)
|
||||||
|
|
||||||
global types
|
global types
|
||||||
global ignoreat
|
global ignoreat
|
||||||
global valtypes
|
global valtypes
|
||||||
|
@ -160,10 +217,10 @@ global attypes
|
||||||
global crucial
|
global crucial
|
||||||
global game
|
global game
|
||||||
win = tk.Tk()
|
win = tk.Tk()
|
||||||
game = hashengine.game(renderer=lambda size, cam: rend(size, cam, win, [0, 0]))
|
game = hashengine.game(renderer=lambda size, cam: rend(size, cam, win, [0, 0]), sounddir="/")
|
||||||
crucial = ["obj",]
|
crucial = ["obj",]
|
||||||
types = hashengine.enum({"obj": hashengine.obj, "script": script})
|
types = hashengine.enum({"obj": hashengine.obj, "script": script, "rawsound": rsound, "sound": lambda: sound(apath("", [("Wave files", ".wave .wav")]))})
|
||||||
ignoreat = ["ID", "execute"]
|
ignoreat = ["ID", "execute", "sdata"]
|
||||||
"""self.position = vector2()
|
"""self.position = vector2()
|
||||||
self.char = " "
|
self.char = " "
|
||||||
self.ID = 0
|
self.ID = 0
|
File diff suppressed because one or more lines are too long
|
@ -3,6 +3,8 @@ import string
|
||||||
import random
|
import random
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import wave
|
||||||
|
import os
|
||||||
|
|
||||||
class stdrend:
|
class stdrend:
|
||||||
def __init__(self, size, cam):
|
def __init__(self, size, cam):
|
||||||
|
@ -122,6 +124,11 @@ class enum:
|
||||||
def getposssel(self):
|
def getposssel(self):
|
||||||
return list(self._sel.keys())
|
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})
|
cammode = enum({"editable": 0, "follow": 1})
|
||||||
|
|
||||||
class event:
|
class event:
|
||||||
|
@ -168,8 +175,14 @@ class camera(obj):
|
||||||
self.position = self.subject.position
|
self.position = self.subject.position
|
||||||
|
|
||||||
class game:
|
class game:
|
||||||
def __init__(self, size=[10, 10], renderer=stdrend):
|
def __init__(self, size=[10, 10], renderer=stdrend, sounddir=""):
|
||||||
if renderer == None: raise TypeError("Renderer class needed!")
|
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._size = size
|
||||||
self._objects = {}
|
self._objects = {}
|
||||||
self.camera = camera()
|
self.camera = camera()
|
||||||
|
@ -261,8 +274,12 @@ class game:
|
||||||
for i in self._threads:
|
for i in self._threads:
|
||||||
i.join(.0)
|
i.join(.0)
|
||||||
|
|
||||||
|
def stopsounds(self):
|
||||||
|
for i in self.currentsounds:
|
||||||
|
i.stop()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
testgame = game()
|
testgame = game(sounddir="testsound")
|
||||||
object = obj()
|
object = obj()
|
||||||
object.char = "#"
|
object.char = "#"
|
||||||
object.anchored = False
|
object.anchored = False
|
|
@ -0,0 +1,175 @@
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
# Python 2
|
||||||
|
from Tkinter import *
|
||||||
|
import Queue as queue
|
||||||
|
else:
|
||||||
|
# Python 3
|
||||||
|
from tkinter import *
|
||||||
|
import queue
|
||||||
|
|
||||||
|
|
||||||
|
class _Tk(object):
|
||||||
|
"""Wrapper for underlying attribute tk of class Tk"""
|
||||||
|
|
||||||
|
def __init__(self, tk, mt_debug=0, mt_check_period=10):
|
||||||
|
"""
|
||||||
|
:param tk: Tkinter.Tk.tk Tk interpreter object
|
||||||
|
:param mt_debug: Determines amount of debug output.
|
||||||
|
0 = No debug output (default)
|
||||||
|
1 = Minimal debug output
|
||||||
|
...
|
||||||
|
9 = Full debug output
|
||||||
|
:param mt_check_period: Amount of time in milliseconds (default
|
||||||
|
10) between checks for out-of-thread events when things are
|
||||||
|
otherwise idle. Decreasing this value can improve GUI
|
||||||
|
responsiveness, but at the expense of consuming more CPU
|
||||||
|
cycles.
|
||||||
|
|
||||||
|
# TODO: Replace custom logging functionality with standard
|
||||||
|
# TODO: logging.Logger for easier access and standardization
|
||||||
|
"""
|
||||||
|
self._tk = tk
|
||||||
|
|
||||||
|
# Create the incoming event queue
|
||||||
|
self._event_queue = queue.Queue(1)
|
||||||
|
|
||||||
|
# Identify the thread from which this object is being created
|
||||||
|
# so we can tell later whether an event is coming from another
|
||||||
|
# thread.
|
||||||
|
self._creation_thread = threading.current_thread()
|
||||||
|
|
||||||
|
# Create attributes for kwargs
|
||||||
|
self._debug = mt_debug
|
||||||
|
self._check_period = mt_check_period
|
||||||
|
# Destroying flag to be set by the .destroy() hook
|
||||||
|
self._destroying = False
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
"""
|
||||||
|
Diverts attribute accesses to a wrapper around the underlying tk
|
||||||
|
object.
|
||||||
|
"""
|
||||||
|
return _TkAttr(self, getattr(self._tk, name))
|
||||||
|
|
||||||
|
|
||||||
|
class _TkAttr(object):
|
||||||
|
"""Thread-safe callable attribute wrapper"""
|
||||||
|
|
||||||
|
def __init__(self, tk, attr):
|
||||||
|
self._tk = tk
|
||||||
|
self._attr = attr
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Thread-safe method invocation. Diverts out-of-thread calls
|
||||||
|
through the event queue. Forwards all other method calls to the
|
||||||
|
underlying tk object directly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Check if we're in the creation thread
|
||||||
|
if threading.current_thread() == self._tk._creation_thread:
|
||||||
|
# We're in the creation thread; just call the event directly
|
||||||
|
if self._tk._debug >= 8 or \
|
||||||
|
self._tk._debug >= 3 and self._attr.__name__ == 'call' and \
|
||||||
|
len(args) >= 1 and args[0] == 'after':
|
||||||
|
print('Calling event directly:', self._attr.__name__, args, kwargs)
|
||||||
|
return self._attr(*args, **kwargs)
|
||||||
|
else:
|
||||||
|
if not self._tk._destroying:
|
||||||
|
# We're in a different thread than the creation thread;
|
||||||
|
# enqueue the event, and then wait for the response.
|
||||||
|
response_queue = queue.Queue(1)
|
||||||
|
if self._tk._debug >= 1:
|
||||||
|
print('Marshalling event:', self._attr.__name__, args, kwargs)
|
||||||
|
self._tk._event_queue.put((self._attr, args, kwargs, response_queue), True, 1)
|
||||||
|
is_exception, response = response_queue.get(True, None)
|
||||||
|
|
||||||
|
# Handle the response, whether it's a normal return value or
|
||||||
|
# an exception.
|
||||||
|
if is_exception:
|
||||||
|
ex_type, ex_value, ex_tb = response
|
||||||
|
raise ex_type(ex_value, ex_tb)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def _Tk__init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Hook for Tkinter.Tk.__init__ method
|
||||||
|
:param self: Tk instance
|
||||||
|
:param args, kwargs: Arguments for Tk initializer
|
||||||
|
"""
|
||||||
|
# We support some new keyword arguments that the original __init__ method
|
||||||
|
# doesn't expect, so separate those out before doing anything else.
|
||||||
|
new_kwnames = ('mt_check_period', 'mt_debug')
|
||||||
|
new_kwargs = {
|
||||||
|
kw_name: kwargs.pop(kw_name) for kw_name in new_kwnames
|
||||||
|
if kwargs.get(kw_name, None) is not None
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the original __init__ method, creating the internal tk member.
|
||||||
|
self.__original__init__mtTkinter(*args, **kwargs)
|
||||||
|
|
||||||
|
# Replace the internal tk member with a wrapper that handles calls from
|
||||||
|
# other threads.
|
||||||
|
self.tk = _Tk(self.tk, **new_kwargs)
|
||||||
|
|
||||||
|
# Set up the first event to check for out-of-thread events.
|
||||||
|
self.after_idle(_check_events, self)
|
||||||
|
|
||||||
|
|
||||||
|
# Define a hook for class Tk's destroy method.
|
||||||
|
def _Tk_destroy(self):
|
||||||
|
self.tk._destroying = True
|
||||||
|
self.__original__destroy()
|
||||||
|
|
||||||
|
|
||||||
|
def _check_events(tk):
|
||||||
|
"""Checks events in the queue on a given Tk instance"""
|
||||||
|
|
||||||
|
used = False
|
||||||
|
try:
|
||||||
|
# Process all enqueued events, then exit.
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# Get an event request from the queue.
|
||||||
|
method, args, kwargs, response_queue = tk.tk._event_queue.get_nowait()
|
||||||
|
except queue.Empty:
|
||||||
|
# No more events to process.
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# Call the event with the given arguments, and then return
|
||||||
|
# the result back to the caller via the response queue.
|
||||||
|
used = True
|
||||||
|
if tk.tk._debug >= 2:
|
||||||
|
print('Calling event from main thread:', method.__name__, args, kwargs)
|
||||||
|
try:
|
||||||
|
response_queue.put((False, method(*args, **kwargs)))
|
||||||
|
except SystemExit:
|
||||||
|
raise # Raises original SystemExit
|
||||||
|
except Exception:
|
||||||
|
# Calling the event caused an exception; return the
|
||||||
|
# exception back to the caller so that it can be raised
|
||||||
|
# in the caller's thread.
|
||||||
|
from sys import exc_info # Python 2 requirement
|
||||||
|
ex_type, ex_value, ex_tb = exc_info()
|
||||||
|
response_queue.put((True, (ex_type, ex_value, ex_tb)))
|
||||||
|
finally:
|
||||||
|
# Schedule to check again. If we just processed an event, check
|
||||||
|
# immediately; if we didn't, check later.
|
||||||
|
if used:
|
||||||
|
tk.after_idle(_check_events, tk)
|
||||||
|
else:
|
||||||
|
tk.after(tk.tk._check_period, _check_events, tk)
|
||||||
|
|
||||||
|
|
||||||
|
"""Perform in-memory modification of Tkinter module"""
|
||||||
|
# Replace Tk's original __init__ with the hook.
|
||||||
|
Tk.__original__init__mtTkinter = Tk.__init__
|
||||||
|
Tk.__init__ = _Tk__init__
|
||||||
|
|
||||||
|
# Replace Tk's original destroy with the hook.
|
||||||
|
Tk.__original__destroy = Tk.destroy
|
||||||
|
Tk.destroy = _Tk_destroy
|
|
@ -5,6 +5,9 @@ import string
|
||||||
import threading
|
import threading
|
||||||
import mtTkinter as tk
|
import mtTkinter as tk
|
||||||
import time
|
import time
|
||||||
|
import simpleaudio as sa
|
||||||
|
import os
|
||||||
|
import base64
|
||||||
|
|
||||||
global gamedata
|
global gamedata
|
||||||
gamedata = {}
|
gamedata = {}
|
||||||
|
@ -69,7 +72,17 @@ def add(objtype):
|
||||||
game.addobj(obj)
|
game.addobj(obj)
|
||||||
gamedata[id]["args"]["ID"] = obj.ID
|
gamedata[id]["args"]["ID"] = obj.ID
|
||||||
return id
|
return id
|
||||||
|
|
||||||
|
def importsound(target):
|
||||||
|
oid = add("rawsound")
|
||||||
|
gamedata[oid]["name"] = target["name"]
|
||||||
|
gamedata[oid]["args"]["sdata"] = base64.b64decode(target["args"]["sdata"])
|
||||||
|
gamedata[oid]["args"]["spath"] = target["args"]["spath"]
|
||||||
|
|
||||||
def importobj(target):
|
def importobj(target):
|
||||||
|
if target["id"] == "sound" or target["id"] == "rawsound":
|
||||||
|
importsound(target)
|
||||||
|
return
|
||||||
oid = add(target["id"])
|
oid = add(target["id"])
|
||||||
id = gamedata[oid]
|
id = gamedata[oid]
|
||||||
id["name"] = target["name"]
|
id["name"] = target["name"]
|
||||||
|
@ -106,11 +119,31 @@ def log(text, end="\n", flush=False):
|
||||||
def NULL():
|
def NULL():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class gsound:
|
||||||
|
def __init__(self, data, game):
|
||||||
|
self._playing = False
|
||||||
|
self._data = data
|
||||||
|
game.currentsounds.append(self)
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
if self._playing == True: return
|
||||||
|
self._sound = sa.play_buffer(self._data, 2, 2, 44100)
|
||||||
|
self._playing = True
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.stop()
|
||||||
|
self._playing = False
|
||||||
|
|
||||||
|
def wait(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.wait_done()
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
print("preparing log file...")
|
print("preparing log file...")
|
||||||
global logfile
|
global logfile
|
||||||
global win
|
global maingame
|
||||||
global game
|
global window
|
||||||
temp = time.gmtime(time.time())
|
temp = time.gmtime(time.time())
|
||||||
logfile = ""
|
logfile = ""
|
||||||
for i in temp:
|
for i in temp:
|
||||||
|
@ -120,8 +153,18 @@ def run():
|
||||||
log("Preparing API...")
|
log("Preparing API...")
|
||||||
API = {"print": log, "HASHBASE": hashengine}
|
API = {"print": log, "HASHBASE": hashengine}
|
||||||
log("Done!")
|
log("Done!")
|
||||||
API["HASHGAME"] = game
|
window = tk.Tk()
|
||||||
|
window.protocol("WM_DELETE_WINDOW", NULL)
|
||||||
|
maingame = game
|
||||||
|
API["HASHGAME"] = maingame
|
||||||
|
API["SOUND"] = lambda data: gsound(data, maingame)
|
||||||
log("main game initalised!")
|
log("main game initalised!")
|
||||||
|
log("copying sounds...")
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
if i["id"] != "sound" and i["id"] != "rawsound": continue
|
||||||
|
maingame.sounds[i["args"]["spath"]] = i["args"]["sdata"]
|
||||||
|
print(i["args"]["spath"])
|
||||||
scripts = []
|
scripts = []
|
||||||
for i in gamedata:
|
for i in gamedata:
|
||||||
i = gamedata[i]
|
i = gamedata[i]
|
||||||
|
@ -131,7 +174,8 @@ def run():
|
||||||
obj.code = i
|
obj.code = i
|
||||||
scripts.append(obj)
|
scripts.append(obj)
|
||||||
for i in scripts:
|
for i in scripts:
|
||||||
game.startscript(lambda: i.execute(API))
|
maingame.startscript(lambda: i.execute(API))
|
||||||
|
log("objects transferred!")
|
||||||
gamescript = """
|
gamescript = """
|
||||||
global HASHGAME
|
global HASHGAME
|
||||||
import time
|
import time
|
||||||
|
@ -143,7 +187,7 @@ while True:
|
||||||
"""
|
"""
|
||||||
gameloopsc = script()
|
gameloopsc = script()
|
||||||
gameloopsc.code = gamescript
|
gameloopsc.code = gamescript
|
||||||
game.startscript(lambda: gameloopsc.execute(API))
|
maingame.startscript(lambda: gameloopsc.execute(API))
|
||||||
log("game test started!!!")
|
log("game test started!!!")
|
||||||
log("---------------------")
|
log("---------------------")
|
||||||
|
|
||||||
|
@ -152,6 +196,19 @@ def wait():
|
||||||
load("game.HEGF")
|
load("game.HEGF")
|
||||||
run()
|
run()
|
||||||
|
|
||||||
|
def apath(old, ext):
|
||||||
|
return "/"
|
||||||
|
|
||||||
|
class rsound:
|
||||||
|
def __init__(self):
|
||||||
|
self.spath = ""
|
||||||
|
self.sdata = b""
|
||||||
|
|
||||||
|
class sound():
|
||||||
|
def __init__(self, new):
|
||||||
|
self.spath = os.path.basename(new).split(".")[0]
|
||||||
|
self.sdata = hashengine.loadsound(new)
|
||||||
|
|
||||||
global types
|
global types
|
||||||
global ignoreat
|
global ignoreat
|
||||||
global valtypes
|
global valtypes
|
||||||
|
@ -160,10 +217,10 @@ global attypes
|
||||||
global crucial
|
global crucial
|
||||||
global game
|
global game
|
||||||
win = tk.Tk()
|
win = tk.Tk()
|
||||||
game = hashengine.game(renderer=lambda size, cam: rend(size, cam, win, [0, 0]))
|
game = hashengine.game(renderer=lambda size, cam: rend(size, cam, win, [0, 0]), sounddir="/")
|
||||||
crucial = ["obj",]
|
crucial = ["obj",]
|
||||||
types = hashengine.enum({"obj": hashengine.obj, "script": script})
|
types = hashengine.enum({"obj": hashengine.obj, "script": script, "rawsound": rsound, "sound": lambda: sound(apath("", [("Wave files", ".wave .wav")]))})
|
||||||
ignoreat = ["ID", "execute"]
|
ignoreat = ["ID", "execute", "sdata"]
|
||||||
"""self.position = vector2()
|
"""self.position = vector2()
|
||||||
self.char = " "
|
self.char = " "
|
||||||
self.ID = 0
|
self.ID = 0
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,336 @@
|
||||||
|
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("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", 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 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
|
||||||
|
|
||||||
|
def calcphysobj(self, target: obj):
|
||||||
|
if target.anchored == True: return
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
|
||||||
|
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()):
|
||||||
|
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))
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
Log file start!
|
||||||
|
Preparing API...
|
||||||
|
Done!
|
||||||
|
main game initalised!
|
||||||
|
copying sounds...
|
||||||
|
objects transferred!
|
||||||
|
game test started!!!
|
||||||
|
---------------------
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
import player
|
||||||
|
import ast
|
||||||
|
file = open("game.HEGF", 'r')
|
||||||
|
file = file.read()
|
||||||
|
file = ast.literal_eval(file)
|
||||||
|
player.execgame(file)
|
|
@ -0,0 +1,175 @@
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
# Python 2
|
||||||
|
from Tkinter import *
|
||||||
|
import Queue as queue
|
||||||
|
else:
|
||||||
|
# Python 3
|
||||||
|
from tkinter import *
|
||||||
|
import queue
|
||||||
|
|
||||||
|
|
||||||
|
class _Tk(object):
|
||||||
|
"""Wrapper for underlying attribute tk of class Tk"""
|
||||||
|
|
||||||
|
def __init__(self, tk, mt_debug=0, mt_check_period=10):
|
||||||
|
"""
|
||||||
|
:param tk: Tkinter.Tk.tk Tk interpreter object
|
||||||
|
:param mt_debug: Determines amount of debug output.
|
||||||
|
0 = No debug output (default)
|
||||||
|
1 = Minimal debug output
|
||||||
|
...
|
||||||
|
9 = Full debug output
|
||||||
|
:param mt_check_period: Amount of time in milliseconds (default
|
||||||
|
10) between checks for out-of-thread events when things are
|
||||||
|
otherwise idle. Decreasing this value can improve GUI
|
||||||
|
responsiveness, but at the expense of consuming more CPU
|
||||||
|
cycles.
|
||||||
|
|
||||||
|
# TODO: Replace custom logging functionality with standard
|
||||||
|
# TODO: logging.Logger for easier access and standardization
|
||||||
|
"""
|
||||||
|
self._tk = tk
|
||||||
|
|
||||||
|
# Create the incoming event queue
|
||||||
|
self._event_queue = queue.Queue(1)
|
||||||
|
|
||||||
|
# Identify the thread from which this object is being created
|
||||||
|
# so we can tell later whether an event is coming from another
|
||||||
|
# thread.
|
||||||
|
self._creation_thread = threading.current_thread()
|
||||||
|
|
||||||
|
# Create attributes for kwargs
|
||||||
|
self._debug = mt_debug
|
||||||
|
self._check_period = mt_check_period
|
||||||
|
# Destroying flag to be set by the .destroy() hook
|
||||||
|
self._destroying = False
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
"""
|
||||||
|
Diverts attribute accesses to a wrapper around the underlying tk
|
||||||
|
object.
|
||||||
|
"""
|
||||||
|
return _TkAttr(self, getattr(self._tk, name))
|
||||||
|
|
||||||
|
|
||||||
|
class _TkAttr(object):
|
||||||
|
"""Thread-safe callable attribute wrapper"""
|
||||||
|
|
||||||
|
def __init__(self, tk, attr):
|
||||||
|
self._tk = tk
|
||||||
|
self._attr = attr
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Thread-safe method invocation. Diverts out-of-thread calls
|
||||||
|
through the event queue. Forwards all other method calls to the
|
||||||
|
underlying tk object directly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Check if we're in the creation thread
|
||||||
|
if threading.current_thread() == self._tk._creation_thread:
|
||||||
|
# We're in the creation thread; just call the event directly
|
||||||
|
if self._tk._debug >= 8 or \
|
||||||
|
self._tk._debug >= 3 and self._attr.__name__ == 'call' and \
|
||||||
|
len(args) >= 1 and args[0] == 'after':
|
||||||
|
print('Calling event directly:', self._attr.__name__, args, kwargs)
|
||||||
|
return self._attr(*args, **kwargs)
|
||||||
|
else:
|
||||||
|
if not self._tk._destroying:
|
||||||
|
# We're in a different thread than the creation thread;
|
||||||
|
# enqueue the event, and then wait for the response.
|
||||||
|
response_queue = queue.Queue(1)
|
||||||
|
if self._tk._debug >= 1:
|
||||||
|
print('Marshalling event:', self._attr.__name__, args, kwargs)
|
||||||
|
self._tk._event_queue.put((self._attr, args, kwargs, response_queue), True, 1)
|
||||||
|
is_exception, response = response_queue.get(True, None)
|
||||||
|
|
||||||
|
# Handle the response, whether it's a normal return value or
|
||||||
|
# an exception.
|
||||||
|
if is_exception:
|
||||||
|
ex_type, ex_value, ex_tb = response
|
||||||
|
raise ex_type(ex_value, ex_tb)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def _Tk__init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Hook for Tkinter.Tk.__init__ method
|
||||||
|
:param self: Tk instance
|
||||||
|
:param args, kwargs: Arguments for Tk initializer
|
||||||
|
"""
|
||||||
|
# We support some new keyword arguments that the original __init__ method
|
||||||
|
# doesn't expect, so separate those out before doing anything else.
|
||||||
|
new_kwnames = ('mt_check_period', 'mt_debug')
|
||||||
|
new_kwargs = {
|
||||||
|
kw_name: kwargs.pop(kw_name) for kw_name in new_kwnames
|
||||||
|
if kwargs.get(kw_name, None) is not None
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the original __init__ method, creating the internal tk member.
|
||||||
|
self.__original__init__mtTkinter(*args, **kwargs)
|
||||||
|
|
||||||
|
# Replace the internal tk member with a wrapper that handles calls from
|
||||||
|
# other threads.
|
||||||
|
self.tk = _Tk(self.tk, **new_kwargs)
|
||||||
|
|
||||||
|
# Set up the first event to check for out-of-thread events.
|
||||||
|
self.after_idle(_check_events, self)
|
||||||
|
|
||||||
|
|
||||||
|
# Define a hook for class Tk's destroy method.
|
||||||
|
def _Tk_destroy(self):
|
||||||
|
self.tk._destroying = True
|
||||||
|
self.__original__destroy()
|
||||||
|
|
||||||
|
|
||||||
|
def _check_events(tk):
|
||||||
|
"""Checks events in the queue on a given Tk instance"""
|
||||||
|
|
||||||
|
used = False
|
||||||
|
try:
|
||||||
|
# Process all enqueued events, then exit.
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# Get an event request from the queue.
|
||||||
|
method, args, kwargs, response_queue = tk.tk._event_queue.get_nowait()
|
||||||
|
except queue.Empty:
|
||||||
|
# No more events to process.
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# Call the event with the given arguments, and then return
|
||||||
|
# the result back to the caller via the response queue.
|
||||||
|
used = True
|
||||||
|
if tk.tk._debug >= 2:
|
||||||
|
print('Calling event from main thread:', method.__name__, args, kwargs)
|
||||||
|
try:
|
||||||
|
response_queue.put((False, method(*args, **kwargs)))
|
||||||
|
except SystemExit:
|
||||||
|
raise # Raises original SystemExit
|
||||||
|
except Exception:
|
||||||
|
# Calling the event caused an exception; return the
|
||||||
|
# exception back to the caller so that it can be raised
|
||||||
|
# in the caller's thread.
|
||||||
|
from sys import exc_info # Python 2 requirement
|
||||||
|
ex_type, ex_value, ex_tb = exc_info()
|
||||||
|
response_queue.put((True, (ex_type, ex_value, ex_tb)))
|
||||||
|
finally:
|
||||||
|
# Schedule to check again. If we just processed an event, check
|
||||||
|
# immediately; if we didn't, check later.
|
||||||
|
if used:
|
||||||
|
tk.after_idle(_check_events, tk)
|
||||||
|
else:
|
||||||
|
tk.after(tk.tk._check_period, _check_events, tk)
|
||||||
|
|
||||||
|
|
||||||
|
"""Perform in-memory modification of Tkinter module"""
|
||||||
|
# Replace Tk's original __init__ with the hook.
|
||||||
|
Tk.__original__init__mtTkinter = Tk.__init__
|
||||||
|
Tk.__init__ = _Tk__init__
|
||||||
|
|
||||||
|
# Replace Tk's original destroy with the hook.
|
||||||
|
Tk.__original__destroy = Tk.destroy
|
||||||
|
Tk.destroy = _Tk_destroy
|
|
@ -0,0 +1,725 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.dont_write_bytecode = True
|
||||||
|
import mtTkinter as tk
|
||||||
|
from tkinter import ttk as tkk
|
||||||
|
from tkinter import messagebox
|
||||||
|
from tkinter import filedialog
|
||||||
|
import copy
|
||||||
|
import hashengine
|
||||||
|
global LH
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import PCPL
|
||||||
|
import langsys
|
||||||
|
PCPL.interpreter.ENG = hashengine
|
||||||
|
LH = langsys.langhandler()
|
||||||
|
lang = open("clang", 'r')
|
||||||
|
lang = lang.read()
|
||||||
|
LH.setlang(lang)
|
||||||
|
# LH.string("")
|
||||||
|
else:
|
||||||
|
class rLH:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
def string(self, target):
|
||||||
|
return target
|
||||||
|
LH = rLH()
|
||||||
|
import ast
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import easygui
|
||||||
|
import base64
|
||||||
|
import simpleaudio as sa
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
global gamedata
|
||||||
|
global cooldown
|
||||||
|
cooldown = False
|
||||||
|
gamedata = {}
|
||||||
|
|
||||||
|
def prepgamedata():
|
||||||
|
out = []
|
||||||
|
tempwin = tk.Tk()
|
||||||
|
bar = tkk.Progressbar(tempwin)
|
||||||
|
bar.place(width=200)
|
||||||
|
ptext = tk.Label(tempwin, text="NONE")
|
||||||
|
ptext.place()
|
||||||
|
count = 1
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
ptext.config(text=i["name"])
|
||||||
|
bar.step(count/len(gamedata))
|
||||||
|
count += 1
|
||||||
|
tempwin.update()
|
||||||
|
temp = {"id": i["id"], "name": i["name"]}
|
||||||
|
tempargs = {}
|
||||||
|
tosearch = {}
|
||||||
|
for arg in i["args"]:
|
||||||
|
if not arg in extypes and not arg in ignoreat and arg != "sdata":
|
||||||
|
tosearch[arg] = i["args"][arg]
|
||||||
|
continue
|
||||||
|
if arg in ignoreat and arg != "sdata": continue
|
||||||
|
if arg != "sdata":
|
||||||
|
tempargs[arg] = i["args"][arg]
|
||||||
|
else:
|
||||||
|
tempargs[arg] = str(base64.b64encode(i["args"][arg]), "ascii", "ignore")
|
||||||
|
for argname in tosearch:
|
||||||
|
arg = tosearch[argname]
|
||||||
|
temp2 = getattributes(arg)
|
||||||
|
temp2.update({"ARGID": arg._type})
|
||||||
|
tempargs[argname] = temp2
|
||||||
|
temp["args"] = tempargs
|
||||||
|
out.append(temp)
|
||||||
|
tempwin.destroy()
|
||||||
|
return out
|
||||||
|
|
||||||
|
class script:
|
||||||
|
def __init__(self):
|
||||||
|
self.code = ""
|
||||||
|
|
||||||
|
def execute(self, API):
|
||||||
|
#old code for PCPL code execution, replaced with python code execution
|
||||||
|
"""
|
||||||
|
PCPL.resetvar()
|
||||||
|
PCPL.LIS("HASHBASE")
|
||||||
|
PCPL.run(self.code)"""
|
||||||
|
exec(self.code, API)
|
||||||
|
|
||||||
|
class previewrend:
|
||||||
|
def __init__(self, size, cam, container, offset):
|
||||||
|
self._size = size
|
||||||
|
self._grid = {}
|
||||||
|
self._win = container
|
||||||
|
self._frame = tk.Frame(container)
|
||||||
|
self._posframe = tk.Frame(self._frame)
|
||||||
|
self._cam = cam
|
||||||
|
self._xcam = tk.Label(self._posframe, text="-")
|
||||||
|
self._ycam = tk.Label(self._posframe, text="-")
|
||||||
|
self._xcam.grid(row=size[1], column=0)
|
||||||
|
self._ycam.grid(row=size[1]+1, column=0)
|
||||||
|
|
||||||
|
tkeys = list(string.ascii_letters)
|
||||||
|
self._keys = {}
|
||||||
|
for i in tkeys:
|
||||||
|
self._keys[i] = False
|
||||||
|
self._win.bind("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", self.keydupd)
|
||||||
|
|
||||||
|
for y in range(size[1]):
|
||||||
|
for x in range(size[0]):
|
||||||
|
temp = tk.Label(self._frame, text=" ", borderwidth=1, relief=tk.GROOVE, width=3)
|
||||||
|
temp.grid(row=y+offset[1], column=x+offset[0]+1)
|
||||||
|
self._win.update()
|
||||||
|
self._grid[f"{x}:{y}"] = temp
|
||||||
|
self._posframe.grid()
|
||||||
|
self._frame.grid()
|
||||||
|
|
||||||
|
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(int(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):
|
||||||
|
self._xcam.config(text=LH.string("xcam")+str(self._cam.position.x))
|
||||||
|
self._ycam.config(text=LH.string("ycam")+str(self._cam.position.y))
|
||||||
|
if f"{x}:{y}" in self._grid:
|
||||||
|
self._grid[f"{x}:{y}"].config(text=text, bg=self.coltohex(bcolor), fg=self.coltohex(fcolor))
|
||||||
|
|
||||||
|
class render:
|
||||||
|
def __init__(self, size, cam, container, offset):
|
||||||
|
self._size = size
|
||||||
|
self._grid = {}
|
||||||
|
self._win = container
|
||||||
|
self._frame = tk.Frame(container)
|
||||||
|
self._posframe = tk.Frame(self._frame)
|
||||||
|
self._cam = cam
|
||||||
|
self._xcam = tk.Label(self._posframe, text="-")
|
||||||
|
self._ycam = tk.Label(self._posframe, text="-")
|
||||||
|
#self._xcam.grid(row=size[1], column=0)
|
||||||
|
#self._ycam.grid(row=size[1]+1, column=0)
|
||||||
|
|
||||||
|
tkeys = list(string.ascii_letters)
|
||||||
|
self._keys = {}
|
||||||
|
for i in tkeys:
|
||||||
|
self._keys[i] = False
|
||||||
|
self._win.bind("<KeyPress>", self.keypupd)
|
||||||
|
self._win.bind("<KeyRelease>", self.keydupd)
|
||||||
|
|
||||||
|
for y in range(size[1]):
|
||||||
|
for x in range(size[0]):
|
||||||
|
temp = tk.Label(self._frame, text=" ", width=3)
|
||||||
|
temp.grid(row=y+offset[1], column=x+offset[0]+1)
|
||||||
|
self._win.update()
|
||||||
|
self._grid[f"{x}:{y}"] = temp
|
||||||
|
self._posframe.grid()
|
||||||
|
self._frame.grid()
|
||||||
|
|
||||||
|
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(int(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):
|
||||||
|
self._xcam.config(text=LH.string("xcam")+str(self._cam.position.x))
|
||||||
|
self._ycam.config(text=LH.string("ycam")+str(self._cam.position.y))
|
||||||
|
if f"{x}:{y}" in self._grid:
|
||||||
|
self._grid[f"{x}:{y}"].config(text=text, bg=self.coltohex(bcolor), fg=self.coltohex(fcolor))
|
||||||
|
|
||||||
|
class nullrend:
|
||||||
|
def __init__(self, size, cam):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getkeys(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pix(self, x, y, text, bcolor, fcolor):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def selectlang(new):
|
||||||
|
lang = open("clang", 'w')
|
||||||
|
lang.write(new)
|
||||||
|
lang.close()
|
||||||
|
container.quit()
|
||||||
|
subprocess.Popen([sys.executable, __file__])
|
||||||
|
|
||||||
|
def add(objtype):
|
||||||
|
global objtree
|
||||||
|
obj = getattr(types, objtype)()
|
||||||
|
args = {}
|
||||||
|
for i in dir(obj):
|
||||||
|
if i.startswith("_"): continue
|
||||||
|
args[i] = getattr(obj, i)
|
||||||
|
temp = {"id": objtype, "args": args, "name": LH.string(objtype)}
|
||||||
|
id = ""
|
||||||
|
chars = list(string.ascii_letters)
|
||||||
|
for i in range(255):
|
||||||
|
id = id + random.choice(chars)
|
||||||
|
if GUIe == True: objtree.insert("", tk.END, text=LH.string(objtype), image=icons[objtype], iid=id, tags=("objsel"))
|
||||||
|
gamedata[id] = temp
|
||||||
|
if objtype in crucial:
|
||||||
|
preview.addobj(obj)
|
||||||
|
gamedata[id]["args"]["ID"] = obj.ID
|
||||||
|
if GUIe == True: preview.render()
|
||||||
|
return id
|
||||||
|
|
||||||
|
def renameobj():
|
||||||
|
target = objtree.focus()
|
||||||
|
if target == "": return
|
||||||
|
new = easygui.enterbox(LH.string("NN"), LH.string("rename"))
|
||||||
|
if new:
|
||||||
|
objtree.item(target, text=new)
|
||||||
|
gamedata[target]["name"] = new
|
||||||
|
|
||||||
|
def delobj():
|
||||||
|
target = objtree.focus()
|
||||||
|
if target == "": return
|
||||||
|
atritree.delete(*atritree.get_children())
|
||||||
|
objtree.delete(target)
|
||||||
|
temp = gamedata.pop(target)
|
||||||
|
if temp["id"] in crucial:
|
||||||
|
preview.removeobjbyid(temp["args"]["ID"])
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def rpopup(event):
|
||||||
|
try:
|
||||||
|
rmenu.tk_popup(event.x_root, event.y_root)
|
||||||
|
finally:
|
||||||
|
rmenu.grab_release()
|
||||||
|
|
||||||
|
def getattributes(target):
|
||||||
|
out = {}
|
||||||
|
for i in dir(target):
|
||||||
|
if i.startswith("_"): continue
|
||||||
|
out[i] = getattr(target, i)
|
||||||
|
return out
|
||||||
|
|
||||||
|
def updatribute(event):
|
||||||
|
global currentat
|
||||||
|
target = objtree.focus()
|
||||||
|
currentat = target
|
||||||
|
atritree.delete(*atritree.get_children())
|
||||||
|
for i in gamedata[target]["args"]:
|
||||||
|
if i in ignoreat: continue
|
||||||
|
|
||||||
|
if i in valtypes:
|
||||||
|
val = gamedata[target]["args"][i]
|
||||||
|
atritree.insert("", tk.END, text=i, values=(val))
|
||||||
|
else:
|
||||||
|
root = atritree.insert("", tk.END, text=i)
|
||||||
|
temp = getattributes(gamedata[target]["args"][i])
|
||||||
|
for f in temp:
|
||||||
|
atritree.insert(root, tk.END, text=f, values=(temp[f]))
|
||||||
|
|
||||||
|
def halatribute(event):
|
||||||
|
target = atritree.focus()
|
||||||
|
name = atritree.item(target, "text")
|
||||||
|
parent = atritree.parent(target)
|
||||||
|
if name in valtypes:
|
||||||
|
if parent == "":
|
||||||
|
new = valtypes[name](gamedata[currentat]["args"][name])
|
||||||
|
gamedata[currentat]["args"][name] = new
|
||||||
|
if "ID" in gamedata[currentat]["args"]:
|
||||||
|
temp = preview.getobjbyid(gamedata[currentat]["args"]["ID"])
|
||||||
|
setattr(temp, name, new)
|
||||||
|
atritree.item(target, values=(new))
|
||||||
|
else:
|
||||||
|
parent = atritree.item(parent, "text")
|
||||||
|
new = valtypes[name](getattr(gamedata[currentat]["args"][parent], name))
|
||||||
|
setattr(gamedata[currentat]["args"][parent], name, new)
|
||||||
|
atritree.item(target, values=(new))
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def updatepreviewcam(char):
|
||||||
|
global cooldown
|
||||||
|
if cooldown == True: return
|
||||||
|
cooldown = True
|
||||||
|
char = char.char
|
||||||
|
if char == "w": preview.camera.position += hashengine.vector2(y=1)
|
||||||
|
if char == "a": preview.camera.position += hashengine.vector2(x=1)
|
||||||
|
if char == "s": preview.camera.position -= hashengine.vector2(y=1)
|
||||||
|
if char == "d": preview.camera.position -= hashengine.vector2(x=1)
|
||||||
|
preview.render()
|
||||||
|
time.sleep(0)
|
||||||
|
cooldown = False
|
||||||
|
|
||||||
|
def save():
|
||||||
|
target = filedialog.asksaveasfile()
|
||||||
|
target.write(str(prepgamedata()))
|
||||||
|
target.close()
|
||||||
|
messagebox.showinfo(LH.string("suc"), LH.string("save-suc"))
|
||||||
|
|
||||||
|
def clear():
|
||||||
|
global gamedata
|
||||||
|
objtree.delete(*objtree.get_children())
|
||||||
|
atritree.delete(*atritree.get_children())
|
||||||
|
gamedata = {}
|
||||||
|
preview._objects = {}
|
||||||
|
preview.camera.position = hashengine.vector2()
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def importsound(target):
|
||||||
|
oid = add("rawsound")
|
||||||
|
gamedata[oid]["name"] = target["name"]
|
||||||
|
gamedata[oid]["args"]["sdata"] = base64.b64decode(target["args"]["sdata"])
|
||||||
|
gamedata[oid]["args"]["spath"] = target["args"]["spath"]
|
||||||
|
if GUIe == True: objtree.item(oid, text=target["name"])
|
||||||
|
|
||||||
|
def importobj(target):
|
||||||
|
if target["id"] == "sound" or target["id"] == "rawsound":
|
||||||
|
importsound(target)
|
||||||
|
return
|
||||||
|
oid = add(target["id"])
|
||||||
|
id = gamedata[oid]
|
||||||
|
id["name"] = target["name"]
|
||||||
|
if GUIe == True: objtree.item(oid, text=target["name"])
|
||||||
|
#create arguments
|
||||||
|
outargs = {}
|
||||||
|
for argname in target["args"]:
|
||||||
|
arg = target["args"][argname]
|
||||||
|
if isinstance(arg, dict):
|
||||||
|
ID = arg.pop("ARGID")
|
||||||
|
obj = attypes[ID]()
|
||||||
|
for i in arg:
|
||||||
|
setattr(obj, i, arg[i])
|
||||||
|
arg = obj
|
||||||
|
outargs[argname] = arg
|
||||||
|
#apply arguments to obj
|
||||||
|
if target["id"] in crucial:
|
||||||
|
for i in outargs:
|
||||||
|
setattr(preview.getobjbyid(gamedata[oid]["args"]["ID"]), i, outargs[i])
|
||||||
|
id["args"].update(outargs)
|
||||||
|
|
||||||
|
def load():
|
||||||
|
file = filedialog.askopenfile()
|
||||||
|
tempwin = tk.Tk()
|
||||||
|
ptext = tk.Label(tempwin, text="NONE")
|
||||||
|
ptext.place(y=30)
|
||||||
|
stat = tk.Label(tempwin, text="NONE")
|
||||||
|
stat.place(y=50)
|
||||||
|
target = file.read()
|
||||||
|
file.close()
|
||||||
|
target = ast.literal_eval(target)
|
||||||
|
clear()
|
||||||
|
count = 1
|
||||||
|
bar = tkk.Progressbar(tempwin, maximum=len(target))
|
||||||
|
bar.place(width=200)
|
||||||
|
for i in target:
|
||||||
|
ptext.config(text="Current: "+i["name"])
|
||||||
|
bar.step()
|
||||||
|
stat.config(text=f"Object {count}/{len(target)}")
|
||||||
|
tempwin.update()
|
||||||
|
importobj(i)
|
||||||
|
count += 1
|
||||||
|
tempwin.destroy()
|
||||||
|
preview.render()
|
||||||
|
|
||||||
|
def log(text, end="\n", flush=False):
|
||||||
|
global logfile
|
||||||
|
if not os.path.exists("logs"):
|
||||||
|
os.mkdir("logs")
|
||||||
|
file = open("logs/"+logfile+".txt", 'a')
|
||||||
|
file.write(str(text)+end)
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
def NULL():
|
||||||
|
pass
|
||||||
|
|
||||||
|
class gsound:
|
||||||
|
def __init__(self, data, game):
|
||||||
|
self._playing = False
|
||||||
|
self._data = data
|
||||||
|
game.currentsounds.append(self)
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
if self._playing == True: return
|
||||||
|
self._sound = sa.play_buffer(self._data, 2, 2, 44100)
|
||||||
|
self._playing = True
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.stop()
|
||||||
|
self._playing = False
|
||||||
|
|
||||||
|
def wait(self):
|
||||||
|
if self._playing == False: return
|
||||||
|
self._sound.wait_done()
|
||||||
|
|
||||||
|
def testing():
|
||||||
|
global testproc
|
||||||
|
testproc = multiprocessing.Process(target=execgame, args=(prepgamedata(),))
|
||||||
|
testproc.start()
|
||||||
|
|
||||||
|
def run():
|
||||||
|
print("preparing log file...")
|
||||||
|
global logfile
|
||||||
|
global maingame
|
||||||
|
global window
|
||||||
|
temp = time.gmtime(time.time())
|
||||||
|
logfile = ""
|
||||||
|
for i in temp:
|
||||||
|
logfile = logfile + "S" + str(i)
|
||||||
|
print("done")
|
||||||
|
log("Log file start!")
|
||||||
|
log("Preparing API...")
|
||||||
|
API = {"print": log, "HASHBASE": hashengine}
|
||||||
|
log("Done!")
|
||||||
|
window = tk.Tk()
|
||||||
|
window.protocol("WM_DELETE_WINDOW", NULL)
|
||||||
|
maingame = hashengine.game(renderer=lambda size, cam: render(size, cam, window, [0, 0]), sounddir="/")
|
||||||
|
API["HASHGAME"] = maingame
|
||||||
|
API["SOUND"] = lambda data: gsound(data, maingame)
|
||||||
|
log("main game initalised!")
|
||||||
|
log("copying sounds...")
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
if i["id"] != "sound" and i["id"] != "rawsound": continue
|
||||||
|
maingame.sounds[i["args"]["spath"]] = i["args"]["sdata"]
|
||||||
|
print(i["args"]["spath"])
|
||||||
|
objects = copy.deepcopy(preview._objects)
|
||||||
|
maingame._objects = objects
|
||||||
|
scripts = []
|
||||||
|
for i in gamedata:
|
||||||
|
i = gamedata[i]
|
||||||
|
if i["id"] != "script": continue
|
||||||
|
i = i["args"]["code"]
|
||||||
|
obj = script()
|
||||||
|
obj.code = i
|
||||||
|
scripts.append(obj)
|
||||||
|
log("objects transferred!")
|
||||||
|
gamescript = """
|
||||||
|
global HASHGAME
|
||||||
|
import time
|
||||||
|
while True:
|
||||||
|
for i in HASHGAME._objects:
|
||||||
|
i = HASHGAME._objects[i]
|
||||||
|
HASHGAME.calcphysobj(i)
|
||||||
|
HASHGAME.render()
|
||||||
|
"""
|
||||||
|
gameloopsc = script()
|
||||||
|
gameloopsc.code = gamescript
|
||||||
|
maingame.startscript(lambda: gameloopsc.execute(API))
|
||||||
|
log("game test started!!!")
|
||||||
|
log("---------------------")
|
||||||
|
for i in scripts:
|
||||||
|
maingame.startscript(lambda: i.execute(API))
|
||||||
|
window.mainloop()
|
||||||
|
|
||||||
|
def muladd(target):
|
||||||
|
for i in range(10):
|
||||||
|
add(target)
|
||||||
|
|
||||||
|
def stoptest():
|
||||||
|
global testproc
|
||||||
|
testproc.terminate()
|
||||||
|
|
||||||
|
def build():
|
||||||
|
print("asking user for output directory...")
|
||||||
|
target = filedialog.askdirectory()
|
||||||
|
os.mkdir(target+"/out")
|
||||||
|
target = target+"/out"
|
||||||
|
print("building started")
|
||||||
|
print("generating HEGF file...")
|
||||||
|
hegf = str(prepgamedata())
|
||||||
|
file = open(target+"/game.HEGF", 'w')
|
||||||
|
file.write(hegf)
|
||||||
|
file.close()
|
||||||
|
print("done.")
|
||||||
|
print("copying files...")
|
||||||
|
tocopy = ["mtTkinter.py", "hashengine.py"]
|
||||||
|
for i in tocopy:
|
||||||
|
print(f"copying {i}...")
|
||||||
|
shutil.copyfile(i, target+"/"+i)
|
||||||
|
shutil.copyfile(__file__, target+"/"+"player.py")
|
||||||
|
file = open(target+"/main.py", 'w')
|
||||||
|
file.write("""
|
||||||
|
import player
|
||||||
|
import ast
|
||||||
|
file = open("game.HEGF", 'r')
|
||||||
|
file = file.read()
|
||||||
|
file = ast.literal_eval(file)
|
||||||
|
player.execgame(file)
|
||||||
|
""")
|
||||||
|
print("done.")
|
||||||
|
print("building finished!")
|
||||||
|
|
||||||
|
def GUIinit():
|
||||||
|
global container
|
||||||
|
global objtree
|
||||||
|
global rmenu
|
||||||
|
global atritree
|
||||||
|
global currentat
|
||||||
|
global preview
|
||||||
|
global GUIe
|
||||||
|
GUIe = True
|
||||||
|
container = tk.Tk()
|
||||||
|
container.bind("<KeyPress>", updatepreviewcam)
|
||||||
|
|
||||||
|
global icons
|
||||||
|
icons = {}
|
||||||
|
|
||||||
|
for i in os.listdir("icons"):
|
||||||
|
icons[i.split(".")[0]] = tk.PhotoImage(file=f"icons/{i}")
|
||||||
|
|
||||||
|
#preview init
|
||||||
|
preview = hashengine.game(renderer=lambda size, cam: previewrend(size, cam, container=container, offset=[0, 0]), sounddir="/")
|
||||||
|
|
||||||
|
#tree init
|
||||||
|
objtree = tkk.Treeview(container, selectmode="browse", columns=("-"))
|
||||||
|
objtree.heading("#0", text=LH.string("objs"))
|
||||||
|
objtree.tag_bind("objsel", "<<TreeviewSelect>>", updatribute)
|
||||||
|
objtree.grid(row=1, column=0)
|
||||||
|
|
||||||
|
#attribute tree init
|
||||||
|
currentat = "temp"
|
||||||
|
atritree = tkk.Treeview(container, columns=("#1"), selectmode="browse")
|
||||||
|
atritree.heading("#0", text=LH.string("attribute"))
|
||||||
|
atritree.heading("#1", text=LH.string("attribute-val"))
|
||||||
|
atritree.bind("<Double-1>", halatribute)
|
||||||
|
atritree.grid(row=2, column=0)
|
||||||
|
|
||||||
|
#right click menu
|
||||||
|
rmenu = tk.Menu(container, tearoff=0)
|
||||||
|
rmenu.add_command(label=LH.string("rename"), command=renameobj)
|
||||||
|
rmenu.add_command(label=LH.string("delete"), command=delobj)
|
||||||
|
|
||||||
|
objtree.bind("<Button-3>", rpopup)
|
||||||
|
|
||||||
|
#menu init
|
||||||
|
menu = tk.Menu(container)
|
||||||
|
container.config(menu=menu)
|
||||||
|
filemenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("file"), menu=filemenu)
|
||||||
|
filemenu.add_command(label=LH.string("new"), command=clear)
|
||||||
|
filemenu.add_command(label=LH.string("open"), command=load)
|
||||||
|
filemenu.add_command(label=LH.string("save"), command=save)
|
||||||
|
filemenu.add_separator()
|
||||||
|
filemenu.add_command(label=LH.string("exit"), command=container.quit)
|
||||||
|
|
||||||
|
addmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("add"), menu=addmenu)
|
||||||
|
addmenu.add_command(label=LH.string("obj"), command=lambda: add("obj"))
|
||||||
|
addmenu.add_command(label=LH.string("script"), command=lambda: add("script"))
|
||||||
|
addmenu.add_command(label=LH.string("sound"), command=lambda: add("sound"))
|
||||||
|
#addmenu.add_command(label=LH.string("obj"), command=lambda: muladd("obj"))
|
||||||
|
|
||||||
|
testmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("testing"), menu=testmenu)
|
||||||
|
testmenu.add_command(label=LH.string("test"), command=testing, image=icons["test"], compound="left")
|
||||||
|
testmenu.add_command(label=LH.string("stest"), command=stoptest, image=icons["stop-test"], compound="left")
|
||||||
|
|
||||||
|
buildmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("building"), menu=buildmenu)
|
||||||
|
buildmenu.add_command(label=LH.string("build"), command=build, image=icons["build"], compound="left")
|
||||||
|
|
||||||
|
langmenu = tk.Menu(menu)
|
||||||
|
menu.add_cascade(label=LH.string("langs"), menu=langmenu)
|
||||||
|
for i in LH.getlangs():
|
||||||
|
langmenu.add_command(label=i, command=lambda i=i: selectlang(i))
|
||||||
|
|
||||||
|
container.mainloop()
|
||||||
|
|
||||||
|
# attribute changers
|
||||||
|
def ats(mode, old):
|
||||||
|
#mode 0 = string
|
||||||
|
#mode 1 = single character
|
||||||
|
out = easygui.enterbox(LH.string("newval"), LH.string("newval"))
|
||||||
|
if out:
|
||||||
|
if mode == 1 and len(out) != 1:
|
||||||
|
messagebox.showerror(LH.string("error"), LH.string("SCE"))
|
||||||
|
return "N"
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def anum(old):
|
||||||
|
out = easygui.enterbox(LH.string("newval"), LH.string("newval"))
|
||||||
|
if out:
|
||||||
|
if "." in out:
|
||||||
|
try:
|
||||||
|
out = float(out)
|
||||||
|
return out
|
||||||
|
except ValueError:
|
||||||
|
return old
|
||||||
|
else:
|
||||||
|
return int(out)
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def abool(old):
|
||||||
|
out = easygui.boolbox(LH.string("newval"), LH.string("newval"), (LH.string("true"), LH.string("false")))
|
||||||
|
if out:
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def acode(old):
|
||||||
|
out = easygui.textbox(LH.string("newval"), LH.string("newval"), old)
|
||||||
|
if out:
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def apath(old, ext):
|
||||||
|
new = filedialog.askopenfilename(defaultextension=ext, filetypes=(ext))
|
||||||
|
if new:
|
||||||
|
return new
|
||||||
|
else:
|
||||||
|
return old
|
||||||
|
|
||||||
|
def aNULL(old):
|
||||||
|
return old
|
||||||
|
|
||||||
|
def execgame(gametree):
|
||||||
|
global GUIe
|
||||||
|
global preview
|
||||||
|
preview = hashengine.game(renderer=nullrend, sounddir="/")
|
||||||
|
GUIe = False
|
||||||
|
for i in gametree:
|
||||||
|
importobj(i)
|
||||||
|
run()
|
||||||
|
|
||||||
|
class rsound:
|
||||||
|
def __init__(self):
|
||||||
|
self.spath = ""
|
||||||
|
self.sdata = b""
|
||||||
|
|
||||||
|
class sound():
|
||||||
|
def __init__(self, new):
|
||||||
|
self.spath = os.path.basename(new).split(".")[0]
|
||||||
|
self.sdata = hashengine.loadsound(new)
|
||||||
|
|
||||||
|
global types
|
||||||
|
global ignoreat
|
||||||
|
global valtypes
|
||||||
|
global extypes
|
||||||
|
global attypes
|
||||||
|
global crucial
|
||||||
|
crucial = ["obj"]
|
||||||
|
types = hashengine.enum({"obj": hashengine.obj, "script": script, "rawsound": rsound, "sound": lambda: sound(apath("", [("Wave files", ".wave .wav")]))})
|
||||||
|
ignoreat = ["ID", "execute", "sdata"]
|
||||||
|
"""self.position = vector2()
|
||||||
|
self.char = " "
|
||||||
|
self.ID = 0
|
||||||
|
self.gravity = 0
|
||||||
|
self.acceleration = vector2()
|
||||||
|
self.velocity = vector2()
|
||||||
|
self.friction = 0
|
||||||
|
self.collide = True
|
||||||
|
self.touch = True
|
||||||
|
self.anchored = False
|
||||||
|
self.bcolor = color3(255, 255, 255)
|
||||||
|
self.fcolor = color3()"""
|
||||||
|
valtypes = {
|
||||||
|
"char": lambda old: ats(1, old),
|
||||||
|
"gravity": anum,
|
||||||
|
"x": anum,
|
||||||
|
"y": anum,
|
||||||
|
"z": anum,
|
||||||
|
"r": anum,
|
||||||
|
"g": anum,
|
||||||
|
"b": anum,
|
||||||
|
"friction": anum,
|
||||||
|
"collide": abool,
|
||||||
|
"touch": abool,
|
||||||
|
"anchored": abool,
|
||||||
|
"code": acode,
|
||||||
|
"spath": aNULL,
|
||||||
|
}
|
||||||
|
#lambda old: apath(old, [("Wave files", ".wave .wav")])
|
||||||
|
extypes = list(valtypes.keys())
|
||||||
|
attypes = {
|
||||||
|
"vector2": hashengine.vector2,
|
||||||
|
"color3": hashengine.color3,
|
||||||
|
}
|
||||||
|
if __name__ == "__main__":
|
||||||
|
GUIinit()
|
|
@ -0,0 +1 @@
|
||||||
|
[{'id': 'script', 'name': 'Skript', 'args': {'code': 'import time\nwhile True:\n\tprint(HASHGAME.isdown("q"))\n\ttime.sleep(1)'}}]
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Loading…
Reference in New Issue