added pathfinding

This commit is contained in:
Justus Jan Nico Wolff 2024-07-06 16:32:26 +02:00
parent dd85d592e1
commit 1b1c170d6b
2 changed files with 131 additions and 10 deletions

View file

@ -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.")
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.")

78
pathfinding.py Normal file
View file

@ -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 []