366 lines
12 KiB
Python
366 lines
12 KiB
Python
import mtTkinter as tk
|
|
from HEMD import color3, vector2, event, NULL
|
|
import audiosys
|
|
from loadbar import loadbar
|
|
import random
|
|
import string
|
|
import math
|
|
import time
|
|
import threading
|
|
import pickle
|
|
from pathfinding import pathfinding
|
|
from keyboard import keyboard
|
|
#import itertools
|
|
#import multiprocessing
|
|
|
|
# designated graphics size pixel 5x5
|
|
|
|
__VERSION__ = "HE2.3-HASHENGINE-2.3"
|
|
|
|
class obj:
|
|
def __init__(self):
|
|
self.position = vector2()
|
|
self.collide = True
|
|
self.anchored = True
|
|
self.velocity = vector2()
|
|
self.acceleration = vector2()
|
|
self.id = NULL()
|
|
self.color = color3()
|
|
self.colliding = event()
|
|
self._parent = NULL()
|
|
self.children = []
|
|
self.ignorecollision = []
|
|
|
|
@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)
|
|
|
|
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)
|
|
|
|
class game:
|
|
def __init__(self, canvas: tk.Canvas, pixelsize=3):
|
|
self._canvas = canvas
|
|
self._height = int(canvas.winfo_reqheight()/pixelsize)
|
|
self._width = int(canvas.winfo_reqwidth()/pixelsize)
|
|
self._pixelsize = pixelsize
|
|
self._OAP = {}
|
|
self._objects = {}
|
|
self._visobjects = {}
|
|
self._camera = obj()
|
|
self._camera.zoom = pixelsize
|
|
self._OAPUPDATING = False
|
|
self._handler = audiosys.handler()
|
|
self._threads = []
|
|
self._root = obj()
|
|
self._scripts = []
|
|
self._keyboard = keyboard(self._canvas)
|
|
"""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()
|
|
self._workers.append({"process": temp, ""})""" # scraped idea, im keeping it in incase i ever decide to use it
|
|
|
|
def genid(self):
|
|
out = ""
|
|
for i in range(255):
|
|
out = out + random.choice(list(string.ascii_letters))
|
|
return out
|
|
|
|
def v2tuple(self, target: vector2):
|
|
return (target.x, target.y)
|
|
|
|
def tuple2v(self, target: tuple):
|
|
return vector2(target[0], target[1])
|
|
|
|
def addtooap(self, target: obj):
|
|
if self.v2tuple(target.position.__round__()) in self._OAP:
|
|
self._OAP[self.v2tuple(target.position.__round__())].append(target)
|
|
else:
|
|
self._OAP[self.v2tuple(target.position.__round__())] = [target]
|
|
|
|
def updateobjinoap(self, target: obj):
|
|
self.remfromoap(target)
|
|
self.addtooap(target)
|
|
|
|
def remfromoap(self, target: obj):
|
|
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
|
|
|
|
def getfromoap(self, target: vector2):
|
|
if self.v2tuple(target.__round__()) in self._OAP:
|
|
return self._OAP[self.v2tuple(target.__round__())]
|
|
else:
|
|
return []
|
|
|
|
def addobj(self, target: obj, physics=True, id=None):
|
|
if id == None: temp = self.genid()
|
|
else: temp = id
|
|
if physics: self._objects[temp] = target
|
|
self._visobjects[temp] = target
|
|
target.id = temp
|
|
target._parent = self._root
|
|
self._root.children.append(target)
|
|
self.addtooap(target)
|
|
|
|
def getobjbyid(self, id):
|
|
if not id in self._objects: raise TypeError(f"No object with id {id} was found")
|
|
return self._objects[id]
|
|
|
|
def removeobj(self, target: obj):
|
|
if target.id in self._visobjects: self._visobjects.pop(target.id)
|
|
if target.id in self._objects: self._objects.pop(target.id)
|
|
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)
|
|
|
|
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:
|
|
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
|
|
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
|
|
if len(colliding) <= 1: target.position += target.velocity
|
|
else:
|
|
target.position += target.velocity
|
|
target.velocity += target.acceleration
|
|
self.updateobjinoap(target)
|
|
|
|
def updallobjpositions(self):
|
|
self._OAPUPDATING = True
|
|
for i in self._visobjects.values():
|
|
try:
|
|
self.updateobjinoap(i)
|
|
except Exception as e:
|
|
pass
|
|
self._OAPUPDATING = False
|
|
|
|
def render(self):
|
|
if self._OAPUPDATING == False: threading.Thread(target=self.updallobjpositions).start()
|
|
self._canvas.delete(tk.ALL)
|
|
self._height = int(self._canvas.winfo_reqheight()/self._camera.zoom)
|
|
self._width = int(self._canvas.winfo_reqwidth()/self._camera.zoom)
|
|
self._pixelsize = self._camera.zoom
|
|
#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))
|
|
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):
|
|
start = time.time()
|
|
for i in self._objects.values():
|
|
self.calcphysobj(i)
|
|
return time.time()-start
|
|
|
|
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()
|
|
|
|
def isdown(self, key):
|
|
temp = self._keyboard.getkeys()
|
|
if key in temp:
|
|
return temp[key]
|
|
|
|
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)
|
|
|
|
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)
|
|
|
|
if not "__CMD__" in globals():
|
|
from PIL import Image
|
|
from tkinter import filedialog
|
|
root = tk.Tk()
|
|
canvas = tk.Canvas(root)
|
|
canvas.grid()
|
|
temp = game(canvas)
|
|
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()
|
|
input("press enter to exit.")
|
|
"""root = tk.Tk()
|
|
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()
|
|
input("press enter to exit.")"""
|
|
|