Hashengine-2.3/hashengine.py

366 lines
12 KiB
Python
Raw Normal View History

2024-07-03 18:22:50 +02:00
import mtTkinter as tk
2024-07-06 15:21:14 +02:00
from HEMD import color3, vector2, event, NULL
import audiosys
from loadbar import loadbar
2024-07-04 15:23:29 +02:00
import random
import string
import math
2024-07-04 20:26:48 +02:00
import time
2024-07-05 15:27:31 +02:00
import threading
2024-07-06 15:21:14 +02:00
import pickle
2024-07-06 16:32:26 +02:00
from pathfinding import pathfinding
2024-07-07 12:27:18 +02:00
from keyboard import keyboard
2024-07-03 19:07:33 +02:00
#import itertools
#import multiprocessing
2024-07-03 18:22:50 +02:00
# designated graphics size pixel 5x5
__VERSION__ = "HE2.3-HASHENGINE-2.3"
2024-07-03 19:07:33 +02:00
2024-07-04 15:23:29 +02:00
class obj:
2024-07-03 19:07:33 +02:00
def __init__(self):
2024-07-04 15:23:29 +02:00
self.position = vector2()
self.collide = True
self.anchored = True
self.velocity = vector2()
self.acceleration = vector2()
self.id = NULL()
self.color = color3()
self.colliding = event()
2024-07-06 15:21:14 +02:00
self._parent = NULL()
2024-07-04 15:23:29 +02:00
self.children = []
2024-07-04 20:26:48 +02:00
self.ignorecollision = []
2024-07-03 19:07:33 +02:00
2024-07-06 15:21:14 +02:00
@property
def parent(self):
return self._parent
@parent.setter
def parent(self, value):
self._parent.children.remove(self)
self._parent = value
self._parent.children.append(self)
2024-07-07 17:32:02 +02:00
class folder:
def __init__(self):
self._parent = NULL()
self.children = []
@property
def parent(self):
return self._parent
@parent.setter
def parent(self, value):
self._parent.children.remove(self)
self._parent = value
self._parent.children.append(self)
2024-07-03 19:07:33 +02:00
class game:
2024-07-04 20:26:48 +02:00
def __init__(self, canvas: tk.Canvas, pixelsize=3):
2024-07-03 19:07:33 +02:00
self._canvas = canvas
2024-07-04 20:26:48 +02:00
self._height = int(canvas.winfo_reqheight()/pixelsize)
self._width = int(canvas.winfo_reqwidth()/pixelsize)
self._pixelsize = pixelsize
2024-07-03 19:07:33 +02:00
self._OAP = {}
self._objects = {}
self._visobjects = {}
2024-07-04 20:26:48 +02:00
self._camera = obj()
self._camera.zoom = pixelsize
2024-07-05 15:27:31 +02:00
self._OAPUPDATING = False
2024-07-06 15:21:14 +02:00
self._handler = audiosys.handler()
self._threads = []
self._root = obj()
self._scripts = []
2024-07-07 12:27:18 +02:00
self._keyboard = keyboard(self._canvas)
2024-07-03 19:07:33 +02:00
"""self._workers = []
self._processes = 2 # total number of processes.
for i in range(self._processes):
xresult = multiprocessing.Array("i")
yresult = multiprocessing.Array("i")
oresult = multiprocessing.Array("s")
temp = multiprocessing.Process()
temp.start()
2024-07-04 20:26:48 +02:00
self._workers.append({"process": temp, ""})""" # scraped idea, im keeping it in incase i ever decide to use it
2024-07-03 19:07:33 +02:00
2024-07-04 15:23:29 +02:00
def genid(self):
out = ""
for i in range(255):
out = out + random.choice(list(string.ascii_letters))
return out
2024-07-04 20:26:48 +02:00
def v2tuple(self, target: vector2):
return (target.x, target.y)
def tuple2v(self, target: tuple):
return vector2(target[0], target[1])
2024-07-04 15:23:29 +02:00
def addtooap(self, target: obj):
2024-07-04 20:26:48 +02:00
if self.v2tuple(target.position.__round__()) in self._OAP:
self._OAP[self.v2tuple(target.position.__round__())].append(target)
2024-07-04 15:23:29 +02:00
else:
2024-07-04 20:26:48 +02:00
self._OAP[self.v2tuple(target.position.__round__())] = [target]
def updateobjinoap(self, target: obj):
self.remfromoap(target)
self.addtooap(target)
2024-07-04 15:23:29 +02:00
def remfromoap(self, target: obj):
2024-07-04 20:26:48 +02:00
for i in self._OAP:
if target in self._OAP[i]:
self._OAP[i].remove(target)
if len(self._OAP[i]) == 0:
self._OAP.pop(i)
break
2024-07-04 15:23:29 +02:00
def getfromoap(self, target: vector2):
2024-07-04 20:26:48 +02:00
if self.v2tuple(target.__round__()) in self._OAP:
return self._OAP[self.v2tuple(target.__round__())]
2024-07-04 15:23:29 +02:00
else:
return []
2024-07-05 15:27:31 +02:00
def addobj(self, target: obj, physics=True, id=None):
if id == None: temp = self.genid()
else: temp = id
2024-07-04 15:23:29 +02:00
if physics: self._objects[temp] = target
self._visobjects[temp] = target
2024-07-04 20:26:48 +02:00
target.id = temp
2024-07-06 15:21:14 +02:00
target._parent = self._root
self._root.children.append(target)
2024-07-04 15:23:29 +02:00
self.addtooap(target)
2024-07-06 16:32:26 +02:00
def getobjbyid(self, id):
if not id in self._objects: raise TypeError(f"No object with id {id} was found")
return self._objects[id]
2024-07-04 15:23:29 +02:00
def removeobj(self, target: obj):
2024-07-06 16:32:26 +02:00
if target.id in self._visobjects: self._visobjects.pop(target.id)
if target.id in self._objects: self._objects.pop(target.id)
2024-07-04 15:23:29 +02:00
self.remfromoap(target)
def distance(self, pos1, pos2):
return math.dist(((pos1.x, pos1.y), (pos2.x, pos2.y)))
def getcolliding(self, target):
return self.getfromoap(target.position)
2024-07-04 20:26:48 +02:00
def handlecollision(self, obj1: obj, obj2: obj):
#False is blocked
#True is not blocked
#returns tuple like this (True, True)
xblock = False
yblock = False
obj1pos = obj1.position.__round__()
obj2pos = obj2.position.__round__()
if obj2.collide == False: return (xblock, yblock)
if obj2pos.x > obj1pos.x > obj2pos.x: xblock = True
if obj2pos.y > obj1pos.y > obj2pos.y: yblock = True
if obj2.anchored == True:
obj1.velocity = vector2()
else:
2024-07-05 15:27:31 +02:00
if xblock: obj1.velocity.x = obj1.velocity.x/2;obj2.velocity.x = obj2.velocity.x/2;obj2.position.x += obj2.velocity.x
if yblock: obj1.velocity.y = obj1.velocity.y/2;obj2.velocity.y = obj2.velocity.y/2;obj2.position.y += obj2.velocity.y
2024-07-04 20:26:48 +02:00
return (xblock, yblock)
def calcphysobj(self, target: obj):
if target.anchored: target.velocity=vector2();return
new = target.position + target.velocity
oldvel = target.velocity.__copy__()
if target.collide == True:
colliding = self.getfromoap(new)
if len(colliding) > 0: target.colliding.execute()
for i in colliding:
if i == target: continue
if i in target.ignorecollision or target in i.ignorecollision: continue
i.colliding.execute()
temp = self.handlecollision(target, i)
if temp[0] == False: target.position.x += oldvel.x
if temp[1] == False: target.position.y += oldvel.y
2024-07-05 15:27:31 +02:00
if len(colliding) <= 1: target.position += target.velocity
2024-07-04 20:26:48 +02:00
else:
target.position += target.velocity
target.velocity += target.acceleration
self.updateobjinoap(target)
2024-07-05 15:27:31 +02:00
def updallobjpositions(self):
self._OAPUPDATING = True
for i in self._visobjects.values():
try:
self.updateobjinoap(i)
except Exception as e:
pass
self._OAPUPDATING = False
2024-07-04 20:26:48 +02:00
def render(self):
2024-07-05 15:27:31 +02:00
if self._OAPUPDATING == False: threading.Thread(target=self.updallobjpositions).start()
2024-07-04 20:26:48 +02:00
self._canvas.delete(tk.ALL)
2024-07-06 16:32:26 +02:00
self._height = int(self._canvas.winfo_reqheight()/self._camera.zoom)
self._width = int(self._canvas.winfo_reqwidth()/self._camera.zoom)
2024-07-04 20:26:48 +02:00
self._pixelsize = self._camera.zoom
2024-07-06 16:32:26 +02:00
#for y in range(self._camera.position.y, self._height+self._camera.position.y):
#for x in range(self._camera.position.x, self._width+self._camera.position.x):
for y in range(self._height):
for x in range(self._width):
obj = self.getfromoap(vector2(x+self._camera.position.x, y+self._camera.position.y))
2024-07-04 20:26:48 +02:00
if len(obj) == 0: continue
obj = obj[0]
self._canvas.create_rectangle(x*self._pixelsize, y*self._pixelsize, x*self._pixelsize+self._pixelsize, y*self._pixelsize+self._pixelsize, fill=obj.color.__tohex__(), width=0)
def updobjs(self):
2024-07-05 15:27:31 +02:00
start = time.time()
2024-07-04 20:26:48 +02:00
for i in self._objects.values():
self.calcphysobj(i)
2024-07-05 15:27:31 +02:00
return time.time()-start
2024-07-04 15:23:29 +02:00
2024-07-06 15:21:14 +02:00
def savegame(self):
print("pickling root...")
outobjects = pickle.dumps(self._root)
print("copying scripts...")
outscripts = []
TLB = loadbar(20, len(self._scripts))
for i in self._scripts:
outscripts.append(i)
TLB.current += 1
TLB.render()
print("encoding sounds...")
outsounds = []
TLB = loadbar(20, len(self._handler.storage))
for i in self._handler.storage:
outsounds.append(self._handler.tostring(i))
TLB.current += 1
TLB.render()
return {"obj": outobjects, "scripts": outscripts, "sounds": outsounds}
def readdobj(self, target, TLB):
TLB.repeat += len(target)
TLB.steps = TLB.repeat/TLB.length
for i in target.copy():
self.addobj(i, True, i.id)
if len(i.children) > 0: self.readdobj(i.children, TLB)
TLB.current += 1
TLB.render()
2024-07-07 12:27:18 +02:00
def isdown(self, key):
temp = self._keyboard.getkeys()
if key in temp:
return temp[key]
2024-07-06 15:21:14 +02:00
def loadgame(self, target):
print("loading objects...")
self._root = pickle.loads(target["obj"])
print("loading scripts...")
self._scripts = []
TLB = loadbar(20, len(target["scripts"]))
for i in target["scripts"]:
self._scripts.append(i)
TLB.current += 1
TLB.render()
print()
print("loading sounds...")
self._handler.storage = {}
TLB = loadbar(20, len(target["sounds"]))
for i in target["sounds"]:
self._handler.loadfromstring(i)
TLB.current += 1
TLB.render()
print("readding objects...")
self._OAP = {}
self._objects = {}
self._visobjects = {}
TLB = loadbar(20, 0)
self.readdobj(self._root.children, TLB)
2024-07-07 12:27:18 +02:00
def APIGEN(self):
API = {}
API["HASHGAME"] = self
API["vector2"] = vector2
API["color3"] = color3
API["event"] = event
API["NULL"] = NULL
API["obj"] = obj
API["SOUND"] = self._handler
return API
def rungame(self):
# yields forever
print("preparing scripts")
for i in self._scripts:
self._threads.append(threading.Thread(target=lambda i: exec(i, self.APIGEN())))
print("starting scripts")
for i in self._threads:
i.start()
print("starting loop")
while True:
took = self.updallobjpositions()
self.render()
took = 0.1-took
if took > 0:
time.sleep(took)
2024-07-04 15:23:29 +02:00
if not "__CMD__" in globals():
2024-07-07 12:27:18 +02:00
from PIL import Image
2024-07-06 15:21:14 +02:00
from tkinter import filedialog
2024-07-04 15:23:29 +02:00
root = tk.Tk()
canvas = tk.Canvas(root)
canvas.grid()
temp = game(canvas)
2024-07-06 15:21:14 +02:00
tempimg = Image.open(filedialog.askopenfilename())
tempimg = tempimg.resize((temp._width, temp._height))
for y in range(temp._height):
for x in range(temp._width):
tempobj = obj()
tempobj.position = vector2(x, y)
tempcolor = tempimg.getpixel((x, y))
tempobj.color = color3(tempcolor[0], tempcolor[1], tempcolor[2])
temp.addobj(tempobj)
print(f"{y}/{temp._height}", end="\r", flush=True)
tempstate = temp.savegame()
print("resetting...")
temp.__init__(canvas)
input("press enter to reload state")
print("loading...")
temp.loadgame(tempstate)
temp.render()
root.update()
print()
2024-07-07 12:27:18 +02:00
input("press enter to exit.")
"""root = tk.Tk()
2024-07-06 16:32:26 +02:00
canvas = tk.Canvas(root)
canvas.grid()
temp = game(canvas)
temp._camera.position.x = -5
temp._camera.position.y = -10
pathfind = pathfinding(temp)
start = obj()
start.position = vector2(-3, -3)
start.color = color3(0, 255)
temp.addobj(start)
goal = obj()
goal.position = vector2(50, 80)
goal.color = color3(255)
temp.addobj(goal)
tempobjlist = []
out = pathfind.find_path(start.position, goal.position)
for i in out:
tempobj = obj()
tempobj.position = i
tempobjlist.append(tempobj)
temp.addobj(tempobj)
for i in range(50):
goal.position.y -= 1
for i in tempobjlist:
temp.removeobj(i)
#temp.updallobjpositions()
out = pathfind.find_path(start.position, goal.position)
for i in out:
tempobj = obj()
tempobj.position = i
temp.addobj(tempobj)
tempobjlist.append(tempobj)
temp.render()
root.update()
2024-07-07 12:27:18 +02:00
input("press enter to exit.")"""
2024-07-06 16:32:26 +02:00