diff --git a/hashengine.py b/hashengine.py index dd5ce9a..70ac123 100644 --- a/hashengine.py +++ b/hashengine.py @@ -8,6 +8,7 @@ import math import time import threading import pickle +from pathfinding import pathfinding #import itertools #import multiprocessing @@ -49,7 +50,6 @@ class game: self._objects = {} self._visobjects = {} self._camera = obj() - self._camera.position = vector2() self._camera.zoom = pixelsize self._OAPUPDATING = False self._handler = audiosys.handler() @@ -113,9 +113,13 @@ class game: 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 in self._visobjects: self._visobjects.pop(target) - if target in self._objects: self._objects.pop(target) + 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): @@ -174,12 +178,14 @@ class game: def render(self): if self._OAPUPDATING == False: threading.Thread(target=self.updallobjpositions).start() self._canvas.delete(tk.ALL) - self._height = int(canvas.winfo_reqheight()/self._camera.zoom) - self._width = int(canvas.winfo_reqwidth()/self._camera.zoom) + 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.y, self._width+self._camera.position.y): - obj = self.getfromoap(vector2(x, y)) + #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) @@ -244,7 +250,7 @@ class game: self.readdobj(self._root.children, TLB) if not "__CMD__" in globals(): - from PIL import Image + """from PIL import Image from tkinter import filedialog root = tk.Tk() canvas = tk.Canvas(root) @@ -269,4 +275,41 @@ if not "__CMD__" in globals(): temp.render() root.update() print() - input("press enter to exit.") \ No newline at end of file + 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.") + diff --git a/pathfinding.py b/pathfinding.py new file mode 100644 index 0000000..64f46b8 --- /dev/null +++ b/pathfinding.py @@ -0,0 +1,78 @@ +import heapq +from HEMD import vector2 +import math + +class pathfinding: + def __init__(self, game): + self.grid_size = [game._width, game._height] + self.objects = list(game._visobjects.values()) + 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._visobjects.values()) + self._calculate_bounds() + self.grid = [[1 for _ in range(self.grid_width)] for _ in range(self.grid_height)] + 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 []