added building

main
Justus Jan Nico Wolff 2024-05-13 19:57:26 +02:00
parent 7c6afef69b
commit ae80270d71
19 changed files with 1573 additions and 18 deletions

View File

@ -201,11 +201,12 @@ class game:
def calcphysobj(self, target: obj):
if target.anchored == True: return
colliding = self.collidingpos(target.position+target.velocity, [target,])
for i in colliding:
target._touching.execute()
i._touching.execute()
self.handlecollision(target, i)
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

BIN
icons/build.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

BIN
icons/stop-test.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

BIN
icons/test.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

View File

@ -25,4 +25,7 @@
"ycam": "Kamera y Position:",
"testing": "Testen",
"test": "Spiel ausfuehren",
"stest": "Test stoppen",
"building": "Bauen",
"build": "Bauen",
}

View File

@ -25,4 +25,7 @@
"ycam": "Camera y position:",
"testing": "Testing",
"test": "Execute game",
"stest": "Stop execution",
"building": "Building",
"build": "Build",
}

93
main.py
View File

@ -13,10 +13,10 @@ import subprocess
import sys
import time
import hashengine
import shutil
import os
import random
import string
import threading
import easygui
global LH
@ -34,8 +34,18 @@ PCPL.interpreter.ENG = hashengine
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 = {}
@ -52,6 +62,7 @@ def prepgamedata():
tempargs[argname] = temp2
temp["args"] = tempargs
out.append(temp)
tempwin.destroy()
return out
class script:
@ -91,7 +102,7 @@ class previewrend:
colors = []
target = [target.r, target.g, target.b]
for i in target:
colors.append(("0"*(2-len(hex(i)[2:])))+hex(i)[2:])
colors.append(("0"*(2-len(hex(int(i))[2:])))+hex(i)[2:])
out = ""
for i in colors:
out = out + i
@ -252,12 +263,26 @@ def importobj(target):
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):
@ -266,10 +291,14 @@ def log(text, end="\n", flush=False):
file.write(text+end)
file.close()
def NULL():
pass
def testing():
print("preparing log file...")
global logfile
global maingame
global window
temp = time.gmtime(time.time())
logfile = ""
for i in temp:
@ -280,6 +309,7 @@ def testing():
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]))
API["HASHGAME"] = maingame
log("main game initalised!")
@ -304,7 +334,6 @@ while True:
i = HASHGAME._objects[i]
HASHGAME.calcphysobj(i)
HASHGAME.render()
time.sleep(.0)
"""
gameloopsc = script()
gameloopsc.code = gamescript
@ -312,6 +341,32 @@ while True:
log("game test started!!!")
log("---------------------")
def muladd(target):
for i in range(10):
add(target)
def stoptest():
maingame.stopscripts()
window.destroy()
def build():
print("asking user for output directory...")
target = filedialog.askdirectory()
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", "player.py", "hashengine.py"]
for i in tocopy:
print(f"copying {i}...")
shutil.copyfile(i, target+"/"+i)
print("done.")
print("building finished!")
def GUIinit():
global container
global objtree
@ -367,10 +422,16 @@ def GUIinit():
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("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)
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)
@ -390,28 +451,37 @@ def ats(mode, old):
return "N"
return out
else:
return "N"
return old
def anum(old):
out = easygui.integerbox(LH.string("newval"), LH.string("newval"), lowerbound=-9999999999, upperbound=9999999999)
out = easygui.enterbox(LH.string("newval"), LH.string("newval"))
if out:
return out
if "." in out:
try:
out = float(out)
return out
except ValueError:
return old
else:
return int(out)
else:
return 0
return old
def abool(old):
out = easygui.boolbox(LH.string("newval"), LH.string("newval"), (LH.string("true"), LH.string("false")))
return out
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 "NULL"
return old
global types
global icon
global ignoreat
global valtypes
global extypes
@ -419,7 +489,6 @@ global attypes
global crucial
crucial = ["obj"]
types = hashengine.enum({"obj": hashengine.obj, "script": script})
icon = hashengine.enum({"obj": "icons/object.png", "script": "icons/script.png"})
ignoreat = ["ID", "execute"]
"""self.position = vector2()
self.char = " "

