def __init__(self, posicao, velocidade, aceleracao, coef_elastico=0.9): self.raio = 10.0 self.circulo = eu.Circle(eu.Point2(posicao.x, posicao.y), self.raio) self.posicao = posicao self.velocidade = velocidade self.aceleracao = aceleracao self.coef_elastico = coef_elastico
def atualizar(self): if pyxel.btn(pyxel.KEY_LEFT_BUTTON): bola = Bola(eu.Point2(pyxel.mouse_x, pyxel.mouse_y), eu.Vector2(0, 0), self.gravidade, 0.2) self.bolas.append(bola) for i, b in enumerate(self.bolas): b.atualizar() for s in self.segmentos: b.checar_colisao(s) for b2 in self.bolas[i + 1:]: b.checar_colisao(b2)
def atualizar(self): if pyxel.btnr(pyxel.MOUSE_LEFT_BUTTON): bola = Bola(eu.Point2(pyxel.mouse_x, pyxel.mouse_y), eu.Vector2(0, 0), self.gravidade, 0.8) self.bolas.append(bola) for i, b in enumerate(self.bolas): b.atualizar() if b.permanecer: for s in self.segmentos: b.checar_colisao(s) for b2 in self.bolas[i + 1:]: b.checar_colisao(b2) self.bolas = list(filter(lambda b: b.permanecer, self.bolas))
def checar_colisao(self, objeto): if isinstance(objeto, Segmento): if self.posicao.distance(objeto.linha) <= self.raio: normal = self.posicao.connect(objeto.linha) vetor_normal = (normal.p1 - normal.p2).normalize() nova_posicao = normal.p2 + (vetor_normal * self.raio) self.posicao = eu.Point2(nova_posicao.x, nova_posicao.y) self.velocidade = self.velocidade.reflect( vetor_normal) * self.coef_elastico elif isinstance(objeto, Bola): if self.posicao.distance( objeto.posicao) <= self.raio + objeto.raio: diferenca = self.raio + objeto.raio - self.posicao.distance( objeto.posicao) vetor_colisao = self.posicao - objeto.posicao vetor_colisao.normalize() self.posicao = self.posicao + vetor_colisao * (diferenca / 2) objeto.posicao = objeto.posicao - vetor_colisao * (diferenca / 2) self.velocidade = self.velocidade.reflect( vetor_colisao) * self.coef_elastico objeto.velocidade = objeto.velocidade.reflect( vetor_colisao) * self.coef_elastico
def __init__(self, x1, y1, x2, y2): self.linha = eu.LineSegment2(eu.Point2(x1, y1), eu.Point2(x2, y2))
def decide_move(group, game_map): if group.category != "vehicle": return None if "__sg__" in group.name: return None node_id = game_map.find_group_node(group) if node_id is None: logger.error("The group %s is not on the game map." % str(group)) return None if game_map.red_goal_node is None or game_map.blue_goal_node is None: logger.error( "Must set goal nodes for both sides until can call decide_move.") return None if group.coalition == "red": correct_goal = game_map.red_goal_node else: correct_goal = game_map.blue_goal_node origin_coords = game_map.get_node_coords(node_id) origin_coords = euclid3.Point2(origin_coords[0], origin_coords[1]) goal_coords = game_map.get_node_coords(correct_goal) goal_coords = euclid3.Point2(goal_coords[0], goal_coords[1]) neighbor_paths = [] path_pairs = [] for neighbor in game_map.graph[node_id]: if neighbor == correct_goal: return int(correct_goal) shortest_path_to_goal = game_map.get_shortest_path( neighbor, correct_goal) # Ignore paths that return to the node we are in if shortest_path_to_goal is not None and node_id not in shortest_path_to_goal: neighbor_paths.append(shortest_path_to_goal) if len(neighbor_paths) == 0: logger.warning("No path to goal found for group %s" % group.name) return None if len(neighbor_paths) == 1: return int(neighbor_paths[0][0]) # We try to identify the REALLY stupid choices before we randomize our actual choice forbidden_nodes = [] length = len(neighbor_paths) # A bit complicated algorithm. Creates a list of all possible pairs of different paths and truncates them to the # nearest common node. The i and j -parts of the for loops are the traditional way to compare pairs with least # amount of work. (Don't compare item with itself, and don't compare a to b, and then b to a. for i in range(length - 1): for j in range(i + 1, length): # The previous two loops compared paths. The next two loops compare nodes in paths. found_intersection = False for k in range(0, len(neighbor_paths[i])): for l in range(0, len(neighbor_paths[j])): if neighbor_paths[i][k] == neighbor_paths[j][l]: path_pairs.append((neighbor_paths[i][:k + 1], neighbor_paths[j][:l + 1])) found_intersection = True break if found_intersection: break # Compares all the pairs, and forbids all nodes where there is such a pair that the divergent part is one third # longer for the to-be-forbidden path, than the shorter path. This prevents any dumb detours from happening. for pair in path_pairs: # This allows us to trivially calculate the path length tmpgraph1 = game_map.graph.subgraph(pair[0]) tmpgraph2 = game_map.graph.subgraph(pair[1]) size1 = tmpgraph1.size(weight='weight') size2 = tmpgraph2.size(weight='weight') if size1 >= 1.33 * size2: # Found a dumb detour. Forbid. if pair[0][0] not in forbidden_nodes: forbidden_nodes.append(pair[0][0]) elif size2 >= 1.33 * size1: # ditto if pair[1][0] not in forbidden_nodes: forbidden_nodes.append(pair[1][0]) node_is_backtrack = {} choices = [] allow_backtrack = True for path in neighbor_paths: if path[0] not in forbidden_nodes: is_backtrack = False dest_coords = game_map.get_node_coords(path[0]) dest_coords = euclid3.Point2(dest_coords[0], dest_coords[1]) if dest_coords.distance(goal_coords) > origin_coords.distance( goal_coords): # Making this move would mean backtracking is_backtrack = True else: # We found at least one node which doesn't constitute backtracking. Hence we disallow all moves that do allow_backtrack = False node_is_backtrack[path[0]] = is_backtrack choices.append(path[0]) if allow_backtrack is False: choices = [ node for node in choices if node_is_backtrack[node] is False ] decision = np.random.choice(choices) extra_info = "" if node_is_backtrack[decision] is True: extra_info = " (which is backtracking)" logger.debug("Final decision for %s: move to node %d.%s" % (group.name, decision, extra_info)) if decision is None: return None else: return int(decision)