added scripting documentation and object importing and exporting

main
Justus Jan Nico Wolff 2024-05-23 13:20:17 +02:00
parent 77423821c5
commit 7d9bd5e910
10 changed files with 221 additions and 23 deletions

View File

@ -272,14 +272,8 @@ class game:
return [opos, collide]
def calcphysmodel(self, target: model):
reverse = []
for i in target._objects:
back = self.calcphysmodel(i)
reverse.append((i, back[0]))
if back[1]:
for obj in reverse:
obj[0].Position = obj[1]
break
self.calcphysobj(i)
def addobj(self, obj):
id = ""

View File

@ -33,4 +33,7 @@
"COBS": "Objekte durch String erstellen",
"IOM": "Erstellte Objekte",
"done": "Fertig",
"COP": "Position aendern",
"export": "Exportieren",
"import": "Importieren",
}

View File

@ -33,4 +33,7 @@
"COBS": "Create objects by string",
"IOM": "Created objects",
"done": "Done",
"COP": "Change position",
"export": "Export",
"import": "Import",
}

157
main.py
View File

@ -53,6 +53,8 @@ version = "HE2.2-Hashengine V2.2"
cooldown = False
gamedata = {}
print(string.ascii_letters)
def prepgamedata():
out = []
tempwin = tk.Tk()
@ -89,6 +91,42 @@ def prepgamedata():
tempwin.destroy()
return out
def prepspecified(target):
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 target:
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 = ""
@ -246,7 +284,7 @@ def selectlang(new):
container.quit()
subprocess.Popen([sys.executable, __file__])
def add(objtype, parent=""):
def add(objtype, parent="", render=True):
global objtree
obj = getattr(types, objtype)()
args = {}
@ -260,7 +298,7 @@ def add(objtype, parent=""):
if objtype in crucial:
preview.addobj(obj)
gamedata[id]["args"]["ID"] = obj.ID
if GUIe == True: preview.render()
if GUIe == True and render == True: preview.render()
return id
def renameobj():
@ -269,14 +307,15 @@ def renameobj():
new = easygui.enterbox(LH.string("NN"), LH.string("rename"))
if new:
objtree.item(target, text=new)
gamedata[target]["name"] = new
if not "HASHMODEL" in objtree.item(target, "tags"):
gamedata[target]["name"] = new
def delobjg(target):
objtree.delete(target)
temp = gamedata.pop(target)
if temp["id"] in crucial:
preview.removeobjbyid(temp["args"]["ID"])
preview.render()
#preview.render()
def delobj():
target = objtree.selection()
@ -284,11 +323,53 @@ def delobj():
atritree.delete(*atritree.get_children())
for i in target:
if "HASHMODEL" in objtree.item(i, "tags"):
tempwin = tk.Tk()
stat = tk.Label(tempwin, text="NONE")
stat.grid()
speed = tk.Label(tempwin, text="NONE")
speed.grid()
tempwin.update()
count = 0
length = len(objtree.get_children(i))
fpscount = 0
timestamp = time.time()
fps = 0
for f in objtree.get_children(i):
delobjg(f)
stat.config(text=f"{count}/{length}")
speed.config(text=f"{fps}/s")
tempwin.update()
count += 1
fpscount += 1
if time.time()-timestamp > 0.1:
fps = fpscount*10
fpscount = 0
timestamp = time.time()
objtree.delete(i)
tempwin.destroy()
else:
delobjg(i)
preview.render()
def HMPC(event):
currentat = objtree.focus()
target = atritree.focus()
name = atritree.item(target, "text")
back = 0
if name == "x":
back = aposx(0)
elif name == "y":
back = aposy(0)
for i in objtree.get_children(currentat):
if not "ID" in gamedata[i]["args"]: continue
setattr(gamedata[i]["args"]["position"], name, getattr(gamedata[i]["args"]["position"], name)+back)
setattr(preview.getobjbyid(gamedata[i]["args"]["ID"]).position, name, getattr(preview.getobjbyid(gamedata[i]["args"]["ID"]).position, name)+back)
preview.render()
def changemodelpos(event):
atritree.delete(*atritree.get_children())
atritree.insert("", index=tk.END, text="x", tags=("OA",))
atritree.insert("", index=tk.END, text="y", tags=("OA",))
def rpopup(event):
try:
@ -310,18 +391,16 @@ def updatribute(event):
atritree.delete(*atritree.get_children())
for i in gamedata[target]["args"]:
if i in ignoreat: continue
if i in valtypes and not i in DCTE:
val = gamedata[target]["args"][i]
atritree.insert("", tk.END, text=i, values=(val))
atritree.insert("", tk.END, text=i, values=(val), tags=("FA", ))
elif i in valtypes and i in DCTE:
atritree.insert("", tk.END, text=i, values=("<DCTE>"))
atritree.insert("", tk.END, text=i, values=("<DCTE>"), tags=("FA", ))
else:
root = atritree.insert("", tk.END, text=i)
root = atritree.insert("", tk.END, text=i, tags=("FA", ))
temp = getattributes(gamedata[target]["args"][i])
for f in temp:
atritree.insert(root, tk.END, text=f, values=(temp[f]))
atritree.insert(root, tk.END, text=f, values=(temp[f]), tags=("FA", ))
def halatribute(event):
target = atritree.focus()
@ -340,6 +419,9 @@ def halatribute(event):
parent = atritree.item(parent, "text")
new = valtypes[name](getattr(gamedata[currentat]["args"][parent], name))
setattr(gamedata[currentat]["args"][parent], name, new)
if "ID" in gamedata[currentat]["args"]:
temp = preview.getobjbyid(gamedata[currentat]["args"]["ID"])
setattr(temp, name, new)
if not name in DCTE: atritree.item(target, values=(new))
if name in DCTE: atritree.item(target, values=("<DCTE>"))
preview.render()
@ -404,7 +486,7 @@ def importobj(target):
setattr(preview.getobjbyid(gamedata[oid]["args"]["ID"]), i, outargs[i])
id["args"].update(outargs)
def load():
def load(cleargame=True):
file = filedialog.askopenfile()
tempwin = tk.Tk()
ptext = tk.Label(tempwin, text="NONE")
@ -414,7 +496,8 @@ def load():
target = file.read()
file.close()
target = ast.literal_eval(target)
clear()
if cleargame:
clear()
count = 1
bar = tkk.Progressbar(tempwin, maximum=len(target))
bar.place(width=200)
@ -428,6 +511,21 @@ def load():
tempwin.destroy()
preview.render()
def export():
temp = objtree.selection()
if temp == (): return
target = []
for i in temp:
if "HASHMODEL" in objtree.item(i, "tags"):
target.extend(objtree.get_children(i))
else: target.append(i)
back = prepspecified(target)
targetpath = filedialog.asksaveasfile()
if not targetpath: return
targetpath.write(str(back))
targetpath.close()
messagebox.showinfo(LH.string("suc"), LH.string("save-suc"))
def log(text, end="\n", flush=False):
global logfile
if not os.path.exists("logs"):
@ -586,18 +684,38 @@ def genid():
return id
def COBS(target: str, offset=hashengine.vector2(), ignore=[" ",]):
origin = target
target = target.split("\n")
tempid = genid()
if GUIe == True: objtree.insert("", tk.END, text=LH.string("IOM"), image=icons["model"], iid=tempid, tags=("HASHMODEL"))
tempwin = tk.Tk()
stat = tk.Label(tempwin, text="NONE")
stat.grid()
speed = tk.Label(tempwin, text="NONE")
speed.grid()
tempwin.update()
if GUIe == True: objtree.insert("", tk.END, text=LH.string("IOM"), image=icons["model"], iid=tempid, tags=("HASHMODEL",))
count = 1
fpscount = 0
timestamp = time.time()
fps = 0
for i in range(len(target)):
y = i
i = target[i]
for f in range(len(i)):
x = f
f = i[x]
stat.config(text=f"{count}/{len(origin)}")
speed.config(text=f"{fps}/s")
tempwin.update()
count += 1
fpscount += 1
if time.time()-timestamp > 0.1:
fps = fpscount*10
fpscount = 0
timestamp = time.time()
if f in ignore:
continue
temp = add("obj", tempid)
temp = add("obj", tempid, False)
#gamedata[temp]["args"]["ID"]
gamedata[temp]["args"]["char"] = f
setattr(preview.getobjbyid(gamedata[temp]["args"]["ID"]), "char", f)
@ -607,7 +725,9 @@ def COBS(target: str, offset=hashengine.vector2(), ignore=[" ",]):
setattr(preview.getobjbyid(gamedata[temp]["args"]["ID"]), "anchored", True)
gamedata[temp]["args"]["collide"] = True
setattr(preview.getobjbyid(gamedata[temp]["args"]["ID"]), "collide", True)
preview.render()
#preview.render()
preview.render()
tempwin.destroy()
def GUIinit():
global container
@ -634,6 +754,7 @@ def GUIinit():
objtree = tkk.Treeview(container, columns=("-"))
objtree.heading("#0", text=LH.string("objs"))
objtree.tag_bind("objsel", "<<TreeviewSelect>>", updatribute)
objtree.tag_bind("HASHMODEL", "<<TreeviewSelect>>", changemodelpos)
objtree.grid(row=1, column=0)
#attribute tree init
@ -641,7 +762,8 @@ def GUIinit():
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.tag_bind("FA", "<Double-1>", halatribute)
atritree.tag_bind("OA", "<Double-1>", HMPC)
atritree.grid(row=2, column=0)
#right click menu
@ -660,6 +782,9 @@ def GUIinit():
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("export"), command=export)
filemenu.add_command(label=LH.string("import"), command=lambda: load(False))
filemenu.add_separator()
filemenu.add_command(label=LH.string("exit"), command=container.quit)
addmenu = tk.Menu(menu)

