Vector Field Pathfinder
unknown
python
3 years ago
4.0 kB
34
Indexable
Never
import time import numpy as np from pyglet.math import Vec2 class FlowField(object): # Const neighbours vectors DIR_VECTORS = [[1, 0], [-1, 0], [0, 1], [0, -1]] FULL_DIR_VECTORS = [[1, 0], [-1, 0], [0, 1], [0, -1], [1, 1], [-1, -1], [1, -1], [-1, 1]] def __init__(self, cost_map: np.array, map_size: Vec2): self.cost_map = cost_map self.size = map_size self.node_map = self.generate_node_map() def generate_node_map(self): nodes = np.empty((self.size.x, self.size.y), dtype=object) for x in range(self.size.x): for y in range(self.size.y): n = Node(x, y, self.cost_map[x, y]) nodes[x, y] = n return nodes def reset_nodes(self): for x in range(self.size.x): for y in range(self.size.y): self.node_map[x,y].best_cost = 65536 self.node_map[x,y].cost = self.cost_map[x, y] def calculate_integration_field(self, target_x: int, target_y: int): self.start = time.time() # Create a new, empty list open_node_list = [] self.reset_nodes() # Set the target node cost and best cost to 0 self.node_map[target_x, target_y].cost = 0 self.node_map[target_x, target_y].best_cost = 0 self.node_map[target_x, target_y].best_direction = Vec2(0, 0) # Add the node goal to the open list open_node_list.append(self.node_map[target_x, target_y]) while len(open_node_list) > 0: # Get the next node and removes it from the list current_node = open_node_list[-1] open_node_list.pop() # Get the neighbours cells neighbours = self.get_node_neighbours(current_node.position, self.DIR_VECTORS) for node in neighbours: if node.cost == 255: continue if node.cost + current_node.best_cost < node.best_cost: node.best_cost = current_node.best_cost + node.cost self.node_map[node.position.x, node.position.y].best_cost = node.best_cost open_node_list.append(node) self.create_vector_field() def create_vector_field(self): for x in range(self.size.x): for y in range(self.size.y): # Get the neighbours cells node = self.node_map[x,y] neighbours = self.get_node_neighbours(node.position, self.FULL_DIR_VECTORS) best_cost = node.best_cost for neighbour in neighbours: if neighbour.best_cost < best_cost: best_cost = neighbour.best_cost node.best_direction = Vec2(neighbour.position.x - node.position.x, neighbour.position.y - node.position.y) end = time.time() print("Vector Field Generated in: " + str(end - self.start)) def get_node_neighbours(self, current_node_pos: Vec2, directions: list): neighbours = [] for i in range(len(directions)): n_pos = Vec2(current_node_pos.x + directions[i][0], current_node_pos.y + directions[i][1]) if 0 <= n_pos.x < self.size.x: if 0 <= n_pos.y < self.size.y: n = self.node_map[n_pos.x, n_pos.y] neighbours.append(n) return neighbours class Node(object): def __init__(self, pos_x: int, pos_y: int, cost: int): self.position = Vec2(pos_x, pos_y) self.cost = cost self.best_cost = 65536 self.best_direction = Vec2(0, 0) def increase_cost(self, amount: int): # If the cost of the cell is already at the maximum value, return. if self.cost == 255: return # Clamp the value if amount + self.cost > 255: self.cost = 255 else: self.cost += amount