184
player.py 100644
View File

@ -0,0 +1,184 @@
import hashengine
import random
import ast
import string
import threading
import mtTkinter as tk
import time
global gamedata
gamedata = {}
class rend:
def __init__(self, size, cam, container, offset):
self._size = size
self._grid = {}
self._win = container
self._frame = tk.Frame(container)
self._cam = cam
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._frame.grid()
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 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)
def add(objtype):
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": objtype}
id = ""
chars = list(string.ascii_letters)
for i in range(255):
id = id + random.choice(chars)
gamedata[id] = temp
if objtype in crucial:
game.addobj(obj)
gamedata[id]["args"]["ID"] = obj.ID
return id
def importobj(target):
oid = add(target["id"])
id = gamedata[oid]
id["name"] = 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(game.getobjbyid(gamedata[oid]["args"]["ID"]), i, outargs[i])
id["args"].update(outargs)
def load(target):
file = open(target, 'r')
target = file.read()
file.close()
target = ast.literal_eval(target)
for i in target:
importobj(i)
def log(text, end="\n", flush=False):
global logfile
file = open(logfile+".txt", 'a')
file.write(text+end)
file.close()
def NULL():
pass
def run():
print("preparing log file...")
global logfile
global win
global game
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!")
API["HASHGAME"] = game
log("main game initalised!")
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)
for i in scripts:
game.startscript(lambda: i.execute(API))
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
game.startscript(lambda: gameloopsc.execute(API))
log("game test started!!!")
log("---------------------")
def wait():
time.sleep(0.1)
load("game.HEGF")
run()
global types
global ignoreat
global valtypes
global extypes
global attypes
global crucial
global game
win = tk.Tk()
game = hashengine.game(renderer=lambda size, cam: rend(size, cam, win, [0, 0]))
crucial = ["obj",]
types = hashengine.enum({"obj": hashengine.obj, "script": script})
ignoreat = ["ID", "execute"]
"""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()"""
attypes = {
"vector2": hashengine.vector2,
"color3": hashengine.color3,
}
threading.Thread(target=wait).start()
win.mainloop()

View File

@ -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)'}}]

View File

@ -0,0 +1,287 @@
import tkinter as tk
import string
import random
import threading
import time
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())
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):
if renderer == None: raise TypeError("Renderer class needed!")
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):
for x in range(self._size[0]):
for y in range(self._size[1]):
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
self._renderer.pix(round(pos.x), round(pos.y), i.char, i.bcolor, i.fcolor)
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)
if __name__ == "__main__":
testgame = game()
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)

View 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

View File

@ -0,0 +1,184 @@
import hashengine
import random
import ast
import string
import threading
import mtTkinter as tk
import time
global gamedata
gamedata = {}
class rend:
def __init__(self, size, cam, container, offset):
self._size = size
self._grid = {}
self._win = container
self._frame = tk.Frame(container)
self._cam = cam
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._frame.grid()
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 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)
def add(objtype):
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": objtype}
id = ""
chars = list(string.ascii_letters)
for i in range(255):
id = id + random.choice(chars)
gamedata[id] = temp
if objtype in crucial:
game.addobj(obj)
gamedata[id]["args"]["ID"] = obj.ID
return id
def importobj(target):
oid = add(target["id"])
id = gamedata[oid]
id["name"] = 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(game.getobjbyid(gamedata[oid]["args"]["ID"]), i, outargs[i])
id["args"].update(outargs)
def load(target):
file = open(target, 'r')
target = file.read()
file.close()
target = ast.literal_eval(target)
for i in target:
importobj(i)
def log(text, end="\n", flush=False):
global logfile
file = open(logfile+".txt", 'a')
file.write(text+end)
file.close()
def NULL():
pass
def run():
print("preparing log file...")
global logfile
global win
global game
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!")
API["HASHGAME"] = game
log("main game initalised!")
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)
for i in scripts:
game.startscript(lambda: i.execute(API))
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
game.startscript(lambda: gameloopsc.execute(API))
log("game test started!!!")
log("---------------------")
def wait():
time.sleep(0.1)
load("game.HEGF")
run()
global types
global ignoreat
global valtypes
global extypes
global attypes
global crucial
global game
win = tk.Tk()
game = hashengine.game(renderer=lambda size, cam: rend(size, cam, win, [0, 0]))
crucial = ["obj",]
types = hashengine.enum({"obj": hashengine.obj, "script": script})
ignoreat = ["ID", "execute"]
"""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()"""
attypes = {
"vector2": hashengine.vector2,
"color3": hashengine.color3,
}
threading.Thread(target=wait).start()
win.mainloop()