View File

@ -0,0 +1,59 @@
# Hashengine 2.2 Scripting documentation (EN)
Scripts in games made in Hashengine 2.2 have restricted access to the game.
this includes **HASHBASE**, **HASHGAME** and **SOUND**.
Note: the **print** function is redirected to an log function; all printed text is written into a file instead of stdout.
## HASHBASE
### **HASHBASE** gives access to the Hashengine module, it is intended to be used when creating **vector2** and **color3**.
vector2 describes an position in a game of Hashengine and to create an vector2 HASHBASE.vector2() should be used.
optional arguments are x and y. by default both are 0.
color3 describes an color, for either the foreground or background of an object.
to create an color HASHBASE.color3() should be used.
optional arguments are r, g and b. by default, all are 0.
To create objects in the game, use HASHBASE.obj().
No optional arguments.
events are used to execute one or more scripts when it is executed.
normal use cases of events are in objects._touched and all scripts attached to that event
get executed once that object is colliding with something.
to attach to an event use \<EVENT>.attach(\<FUNCTION>).
to create your own event use HASHBASE.event(), you can execute the event with \<EVENT>.execute() which will return a list of created threads where the executed functions run in.
Note: **HASHBASE** is sometimes also used to load custom sounds via HASHBASE.loadsound(path)
this returns an bytearray which can be then used to play the sounds, which will be explained later on.
## HASHGAME
### **HASHGAME** gives access to the running game class which handles collision, rendering etc.
use cases of **HASHGAME** are to access packaged sounds, the renderer, objects, the camera and the keyboard.
to access the object dictionary directly (which is normally a bad practice) use HASHGAME._objects.
the key to an object is its ID and the value is the object class.
to access the renderer (which is also normally bad practice) use HASHGAME._renderer, this gives you access to the running renderer class.
How to correctly access/add/remove an object:
to safely access an Object (no failsafes tho) you can use HASHGAME.getobjbyid(\<ID>).
to add an Object to the running game use HASHGAME.addobj(\<target object>).
to remove an object from the running game use HASHGAME.removeobj(\<target object class>) or HASHGAME.removeobjbyid(\<ID>).
To check if an specified key is currently pressed use HASHGAME.isdown(\<char>) this will return True if its currently being pressed, False if not and None if its not supported.
Supported Keys:
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
back to the camera: the camera is technically just an object with its position describing the rendering offset, meaning that the camera could be made into an player with scripting.
## SOUNDS
### Hashengine can play sounds too!
Hashengine supports audio playback. As previously said, HASHBASE.loadsound(\<PATH>) can be used to load an sound which is generally not good as audio is normally imported in the Hashengine editor and then packaged into the game.
to play a sound use SOUND(HASHGAME.sounds[\<Target sound name>]) or if youre using loadsound then SOUND(loadsound(\<PATH>)). this will return a **SOUND** Class which can playback the sound. to play the sound use \<sound>.play().
to stop the sound use \<sound>.stop() and to yield until the sound is done playing sue \<sound>.wait()

View File

@ -0,0 +1,10 @@
# #
# #
# #
##########

View File

@ -0,0 +1 @@
[{'id': 'obj', 'name': 'Objekt', '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': 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': 1, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': 'Objekt', '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': 2, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': 'Objekt', 'args': {'anchored': True, 'char': 'a', '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': 1, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': 'Objekt', 'args': {'anchored': True, 'char': 'b', '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': 1, 'y': 1, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': 'Objekt', 'args': {'anchored': True, 'char': 'c', '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': 2, 'y': 1, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}]

View File

@ -0,0 +1 @@
[{'id': 'obj', 'name': 'test', 'args': {'anchored': False, 'char': 'b', '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': 1, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': 'test1', 'args': {'anchored': False, 'char': 'a', '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'}}}]

View File

@ -0,0 +1 @@
[{'id': 'obj', 'name': 'Objekt', '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': 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': 1, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': 'Objekt', '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': 2, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}]

View File

@ -0,0 +1 @@
[{'id': 'obj', 'name': 'Objekt', 'args': {'anchored': False, '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'}}}]