class TxtLevelLoader(LevelLoader): """Implementuje tekstowy format mapy gry.""" def load(self, file_name): # vr <version> # pp <width> <height> # ts <file_name> # os <file_name> # t <x> <y> <flags> <tile_sprite> # s <x> <y> <t> <static_sprite> # d <class_name> <x> <y> self._dynamic_objects = [] file = open(file_name, "r") for line in file.readlines(): if line.startswith("pp"): self._terrain_grid = TerrainGrid() self._static_objects = StaticObjects() width, height = int(line.split()[1].strip()), int( line.split()[2].strip()) self._terrain_grid.set_size(vec2(width, height)) self._static_objects.set_size(vec2(width, height)) elif line.startswith("ts"): self._terrain_grid_sprites.append( TileSprite(line.split()[1].strip())) elif line.startswith("os"): self._static_object_sprites.append( ObjectSprite(line.split()[1].strip())) elif line.startswith("t"): split = [x.strip() for x in line.split()] position = vec2(int(split[1]), int(split[2])) flags, sprite = split[3] == "True", int(split[4]) self._terrain_grid.set_tile(position, self._terrain_grid_sprites[sprite]) self._terrain_grid.set_flags(position, flags) elif line.startswith("s"): split = [x.strip() for x in line.split()] position = vec2(int(split[1]) * 0.01, int(split[2]) * 0.01) num_frame = int(split[3]) sprite = int(split[4]) sector = (position / SECTOR_SIZE).floor() self._static_objects.get_sector( vec2(int(position.x), int(position.y)) // SECTOR_SIZE).append((position, num_frame, self._static_object_sprites[sprite])) elif line.startswith("d"): split = [x.strip() for x in line.split()] class_name = split[1] position = vec2(int(split[2]) * 0.01, int(split[3]) * 0.01) object = eval(class_name + "()") object.set_position(position) self._dynamic_objects.append(object) def save(self, file_name): terrain_grid_sprites = dict() for i in range(len(self._terrain_grid_sprites)): terrain_grid_sprites[ self._terrain_grid_sprites[i].get_file_name()] = i static_objects_sprites = dict() for i in range(len(self._static_object_sprites)): static_objects_sprites[self._static_object_sprites[i]] = i file = open(file_name, "w+") file.write("RapingOrcsWithGreatMagic v0.1\n") file.write("pp " + str(self._terrain_grid.get_size().x) + " " + str(self._terrain_grid.get_size().x) + "\n") for x in self._terrain_grid_sprites: file.write("ts " + x.get_file_name() + "\n") for x in self._static_object_sprites: file.write("os " + x.get_file_name() + "\n") for v in area(self._terrain_grid.get_size()): flags = self._terrain_grid.get_flags(v) sprite = self._terrain_grid.get_tile(v) file.write("t " + str(v.x) + " " + str(v.y) + " " + str(flags) + " " + str(terrain_grid_sprites[sprite.get_file_name()]) + "\n") for o in self._dynamic_objects: position = o.get_position() class_name = o.__class__.__name__ x = str(floor(position.x * 100)) y = str(floor(position.y * 100)) file.write("d " + class_name + " " + x + " " + y + "\n") size_in_sectors = self._static_objects.get_size() for y in range(size_in_sectors.y): for x in range(size_in_sectors.x): for i in self._static_objects.get_sector(vec2(x, y)): xp = str(floor(i[0].x * 100)) yp = str(floor(i[0].y * 100)) rt = str(i[1]) sprite = str(static_objects_sprites[i[2]]) file.write("s " + xp + " " + yp + " " + rt + " " + sprite + "\n")
class TxtLevelLoader(LevelLoader): def load(self, file_name): # vr <version> # pp <width> <height> # ts <file_name> # os <file_name> # t <x> <y> <flags> <tile_sprite> # s <x> <y> <t> <static_sprite> # d <class_name> <x> <y> self._dynamic_objects = [] file = open(file_name, "r") for line in file.readlines(): if line.startswith("pp"): self._terrain_grid = TerrainGrid() self._static_objects = StaticObjects() width, height = int(line.split()[1].strip()), int(line.split()[2].strip()) self._terrain_grid.set_size(vec2(width, height)) self._static_objects.set_size(vec2(width, height)) elif line.startswith("ts"): self._terrain_grid_sprites.append(TileSprite(line.split()[1].strip())) elif line.startswith("os"): self._static_object_sprites.append(ObjectSprite(line.split()[1].strip())) elif line.startswith("t"): split = [x.strip() for x in line.split()] position = vec2(int(split[1]), int(split[2])) flags, sprite = split[3] == "True", int(split[4]) self._terrain_grid.set_tile(position, self._terrain_grid_sprites[sprite]) self._terrain_grid.set_flags(position, flags) elif line.startswith("s"): split = [x.strip() for x in line.split()] position = vec2(int(split[1]) * 0.01, int(split[2]) * 0.01) num_frame = int(split[3]) sprite = int(split[4]) sector = (position / SECTOR_SIZE).floor() self._static_objects.get_sector(vec2(int(position.x), int(position.y)) // SECTOR_SIZE).append((position, num_frame, self._static_object_sprites[sprite])) elif line.startswith("d"): split = [x.strip() for x in line.split()] class_name = split[1] position = vec2(int(split[2]) * 0.01, int(split[3]) * 0.01) object = eval(class_name + "()") object.set_position(position) self._dynamic_objects.append(object) def save(self, file_name): terrain_grid_sprites = dict() for i in range(len(self._terrain_grid_sprites)): terrain_grid_sprites[self._terrain_grid_sprites[i]] = i static_objects_sprites = dict() for i in range(len(self._static_object_sprites)): static_objects_sprites[self._static_object_sprites[i]] = i file = open(file_name, "w+") file.write("RapingOrcsWithGreatMagic v0.1\n") file.write("pp " + str(self._terrain_grid.get_size().x) + " " + str(self._terrain_grid.get_size().x) + "\n") for x in self._terrain_grid_sprites: file.write("ts " + x.get_file_name() + "\n") for x in self._static_object_sprites: file.write("os " + x.get_file_name() + "\n") for v in area(self._terrain_grid.get_size()): flags = self._terrain_grid.get_flags(v) sprite = self._terrain_grid.get_tile(v) file.write("t " + str(v.x) + " " + str(v.y) + " " + str(flags) + " " + str(terrain_grid_sprites[sprite]) + "\n") for o in self._dynamic_objects: position = o.get_position() class_name = o.__class__.__name__ x = str(floor(position.x * 100)) y = str(floor(position.y * 100)) file.write("d " + class_name + " " + x + " " + y + "\n") size_in_sectors = self._static_objects.get_size() for y in range(size_in_sectors.y): for x in range(size_in_sectors.x): for i in self._static_objects.get_sector(vec2(x, y)): xp = str(floor(i[0].x * 100)) yp = str(floor(i[0].y * 100)) rt = str(i[1]) sprite = str(static_objects_sprites[i[2]]) file.write("s " + xp + " " + yp + " " + rt + " " + sprite + "\n")
class Environment: """Klasa reprezentująca środowisko gry.""" FIND_PATH_MAX_DIST = 200 WARN_DISTANCE = 100 """ Stala okreslajaca jaka najdluzsza droge moze zwrocic findPath (Poprawia wydajnosc - nizsza stala = mniej szukania) """ def __init__(self, tile_size=TILE_SIZE): # environment self._terrain_grid = TerrainGrid(tile_size) self._static_objects = StaticObjects() self._dynamic_objects = [] # buffers for drawing self._previous_buffer = None self._current_buffer = None self._prev_viewport_pos = vec2(-0xfffffff, -0xfffffff) # surface cache self._PAGE_SIZE = vec2(320, 240) self._cache_size = 0 self._cache_pages = [] self._frame_number = 0 self._visible_objects = [] self._pickable_objects = [] self._players = [] self.resize(vec2(50, 50)) def load(self, loader): """Wczytuje mapę z podanego loadera.""" self._terrain_grid = loader.get_terrain_grid() self._static_objects = loader.get_static_objects() self._dynamic_objects = loader.get_dynamic_objects() self._players = [] for x in self._dynamic_objects: if isinstance(x, PlayerObject): self._players.append(x) x.set_environment(self) def save(self, loader): """Zapisuje mapę do podenego loadera.""" loader.set_terrain_grid(self._terrain_grid) loader.set_static_objects(self._static_objects) loader.set_dynamic_objects(self._dynamic_objects) def resize(self, size): """Zmienia rozmiar środowiska.""" self._terrain_grid.set_size(size) self._static_objects.set_size(size) i, s = 0, len(self._dynamic_objects) while i < s: position = self._dynamic_objects[i].get_position() if position.x < 0 or position.y < 0 or size.x <= position.x or size.y <= position.y: del self._dynamic_objects[i] s -= 1 else: i += 1 def notify(self, message, position): """Powiadamia wszystkie obiekty o czyms""" for object in self._dynamic_objects: if dist(object.get_position(), position) < Environment.WARN_DISTANCE: object.notify(message) def reachable(self, point): """Okresla czy do danego punktu (kwadratu) terenu da sie wejsc - identyczna z is_reachable""" return not self._terrain_grid.get_flags(point.ifloor()) def update(self, delta, current): """Odświeża stan środowiska.""" update_radius_sq = UPDATE_OBJECT_RANGE * UPDATE_OBJECT_RANGE position = vec2() if self._players != []: position = self._players[0].get_position() i, s = 0, len(self._dynamic_objects) while i < s: d_pos = position - self._dynamic_objects[i].get_position() radius_sq = d_pos.lengthsq() if radius_sq < update_radius_sq: if self._dynamic_objects[i].update(delta, current): self._dynamic_objects[i] = self._dynamic_objects[-1] self._dynamic_objects.pop() s -= 1 else: i += 1 else: i += 1 def redraw(self, surface, position, time, collisions=False): """Odrysowywuje środowisko.""" self._create_buffers(surface) surface_size = vec2(surface.get_size()) viewport_pos = (world_to_screen(position) - surface_size / 2).floor() displacement = self._prev_viewport_pos - viewport_pos displacement.y = -displacement.y self._current_buffer.fill((0, 0, 255, 0)) self._current_buffer.blit(self._previous_buffer, displacement.intcpl()) self._terrain_grid.redraw(self._current_buffer, viewport_pos - MARGIN_SIZE, time, collisions) surface.blit(self._current_buffer, (-MARGIN_SIZE).intcpl()) first = viewport_pos // self._PAGE_SIZE last = (viewport_pos + surface_size) // self._PAGE_SIZE + vec2(1, 1) self._visible_objects = [] self._pickable_objects = [] self._static_objects.redraw(surface, viewport_pos, self._visible_objects) self._prev_viewport_pos = viewport_pos # cull invisible objects redraw_radius_sq = REDRAW_OBJECT_RADIUS * REDRAW_OBJECT_RADIUS for object in self._dynamic_objects: d_pos = position - object.get_position() radius_sq = d_pos.lengthsq() if radius_sq < redraw_radius_sq: object.redraw(surface, viewport_pos, time, self._visible_objects, self._pickable_objects) self._visible_objects.sort(key=lambda x: x[1]) for object in self._visible_objects: surface.blit(object[0][0], object[2], object[0][1]) self._swap_buffers() def pick(self, position): """Zwraca listę obiektów na danej pozycji.""" result = [] for object in self._pickable_objects: region = object[1] if region_hit(region, position): result.append(object[0]) return result def get_players(self): """Zwraca obiekty gracza (zwykle jeden).""" return self._players def add_object(self, object): """Dodaje obiekt do środowiska.""" self._dynamic_objects.append(object) def collidable(self): """Zwraca obiekty ktore wchodzą w kolizje.""" return self._dynamic_objects def is_reachable(self, position): """Sprawdza czy dana pozycja jest osiągalna, czy da się tam wejść.""" return not self._terrain_grid.get_flags(position) def is_clear(self): return len(self._dynamic_objects) == 1 def _create_buffers(self, surface): surface_size = vec2(surface.get_size()) required_size = surface_size + MARGIN_SIZE * 2 if self._previous_buffer == None: self._previous_buffer = pygame.Surface(required_size.intcpl()) self._previous_position = vec2(-0xfffffff, -0xfffffff) if self._current_buffer == None: self._current_buffer = pygame.Surface(required_size.intcpl()) def _swap_buffers(self): tmp = self._current_buffer self._current_buffer = self._previous_buffer self._previous_buffer = tmp #returns table with points (nodes) to go through def findPath(self, startPoint, endPoint): """ Zwraca droge z punktu startowego do koncowego omijajaca wszystkie niedostepne statyczne czesci terenu. NIE OMIJA OBIEKTOW DYNAMICZNYCH W przypadku braku drogi zwraca liste pusta Stala srodowiska FIND_PATH_MAX_DIST okresla jaka najdluzsza droge findPath bedzie rozwazal, przestaje szukac i zwraca liste pusta w przypadku gdy przewidywana dlugosc trasy przekroczy ta stala. Jesli punkt startowy lub koncowy sa nieosiagalne stara sie znalezc osiagalny punkt w ich sasiedztwie. Zwraca [] i wypisuje na konsole blad jesli nie znajdzie """ def pairPlus(pair1, pair2): a1, b1 = pair1 a2, b2 = pair2 return (a1 + a2, b1 + b2) def manhattanDis(pair1, pair2): a1, b1 = pair1 a2, b2 = pair2 t0 = a2 - a1 t1 = b2 - b1 return ((t0 * t0 + t1 * t1)) def seqPlus(table, pair): tableNew = table[:] tableNew.append(pair) return tableNew def filter(f, table): newTable = [] for obj in table: if f(obj): newTable.append(obj) return newTable def findPathAux(self, startPoint, endPoint): reached = set() unchecked = PriorityQueue() moves = {(i, j) for i in [-1, 0, 1] for j in [-1, 0, 1]} moves.remove((0, 0)) count = 0 unchecked.put((0, startPoint, [])) while not unchecked.empty(): prior, point, seq = unchecked.get() if point == endPoint: return seq #odcinaj jesli przewidywana droga bedzie zbyt dluga if prior > self.FIND_PATH_MAX_DIST: return [] if not point in reached: reached.add(point) for move in moves: pointNew = pairPlus(point, move) if self.reachable(vec2(pointNew)): seqNew = seqPlus(seq, move) unchecked.put( (manhattanDis(pointNew, endPoint), pointNew, seqNew)) startPointVec = vec2(startPoint) if not self.reachable(startPointVec): rpoints = filter(self.reachable, [ startPointVec + vec2(i, j) for i in [-1, 0, 1] for j in [-1, 0, 1] ]) if rpoints != []: startPoint = rpoints[0].couple() else: # print("FindPath Error: startPoint unreachable and has not reachable neighbours") return [] endPointVec = vec2(endPoint) if not self.reachable(endPointVec): rpoints = filter(self.reachable, [ endPointVec + vec2(i, j) for i in [-1, 0, 1] for j in [-1, 0, 1] ]) if rpoints != []: endPoint = rpoints[0].couple() else: # print("FindPath Error: endPoint unreachable and has not reachable neighbours") return [] seq = findPathAux(self, startPoint, endPoint) if seq == None: # print("FindPath Error: None path of given length exists") return [] seqNew = [] acc = last = startPoint for move in seq: if move == last: acc = pairPlus(acc, last) else: seqNew = seqPlus(seqNew, acc) last = move acc = pairPlus(acc, move) seqNew = seqPlus(seqNew, endPoint) return [(x[0] + 0.49, x[1] + 0.49) for x in seqNew] #return seqNew def redraw_path(self, surface, position, path): """Funkcja pomocnicza rysuje ścieżkę na mapie. Przydatna przy debugowaniu.""" surface_size = vec2(surface.get_size()) i, s = 0, len(path) - 1 while i < s: first = world_to_screen(vec2(path[i]) + vec2(0.5, 0.5)) second = world_to_screen(vec2(path[i + 1]) + vec2(0.5, 0.5)) first -= position second -= position first.y = surface_size.y - first.y second.y = surface_size.y - second.y pygame.draw.line(surface, (255, 0, 0), first.intcpl(), second.intcpl()) i += 1
class Environment: def __init__(self, tile_size = TILE_SIZE): # environment self._terrain_grid = TerrainGrid(tile_size) self._static_objects = StaticObjects() self._dynamic_objects = [] # buffers for drawing self._previous_buffer = None self._current_buffer = None self._prev_viewport_pos = vec2(-0xfffffff, -0xfffffff) # surface cache self._PAGE_SIZE = vec2(320, 240) self._cache_size = 0 self._cache_pages = [] self._frame_number = 0 self.resize(vec2(50, 50)) def load(self, loader): self._terrain_grid = loader.get_terrain_grid() self._static_objects = loader.get_static_objects() self._dynamic_objects = loader.get_dynamic_objects() for x in self._dynamic_objects: x.set_environment(self) def save(self, loader): loader.set_terrain_grid(self._terrain_grid) loader.set_static_objects(self._static_objects) loader.set_dynamic_objects(self._dynamic_objects) def resize(self, size): self._terrain_grid.set_size(size) self._static_objects.set_size(size) i, s = 0, len(self._dynamic_objects) while i < s: position = self._dynamic_objects[i].get_position() if position.x < 0 or position.y < 0 or size.x <= position.x or size.y <= position.y: del self._dynamic_objects[i] s -= 1 else: i += 1 def notify(self, message): for object in self._dynamic_objects: object.notify(message) def reachable(self, point): return not self._terrain_grid.get_flags(point) def update(self, delta, current): i, s = 0, len(self._dynamic_objects) while i < s: if self._dynamic_objects[i].update(delta, current): self._dynamic_objects[i] = self._dynamic_objects[-1] self._dynamic_objects.pop() s -= 1 else: i += 1 def redraw(self, surface, position, time, collisions = False): self._create_buffers(surface) surface_size = vec2(surface.get_size()) viewport_pos = (world_to_screen(position) - surface_size / 2).floor() displacement = self._prev_viewport_pos - viewport_pos displacement.y = -displacement.y self._current_buffer.fill((0, 0, 255, 0)) self._current_buffer.blit(self._previous_buffer, displacement.intcpl()) self._terrain_grid.redraw(self._current_buffer, viewport_pos - MARGIN_SIZE, time, collisions) surface.blit(self._current_buffer, (-MARGIN_SIZE).intcpl()) first = viewport_pos // self._PAGE_SIZE last = (viewport_pos + surface_size) // self._PAGE_SIZE + vec2(1, 1) visible_objects = [] self._static_objects.redraw_to_cache(surface, viewport_pos, visible_objects) self._prev_viewport_pos = viewport_pos # cull invisible objects redraw_radius_sq = REDRAW_OBJECT_RADIUS * REDRAW_OBJECT_RADIUS for object in self._dynamic_objects: d_pos = position - object.get_position() radius = d_pos.lengthsq() if radius < redraw_radius_sq: object.redraw(surface, viewport_pos, time, visible_objects) visible_objects.sort(key = lambda x: x[1]) for object in visible_objects: surface.blit(object[0][0], object[2], object[0][1]) self.redraw_path(surface, viewport_pos, self.findPath((3, 3), (40, 30))) self._swap_buffers() def get_players(self): return [] def _create_buffers(self, surface): surface_size = vec2(surface.get_size()) required_size = surface_size + MARGIN_SIZE * 2 if self._previous_buffer == None: self._previous_buffer = pygame.Surface(required_size.intcpl()) self._previous_position = vec2(-0xfffffff, -0xfffffff) if self._current_buffer == None: self._current_buffer = pygame.Surface(required_size.intcpl()) def _swap_buffers(self): tmp = self._current_buffer self._current_buffer = self._previous_buffer self._previous_buffer = tmp #returns table with points (nodes) to go through def findPath(self, startPoint, endPoint): def pairPlus(pair1, pair2): a1,b1 = pair1 a2,b2 = pair2 return (a1+a2, b1+b2) def manhattanDis(pair1, pair2): a1,b1 = pair1 a2,b2 = pair2 t0 = a2-a1 t1 = b2-b1 return ((t0*t0+t1*t1)) def seqPlus(table, pair): tableNew = table[:] tableNew.append(pair) return tableNew def findPathAux(self, startPoint, endPoint): reached = set() unchecked = PriorityQueue() moves = {(i,j) for i in [-1,0,1] for j in [-1,0,1]} moves.remove((0,0)) count=0 unchecked.put((0,startPoint,[])) while not unchecked.empty(): _, point, seq = unchecked.get() if point == endPoint: return seq if not point in reached: reached.add(point) for move in moves: pointNew = pairPlus(point, move) if self.reachable(vec2(pointNew)): seqNew = seqPlus(seq, move) unchecked.put((manhattanDis(pointNew, endPoint), pointNew, seqNew)) seq = findPathAux(self, startPoint, endPoint) if seq == None: return [] seqNew = [] acc = last = startPoint for move in seq: if move == last: acc = pairPlus(acc, last) else: seqNew = seqPlus(seqNew, acc) last = move acc = pairPlus(acc,move) seqNew = seqPlus(seqNew, endPoint) return seqNew def redraw_path(self, surface, position, path): surface_size = vec2(surface.get_size()) i, s = 0, len(path) - 1 while i < s: first = world_to_screen(vec2(path[i]) + vec2(0.5, 0.5)) second = world_to_screen(vec2(path[i + 1]) + vec2(0.5, 0.5)) first -= position second -= position first.y = surface_size.y - first.y second.y = surface_size.y - second.y pygame.draw.line(surface, (255, 0, 0), first.intcpl(), second.intcpl()) i += 1
class Environment: def __init__(self, tile_size=TILE_SIZE): # environment self._terrain_grid = TerrainGrid(tile_size) self._static_objects = StaticObjects() self._dynamic_objects = [] # buffers for drawing self._previous_buffer = None self._current_buffer = None self._prev_viewport_pos = vec2(-0xfffffff, -0xfffffff) # surface cache self._PAGE_SIZE = vec2(320, 240) self._cache_size = 0 self._cache_pages = [] self._frame_number = 0 self.resize(vec2(50, 50)) def load(self, loader): self._terrain_grid = loader.get_terrain_grid() self._static_objects = loader.get_static_objects() self._dynamic_objects = loader.get_dynamic_objects() for x in self._dynamic_objects: x.set_environment(self) def save(self, loader): loader.set_terrain_grid(self._terrain_grid) loader.set_static_objects(self._static_objects) loader.set_dynamic_objects(self._dynamic_objects) def resize(self, size): self._terrain_grid.set_size(size) self._static_objects.set_size(size) i, s = 0, len(self._dynamic_objects) while i < s: position = self._dynamic_objects[i].get_position() if position.x < 0 or position.y < 0 or size.x <= position.x or size.y <= position.y: del self._dynamic_objects[i] s -= 1 else: i += 1 def notify(self, message): for object in self._dynamic_objects: object.notify(message) def reachable(self, point): return not self._terrain_grid.get_flags(point) def update(self, delta, current): i, s = 0, len(self._dynamic_objects) while i < s: if self._dynamic_objects[i].update(delta, current): self._dynamic_objects[i] = self._dynamic_objects[-1] self._dynamic_objects.pop() s -= 1 else: i += 1 def redraw(self, surface, position, time, collisions=False): self._create_buffers(surface) surface_size = vec2(surface.get_size()) viewport_pos = (world_to_screen(position) - surface_size / 2).floor() displacement = self._prev_viewport_pos - viewport_pos displacement.y = -displacement.y self._current_buffer.fill((0, 0, 255, 0)) self._current_buffer.blit(self._previous_buffer, displacement.intcpl()) self._terrain_grid.redraw(self._current_buffer, viewport_pos - MARGIN_SIZE, time, collisions) surface.blit(self._current_buffer, (-MARGIN_SIZE).intcpl()) first = viewport_pos // self._PAGE_SIZE last = (viewport_pos + surface_size) // self._PAGE_SIZE + vec2(1, 1) visible_objects = [] self._static_objects.redraw_to_cache(surface, viewport_pos, visible_objects) self._prev_viewport_pos = viewport_pos # cull invisible objects redraw_radius_sq = REDRAW_OBJECT_RADIUS * REDRAW_OBJECT_RADIUS for object in self._dynamic_objects: d_pos = position - object.get_position() radius = d_pos.lengthsq() if radius < redraw_radius_sq: object.redraw(surface, viewport_pos, time, visible_objects) visible_objects.sort(key=lambda x: x[1]) for object in visible_objects: surface.blit(object[0][0], object[2], object[0][1]) self.redraw_path(surface, viewport_pos, self.findPath((3, 3), (40, 30))) self._swap_buffers() def get_players(self): return [] def _create_buffers(self, surface): surface_size = vec2(surface.get_size()) required_size = surface_size + MARGIN_SIZE * 2 if self._previous_buffer == None: self._previous_buffer = pygame.Surface(required_size.intcpl()) self._previous_position = vec2(-0xfffffff, -0xfffffff) if self._current_buffer == None: self._current_buffer = pygame.Surface(required_size.intcpl()) def _swap_buffers(self): tmp = self._current_buffer self._current_buffer = self._previous_buffer self._previous_buffer = tmp #returns table with points (nodes) to go through def findPath(self, startPoint, endPoint): def pairPlus(pair1, pair2): a1, b1 = pair1 a2, b2 = pair2 return (a1 + a2, b1 + b2) def manhattanDis(pair1, pair2): a1, b1 = pair1 a2, b2 = pair2 t0 = a2 - a1 t1 = b2 - b1 return ((t0 * t0 + t1 * t1)) def seqPlus(table, pair): tableNew = table[:] tableNew.append(pair) return tableNew def findPathAux(self, startPoint, endPoint): reached = set() unchecked = PriorityQueue() moves = {(i, j) for i in [-1, 0, 1] for j in [-1, 0, 1]} moves.remove((0, 0)) count = 0 unchecked.put((0, startPoint, [])) while not unchecked.empty(): _, point, seq = unchecked.get() if point == endPoint: return seq if not point in reached: reached.add(point) for move in moves: pointNew = pairPlus(point, move) if self.reachable(vec2(pointNew)): seqNew = seqPlus(seq, move) unchecked.put( (manhattanDis(pointNew, endPoint), pointNew, seqNew)) seq = findPathAux(self, startPoint, endPoint) if seq == None: return [] seqNew = [] acc = last = startPoint for move in seq: if move == last: acc = pairPlus(acc, last) else: seqNew = seqPlus(seqNew, acc) last = move acc = pairPlus(acc, move) seqNew = seqPlus(seqNew, endPoint) return seqNew def redraw_path(self, surface, position, path): surface_size = vec2(surface.get_size()) i, s = 0, len(path) - 1 while i < s: first = world_to_screen(vec2(path[i]) + vec2(0.5, 0.5)) second = world_to_screen(vec2(path[i + 1]) + vec2(0.5, 0.5)) first -= position second -= position first.y = surface_size.y - first.y second.y = surface_size.y - second.y pygame.draw.line(surface, (255, 0, 0), first.intcpl(), second.intcpl()) i += 1