View File

@ -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'}}}]

View File

@ -0,0 +1,287 @@
import tkinter as tk
import string
import random
import threading
import time
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())
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):
if renderer == None: raise TypeError("Renderer class needed!")
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):
for x in range(self._size[0]):
for y in range(self._size[1]):
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
self._renderer.pix(round(pos.x), round(pos.y), i.char, i.bcolor, i.fcolor)
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)
if __name__ == "__main__":
testgame = game()
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)

View 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

View File

@ -0,0 +1,184 @@
import hashengine
import random
import ast
import string
import threading
import mtTkinter as tk
import time
global gamedata
gamedata = {}
class rend:
def __init__(self, size, cam, container, offset):
self._size = size
self._grid = {}
self._win = container
self._frame = tk.Frame(container)
self._cam = cam
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._frame.grid()
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 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)
def add(objtype):
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": objtype}
id = ""
chars = list(string.ascii_letters)
for i in range(255):
id = id + random.choice(chars)
gamedata[id] = temp
if objtype in crucial:
game.addobj(obj)
gamedata[id]["args"]["ID"] = obj.ID
return id
def importobj(target):
oid = add(target["id"])
id = gamedata[oid]
id["name"] = 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(game.getobjbyid(gamedata[oid]["args"]["ID"]), i, outargs[i])
id["args"].update(outargs)
def load(target):
file = open(target, 'r')
target = file.read()
file.close()
target = ast.literal_eval(target)
for i in target:
importobj(i)
def log(text, end="\n", flush=False):
global logfile
file = open(logfile+".txt", 'a')
file.write(text+end)
file.close()
def NULL():
pass
def run():
print("preparing log file...")
global logfile
global win
global game
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!")
API["HASHGAME"] = game
log("main game initalised!")
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)
for i in scripts:
game.startscript(lambda: i.execute(API))
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
game.startscript(lambda: gameloopsc.execute(API))
log("game test started!!!")
log("---------------------")
def wait():
time.sleep(0.1)
load("game.HEGF")
run()
global types
global ignoreat
global valtypes
global extypes
global attypes
global crucial
global game
win = tk.Tk()
game = hashengine.game(renderer=lambda size, cam: rend(size, cam, win, [0, 0]))
crucial = ["obj",]
types = hashengine.enum({"obj": hashengine.obj, "script": script})
ignoreat = ["ID", "execute"]
"""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()"""
attypes = {
"vector2": hashengine.vector2,
"color3": hashengine.color3,
}
threading.Thread(target=wait).start()
win.mainloop()

View File

@ -1 +0,0 @@
[{'id': 'obj', 'name': 'boden', 'args': {'anchored': True, 'char': '#', 'collide': True, 'friction': 0, 'gravity': 0, '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': 0, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': 'objekt', 'args': {'anchored': False, 'char': '#', 'collide': True, 'friction': 0, 'gravity': 1, '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': 0, 'y': -5, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'script', 'name': 'cam', 'args': {'code': 'global HASHGAME\nglobal HASHBASE\nHASHGAME.camera.position = HASHBASE.vector2(4, 6)'}}]

View File

@ -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'}}}]

1
tests/mulobjtest 100644

File diff suppressed because one or more lines are too long