pathfinding
parent
9502ee247e
commit
7c8e354103
|
@ -6,6 +6,7 @@ import time
|
||||||
import wave
|
import wave
|
||||||
import os
|
import os
|
||||||
import math
|
import math
|
||||||
|
import heapq
|
||||||
|
|
||||||
class stdrend:
|
class stdrend:
|
||||||
def __init__(self, size, cam):
|
def __init__(self, size, cam):
|
||||||
|
@ -151,7 +152,7 @@ def loadsound(path):
|
||||||
frames = fd.readframes(1000000000)
|
frames = fd.readframes(1000000000)
|
||||||
return frames
|
return frames
|
||||||
|
|
||||||
cammode = enum({"editable": 0, "follow": 1})
|
cammode = enum({"editable": 0, "follow": 1, "freecam": 2})
|
||||||
|
|
||||||
class event:
|
class event:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -197,9 +198,20 @@ class camera(obj):
|
||||||
self.touch = False
|
self.touch = False
|
||||||
self.char = " "
|
self.char = " "
|
||||||
|
|
||||||
def update(self):
|
def update(self, game):
|
||||||
|
"""
|
||||||
|
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)
|
||||||
|
"""
|
||||||
if self.mode == cammode.follow and self.subject:
|
if self.mode == cammode.follow and self.subject:
|
||||||
self.position = self.subject.position
|
self.position = self.subject.position
|
||||||
|
if self.mode == cammode.freecam:
|
||||||
|
if game.isdown("w"): self.position += vector2(y=1)
|
||||||
|
if game.isdown("s"): self.position -= vector2(y=1)
|
||||||
|
if game.isdown("a"): self.position += vector2(x=1)
|
||||||
|
if game.isdown("d"): self.position -= vector2(x=1)
|
||||||
|
|
||||||
class seqobj:
|
class seqobj:
|
||||||
def __init__(self, objects):
|
def __init__(self, objects):
|
||||||
|
@ -334,6 +346,7 @@ class game:
|
||||||
for y in range(self._size[1]):
|
for y in range(self._size[1]):
|
||||||
tochange.append((x, y))
|
tochange.append((x, y))
|
||||||
#self._renderer.pix(x, y, " ", color3(255, 255, 255), color3(255, 255, 255))
|
#self._renderer.pix(x, y, " ", color3(255, 255, 255), color3(255, 255, 255))
|
||||||
|
self.camera.update(self)
|
||||||
for i in list(self._objects.values()):
|
for i in list(self._objects.values()):
|
||||||
if isinstance(i, obj):
|
if isinstance(i, obj):
|
||||||
pos = i.position + self.camera.position
|
pos = i.position + self.camera.position
|
||||||
|
@ -365,6 +378,80 @@ class game:
|
||||||
for i in self.currentsounds:
|
for i in self.currentsounds:
|
||||||
i.stop()
|
i.stop()
|
||||||
|
|
||||||
|
class pathfinding:
|
||||||
|
def __init__(self, grid_size, objects, game):
|
||||||
|
self.grid_size = grid_size
|
||||||
|
self.objects = objects
|
||||||
|
self._calculate_bounds()
|
||||||
|
self.grid = [[1 for _ in range(self.grid_width)] for _ in range(self.grid_height)]
|
||||||
|
self.game = game
|
||||||
|
self._init_grid()
|
||||||
|
|
||||||
|
def _init_grid(self):
|
||||||
|
for obj in self.objects:
|
||||||
|
if obj.collide:
|
||||||
|
x, y = int(obj.position.x) + self.offset_x, int(obj.position.y) + self.offset_y
|
||||||
|
if 0 <= x < self.grid_width and 0 <= y < self.grid_height:
|
||||||
|
self.grid[y][x] = 0
|
||||||
|
|
||||||
|
def _calculate_bounds(self):
|
||||||
|
min_x, max_x = 0, self.grid_size[0]
|
||||||
|
min_y, max_y = 0, self.grid_size[1]
|
||||||
|
for obj in self.objects:
|
||||||
|
if obj.collide:
|
||||||
|
min_x = min(min_x, int(obj.position.x))
|
||||||
|
max_x = max(max_x, int(obj.position.x))
|
||||||
|
min_y = min(min_y, int(obj.position.y))
|
||||||
|
max_y = max(max_y, int(obj.position.y))
|
||||||
|
self.grid_width = max_x - min_x + 1
|
||||||
|
self.grid_height = max_y - min_y + 1
|
||||||
|
self.offset_x = -min_x
|
||||||
|
self.offset_y = -min_y
|
||||||
|
|
||||||
|
def _heuristic(self, a, b):
|
||||||
|
return abs(a[0] - b[0]) + abs(a[1] - b[1])
|
||||||
|
|
||||||
|
def find_path(self, start, end):
|
||||||
|
self.objects = list(self.game._objects.values())
|
||||||
|
self._calculate_bounds()
|
||||||
|
self._init_grid()
|
||||||
|
start = (int(start.x) + self.offset_x, int(start.y) + self.offset_y)
|
||||||
|
end = (int(end.x) + self.offset_x, int(end.y) + self.offset_y)
|
||||||
|
open_set = []
|
||||||
|
heapq.heappush(open_set, (0, start))
|
||||||
|
came_from = {}
|
||||||
|
g_score = {start: 0}
|
||||||
|
f_score = {start: self._heuristic(start, end)}
|
||||||
|
while open_set:
|
||||||
|
_, current = heapq.heappop(open_set)
|
||||||
|
if math.dist(end, current) <= 1:
|
||||||
|
path = []
|
||||||
|
while current in came_from:
|
||||||
|
path.append(current)
|
||||||
|
current = came_from[current]
|
||||||
|
path.append(start)
|
||||||
|
path.reverse()
|
||||||
|
return [vector2(x - self.offset_x, y - self.offset_y) for x, y in path]
|
||||||
|
|
||||||
|
neighbors = [
|
||||||
|
(current[0] + dx, current[1] + dy)
|
||||||
|
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]
|
||||||
|
if 0 <= current[0] + dx < self.grid_width and 0 <= current[1] + dy < self.grid_height
|
||||||
|
]
|
||||||
|
|
||||||
|
for neighbor in neighbors:
|
||||||
|
if self.grid[neighbor[1]][neighbor[0]] == 0:
|
||||||
|
continue
|
||||||
|
tentative_g_score = g_score[current] + 1
|
||||||
|
|
||||||
|
if neighbor not in g_score or tentative_g_score < g_score[neighbor]:
|
||||||
|
came_from[neighbor] = current
|
||||||
|
g_score[neighbor] = tentative_g_score
|
||||||
|
f_score[neighbor] = tentative_g_score + self._heuristic(neighbor, end)
|
||||||
|
heapq.heappush(open_set, (f_score[neighbor], neighbor))
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
testgame = game(sounddir="testsound")
|
testgame = game(sounddir="testsound")
|
||||||
object = obj()
|
object = obj()
|
||||||
|
|
23
main.py
23
main.py
|
@ -476,10 +476,11 @@ def halatribute(event):
|
||||||
setattr(gamedata[currentobj]["args"][parent], name, new)
|
setattr(gamedata[currentobj]["args"][parent], name, new)
|
||||||
if "ID" in gamedata[currentobj]["args"]:
|
if "ID" in gamedata[currentobj]["args"]:
|
||||||
temp = preview.getobjbyid(gamedata[currentobj]["args"]["ID"])
|
temp = preview.getobjbyid(gamedata[currentobj]["args"]["ID"])
|
||||||
setattr(temp, name, new)
|
setattr(getattr(temp, parent), name, new)
|
||||||
atritree.delete(*atritree.get_children())
|
atritree.delete(*atritree.get_children())
|
||||||
objtree.focus("")
|
objtree.focus("")
|
||||||
updselect(None)
|
updselect(None)
|
||||||
|
preview.render()
|
||||||
|
|
||||||
def updatepreviewcam(char):
|
def updatepreviewcam(char):
|
||||||
global cooldown
|
global cooldown
|
||||||
|
@ -707,9 +708,11 @@ def testing():
|
||||||
|
|
||||||
def APIGEN():
|
def APIGEN():
|
||||||
global APIPLUG
|
global APIPLUG
|
||||||
|
global maingame
|
||||||
API = {"print": log, "HASHBASE": hashengine}
|
API = {"print": log, "HASHBASE": hashengine}
|
||||||
API["HASHGAME"] = maingame
|
API["HASHGAME"] = maingame
|
||||||
API["SOUND"] = lambda data: gsound(data, maingame)
|
API["SOUND"] = lambda data: gsound(data, maingame)
|
||||||
|
API["PATHFIND"] = hashengine.pathfinding(maingame._size, list(maingame._objects.values()), maingame)
|
||||||
for i in APIPLUG:
|
for i in APIPLUG:
|
||||||
exec(i, globals())
|
exec(i, globals())
|
||||||
temp = globals()["PLUGINAPIFUNC"]()
|
temp = globals()["PLUGINAPIFUNC"]()
|
||||||
|
@ -1083,7 +1086,6 @@ def GUIinit():
|
||||||
menu.add_cascade(label=LH.string("langs"), menu=langmenu)
|
menu.add_cascade(label=LH.string("langs"), menu=langmenu)
|
||||||
for i in LH.getlangs():
|
for i in LH.getlangs():
|
||||||
langmenu.add_command(label=i, command=lambda i=i: selectlang(i))
|
langmenu.add_command(label=i, command=lambda i=i: selectlang(i))
|
||||||
loadplugins()
|
|
||||||
container.mainloop()
|
container.mainloop()
|
||||||
|
|
||||||
# attribute changers
|
# attribute changers
|
||||||
|
@ -1163,6 +1165,7 @@ def aposx(old):
|
||||||
for i in str(tempvar):
|
for i in str(tempvar):
|
||||||
if not i in numbers:
|
if not i in numbers:
|
||||||
return old
|
return old
|
||||||
|
if str(tempvar).split(".")[1] == "0": return int(tempvar)
|
||||||
return tempvar
|
return tempvar
|
||||||
|
|
||||||
def aposy(old):
|
def aposy(old):
|
||||||
|
@ -1190,6 +1193,7 @@ def aposy(old):
|
||||||
for i in str(tempvar):
|
for i in str(tempvar):
|
||||||
if not i in numbers:
|
if not i in numbers:
|
||||||
return old
|
return old
|
||||||
|
if str(tempvar).split(".")[1] == "0": return int(tempvar)
|
||||||
return tempvar
|
return tempvar
|
||||||
|
|
||||||
def execgame(gametree, shouldlog=True, fAPIPLUG=[], fRUNPLUG=[]):
|
def execgame(gametree, shouldlog=True, fAPIPLUG=[], fRUNPLUG=[]):
|
||||||
|
@ -1208,15 +1212,22 @@ def execgame(gametree, shouldlog=True, fAPIPLUG=[], fRUNPLUG=[]):
|
||||||
clog = shouldlog
|
clog = shouldlog
|
||||||
run()
|
run()
|
||||||
|
|
||||||
|
def execcmd(target):
|
||||||
|
try:
|
||||||
|
exec(target, globals())
|
||||||
|
except Exception as e:
|
||||||
|
return e
|
||||||
|
|
||||||
def cmd():
|
def cmd():
|
||||||
print(f"hashengine version: {version}")
|
print(f"hashengine version: {version}")
|
||||||
print("CMD")
|
print("CMD")
|
||||||
|
autoexecute = ["loadplugins()"]
|
||||||
|
for i in autoexecute:
|
||||||
|
print(f"> {i}")
|
||||||
|
execcmd(i)
|
||||||
while True:
|
while True:
|
||||||
cmd = input("> ")
|
cmd = input("> ")
|
||||||
try:
|
print(execcmd(cmd))
|
||||||
exec(cmd, globals())
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
class rsound:
|
class rsound:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
@ -70,3 +70,10 @@ Hashengine supports audio playback. As previously said, HASHBASE.loadsound(\<PAT
|
||||||
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 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()
|
to stop the sound use \<sound>.stop() and to yield until the sound is done playing sue \<sound>.wait()
|
||||||
|
|
||||||
|
## PATHFIND
|
||||||
|
|
||||||
|
### Hashengine provides you with built-in pathfinding
|
||||||
|
|
||||||
|
Hashengine has an built pathfinding system (A*). to use it, use PATHFIND.find_path(\<start vector2>, \<end vector2>).
|
||||||
|
it returns an list of vector2's representing every single waypoint.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
B #
|
||||||
|
#
|
||||||
|
#
|
||||||
|
A
|
|
@ -0,0 +1 @@
|
||||||
|
[[{'id': 'obj', 'name': 'B', 'SID': 'TqykIpLtCKwtqAdSrksOjKtUmNXVMkXPEnNKVYAjnCbhDGwNbiefXdeJhMxBeNOTWfRCHZWOtdMxmHlcCDPdEXOzGmhuXTQyaVywRqwWOxdVioLSUAZkpivegeBalvtkgfVkIVlaJUGJLHLiOCdncxyNGkciReWUntWGjfQTuIeZSGwWtpakiQQgCZCFpkPUUWYlvLNADLvmCOzKwGQCIMnaVavcHYDEhJStHnzPlYIgASEBDMywrmZeUxtrOlO', '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': 0, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': '#', 'SID': 'TZIeEulKFDdSyFercdukmdlaWqXJtxCNsYUJRehtpqWXtqNrCRIQppHJlLHYlxmOfzSJwjGOMFhOGWFRybutzbfWmxBuuThfZKRaeHqqqdocjkfPxfBVZsqZFTgKYQXcUXtXpXnkSUYZqGZGztgeuOJXyKwTJTLaGMtMfvXmmNXviOlnmBlTbdzgZQoJLTPJqTkmavOKepbCcrzcjDUuCZpfnOaTuehRnyPHFcXbiPIOFRmsqpWfXKwWzREsfyV', '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': 5, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': '#', 'SID': 'HtBTelOcoHVYzWzpvfwphPDTJCUQgZjmOXomRObTJkhMuefWHbCZPQWSeaGZOcbWXknUYaerTNDmsNOhwAOQZJpHxwrAwtBbyLWuQwggXUXKgWDyUzCNaMLeVaWDEIXRXdWVxmRObSotLnIUDfqByenIsHpitNcMWXCqGpLTzApWHKzhMfIoFoswtqrPydSOOqAWXWLyVhNlhIPjqTUqOyxhBtxJoouAZWfsLBriRwCYQJIsPmFUsWTEZLUzqJi', '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': 5, 'y': 1, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': '#', 'SID': 'rpmRdCpAZzcbSvkgQKCOzzeUnFahtWUVmoEJuXVlVejBTMumOrRRLDLjnpuMkkoztSOaLTVGGEgYzTdAJJXcwfJPXemlENOQFlItDHRojMUmZAlPeCdawyaLqkhHPJPJRVUZCHQOJYlixucjpuqyhcorIUKnzxNYWdQSCIOyHHOIyHMAzZEQLrlwBsCgKAXwTMhNqNXGAEscABPlgvULVegLIbqdVRlQAiQTMbhArjOGxtJhBORsAIUDkrRrViz', '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': 5, 'y': 2, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': 'A', 'SID': 'kZbEQPYcJFNelliPHswwvvDVeiYGLXYeYvAGHdmDmxdIAFqWlkAFPxNCBlVRXgofJIaBBQaOMUHcnAyFmsHaorUhFIlblXHSdLFsRtLWmkMpPnBmpHrJZhkNCmNEvaZdCtNWnbJfAWdaFOlfHSYNIbenaNQhLXUntneNdMIlpEgWrCVhaOimAcXRDtMwusYibgkCZIIPLnsHtXWcSjjskdzylorzBNCNOJwnLqFLkDLbbeiaoKcqhfdsdMwPNzn', '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': -2, 'y': -2, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'script', 'name': 'Skript', 'SID': 'jjlcqqosdzDsDAjdUlAzeudsNiDEfggOTzGZZdhYPUtMzWPDEnsAgaOpiEeZofjivwPOkkLejUqHRJzIaUwdcNCkeuoEzRyMsLLxoIzzAJbWxlNIcmayhgZDTPAHAEKalgBYizLaxhXISElzdxcaJdoqfAgHJGDkRlvpPPNHoTnizOrVUNcnVpEncJUuOwBevnNRoHhptbJoKRHHsINkJXtkGxIrOVBObXGHlEbXQKyJKSisqvedYtazodZoXUJ', 'args': {'code': 'start = HASHGAME.getobjbySID("TqykIpLtCKwtqAdSrksOjKtUmNXVMkXPEnNKVYAjnCbhDGwNbiefXdeJhMxBeNOTWfRCHZWOtdMxmHlcCDPdEXOzGmhuXTQyaVywRqwWOxdVioLSUAZkpivegeBalvtkgfVkIVlaJUGJLHLiOCdncxyNGkciReWUntWGjfQTuIeZSGwWtpakiQQgCZCFpkPUUWYlvLNADLvmCOzKwGQCIMnaVavcHYDEhJStHnzPlYIgASEBDMywrmZeUxtrOlO")\nend = HASHGAME.getobjbySID("kZbEQPYcJFNelliPHswwvvDVeiYGLXYeYvAGHdmDmxdIAFqWlkAFPxNCBlVRXgofJIaBBQaOMUHcnAyFmsHaorUhFIlblXHSdLFsRtLWmkMpPnBmpHrJZhkNCmNEvaZdCtNWnbJfAWdaFOlfHSYNIbenaNQhLXUntneNdMIlpEgWrCVhaOimAcXRDtMwusYibgkCZIIPLnsHtXWcSjjskdzylorzBNCNOJwnLqFLkDLbbeiaoKcqhfdsdMwPNzn")\nHASHGAME.camera.mode = 2\npath = PATHFIND.find_path(start.position, end.position)\nfor i in path:\n\ttemp = HASHBASE.obj()\n\ttemp.position = i\n\ttemp.char = "-"\n\ttemp.anchored = True\n\tHASHGAME.addobj(temp)'}}], {'Erstellte Objekte': [0, 1, 2, 3, 4]}, 10, 10]
|
Loading…
Reference in New Issue