def moves_lcd(self, max_step_size): lin_steps = [ k for k in range(-1 * max_step_size, max_step_size + 1) if k != 0 ] steps_x = [Vec(k, 0, 0) for k in lin_steps] steps_y = [Vec(0, k, 0) for k in lin_steps] steps_z = [Vec(0, 0, k) for k in lin_steps] return steps_x + steps_y + steps_z
def apply(point, word, mirrors): point = Vec(point) for gen in word: mirror = mirrors[gen] point = point.reflect(mirror) return point
def collide(self, pos): r = 0.1 is_wall = lambda x: self.parent.get_maze().is_wall(x) p1 = (pos + Vec(r, r)).apply(math.floor) p2 = (pos - Vec(r, r)).apply(math.ceil) return (is_wall(p1) or is_wall(p2) or is_wall(Vec(p1.x, p2.y)) or is_wall(Vec(p2.x, p1.y)))
def try_to_move(self, vel): vx = Vec(vel.x, 0) vy = Vec(0, vel.y) if not self.collide(self.pos + vx + vy): self.pos += vx + vy elif not self.collide(self.pos + vx): self.pos += vx elif not self.collide(self.pos + vy): self.pos += vy else: return True return False
class Mover(TL.Entity): def __init__(self, parent): super(Mover, self).__init__() self.parent = parent self.ppos = Vec(0, 0) self.pos = Vec(0, 0) self.vel = Vec(0, 0) self.pvel = Vec(0, 0) def set_vel(self, vel): self.pvel = self.vel self.vel = vel def collide(self, pos): r = 0.1 is_wall = lambda x: self.parent.get_maze().is_wall(x) p1 = (pos + Vec(r, r)).apply(math.floor) p2 = (pos - Vec(r, r)).apply(math.ceil) return (is_wall(p1) or is_wall(p2) or is_wall(Vec(p1.x, p2.y)) or is_wall(Vec(p2.x, p1.y))) def try_to_move(self, vel): vx = Vec(vel.x, 0) vy = Vec(0, vel.y) if not self.collide(self.pos + vx + vy): self.pos += vx + vy elif not self.collide(self.pos + vx): self.pos += vx elif not self.collide(self.pos + vy): self.pos += vy else: return True return False def update(self): if not self.try_to_move(self.vel): self.try_to_move(self.pvel) self.pos.x = self.pos.x % (self.parent.maze.get_max_cols() - 1) self.pos.y = self.pos.y % (self.parent.maze.get_max_rows() - 1) self.ppos = self.pos def changedTilePos(self): return (self.ppos.apply(round) == self.pos.apply(round))
def handle_targeting(left_click, right_click, turn_results): player_action = None if left_click: targetx, targety = left_click.cx, left_click.cy distance = (self.pos - Vec(targetx, targety)).length() if game_data.targeting_formula: alternate = left_click.alternate if alternate and config.conf.trapcast: game_data.targeting_formula.trap = True game_data.targeting_formula.set_texts() if distance > game_data.targeting_formula.distance: turn_results.append({ "target_out_of_range": True, "targeting_formula": game_data.targeting_formula, }) else: player_action = ThrowVialAction( self, game_data.targeting_formula, targetpos=(Pos(targetx, targety)), ) # gfx_data.visuals.add_temporary(self.pos, Pos(targetx, targety), lifespan=distance * 0.1, gfx_data.visuals.add_temporary( self.pos, Pos(targetx, targety), lifespan=0.2, asset=gfx_data.assets.throwing_bottle, ) game_data.state = game_data.prev_state.pop() game_data.targeting_formula_idx = None elif game_data.targeting_consumable: if distance > game_data.targeting_consumable.distance: turn_results.append({ "target_out_of_range": True, "targeting_consumable": game_data.targeting_consumable, }) else: player_action = UseConsumableAction( self, game_data.targeting_consumable, targetpos=(Pos(targetx, targety)), ) gfx_data.visuals.add_temporary( self.pos, Pos(targetx, targety), lifespan=0.2, asset=gfx_data.assets.throwing_bottle, ) game_data.state = game_data.prev_state.pop() game_data.targeting_consumable = None elif right_click: turn_results.append({"targeting_cancelled": True}) return player_action, turn_results
def get_absolute_pos(self, pos): t_pos = self.pos_1 + Vec(self.get_width() * pos.x, self.get_height() * pos.y) if self.parent != None: return self.parent.get_absolute_pos(t_pos) else: return t_pos
def get_adj_nodes(self, x, y): adj_node = [] for (i, j) in [(-1, 0), (+1, 0), (0, -1), (0, +1)]: if not self.is_wall(Vec(x + i, y + j)): adj_node.append((x + i, y + j)) return adj_node
def normals(self): normals = [] for p in self.planes: vp = [] for m, (q, vq) in enumerate(zip(self.planes, normals)): vpm = (math.cos(self[p, q]) - vq[:m] @ vp[:m]) / vq[m] vp.append(round(vpm, 15)) vp.append(round(math.sqrt(1 - Vec(vp).norm2), 15)) vp = Vec(vp) if any(vp @ v > 0 for v in normals): vp *= -1 normals.append(vp) return {p: n[:len(normals)] for p, n in zip(self.planes, normals)}
def reset(self): r = self.get_max_cols() c = self.get_max_rows() for i in range(0, r): for j in range(0, c): self.get_tile(Vec(i, j)).reset() self.eaten_food = 0
def respawn(self): self.update_scatter_matrix() self.pos = self.spawn_pos self.set_sprite(self.sprite_normal[-1]) self.state = Ghost.CHASE self._next_pos = Vec(0, 0) self.t = 0 return self
def pos_neighbors(coords): vals = [-1, 0, 1] deltas = [ Vec(dx, dy, dz) for dx in vals for dy in vals for dz in vals ] nbrs = Set([ coords + delta for delta in deltas if (not delta.is_zero()) and self.is_coord_valid(coords + delta) ]) return nbrs
def update_scatter_matrix(self): maze = self.parent.get_maze() r, c = maze.get_max_cols(), maze.get_max_rows() self.scatter_pos = self.pos while maze.get_tile(self.scatter_pos).is_wall() or ( self.pos - self.scatter_pos).mag_manhattan() < 1: self.scatter_pos = Vec(random.randint(0, r - 1), random.randint(0, c - 1)) self.scatter_matrix = search_dijkstra( [self.scatter_pos], c, r, self.parent.get_maze().get_adj_nodes)
def loadMap(self, path): self.maze = Maze() self.player = [] self.ghosts = [] self.maze.load_map(self, path, self.player, self.ghosts) self.player = self.player[-1] n = 100 c, r = self.maze.get_max_cols(), self.maze.get_max_rows() + 1 k = max(c, r) + 1 self.frame = TL.Frame().resize(n * k, n * k).set_tile_scale(n, n).set_pos( Vec(0.5, 0.5)) self.frame.set_renderer(self.renderer) self.icons_lives = [] x = 0 for i in ["player/0.png"] * 3: self.icons_lives.append( Icon(TL.load_sprite(get_path(i))).set_pos(Vec(x, r - 1))) x += 1 for i in [self.maze] + self.ghosts + [self.player] + self.icons_lives: self.frame.add_child(i) self.ghost_home = [] for i in self.ghosts: self.ghost_home.append(i.pos) self.update_player_search_matrix() self.home_search_matrix = search_dijkstra(self.ghost_home, self.maze.get_max_rows(), self.maze.get_max_cols(), self.maze.get_adj_nodes) self.respawn_entities()
def __init__(self, parent): super(Mover, self).__init__() self.parent = parent self.ppos = Vec(0, 0) self.pos = Vec(0, 0) self.vel = Vec(0, 0) self.pvel = Vec(0, 0)
def chase(self): phase = self.t % self.len_interv vel = Vec(0, 0) if phase < self.mid: vel = self.get_direction( self.parent.player_search_matrix) * self.chase_vel elif phase == self.mid: self.update_scatter_matrix() else: if (self.scatter_pos - self.pos).mag_manhattan() < 1: self.update_scatter_matrix() vel = self.get_direction(self.scatter_matrix) * self.scatter_vel self.set_vel(vel)
def player_get_input(self, player, event): vel = Vec(0, 0) pressed = lambda lst: any([event.key_is_pressed(i) for i in lst]) if event.mouse_is_pressed(): _dir = event.mouse_dir() vel = Vec(_dir.x, _dir.y).apply(round) if pressed(["a", Ev.Key.LEFT]): vel.x = -1 elif pressed(["d", Ev.Key.RIGHT]): vel.x = +1 if pressed(["w", Ev.Key.UP]): vel.y = -1 elif pressed(["s", Ev.Key.DOWN]): vel.y = +1 player.set_vel(vel)
def get_direction(self, search_matrix): ds = (self.pos - self._next_pos).apply(round).apply(abs) if (ds.x < 0.01 or 1 <= ds.x) and (ds.y < 0.01 or 1 <= ds.y): i, j = self.pos.apply(round).apply(int) pos_lst = search_matrix[i][j] if pos_lst != [] and pos_lst != None: if isinstance(pos_lst, list): i, j = pos_lst[0] else: i, j = pos_lst self._next_pos = Vec(i, j) else: self._next_pos = self.pos return (self._next_pos - self.pos).norm()
def __init__(self, pos, endpos, lifespan, drawable, color, owner, wait, transform=None): self.pos = pos self.endpos = endpos self.lifespan = lifespan self.wait = wait self.age = 0 if pos != endpos: distance = pos.distance_to(endpos) distance_per_update = distance / self.lifespan vec = endpos - pos normalized = vec.normalize() self.move_per_update = normalized * distance_per_update else: self.move_per_update = Vec(0, 0) self.drawable = drawable self.drawable.owner = self self.owner = owner self.transform = transform if color: self.drawable.colorize(color)
def set_buffer(self, buffer): max_rows = len(buffer) max_cols = 0 if max_rows != 0: max_cols = len(buffer[0]) for i in buffer: max_cols = max(max_cols, len(i)) self._max_rows = max_rows self._max_cols = max_cols self._tile_buffer = buffer y = 0 for i in self._tile_buffer: x = 0 for j in i: j.set_pos(Vec(x, y)) x += 1 y += 1 return self
def set_corners(self, x1, y1, x2, y2): self.pos_1 = Vec(x1, y1) self.pos_2 = Vec(x2, y2) return self
def set_buffer_corners(self, x1 = 0, y1 = 0, x2 = 1, y2 = 1): self.buffer_pos_1 = Vec(x1, y1) self.buffer_pos_2 = Vec(x2, y2) return self
def moves_ncd(self): lin_steps = [k for k in range(-2, 3)] moves = [ Vec(dx, dy, dz) for dx in lsteps for dy in lsteps for dz in lsteps ] return [move for move in moves if move.mlen() > 0 and move.mlen() <= 2]
def draw_targeting(self, game_data, gfx_data, main): def draw_rect_boundary(surface, colour, rect, draw_cross): x1 = rect[0] x2 = rect[0] + rect[2] y1 = rect[1] y2 = rect[1] + rect[3] pygame.draw.line(surface, colour, (x1, y1), (x1, y2), 4) pygame.draw.line(surface, colour, (x1, y1), (x2, y1), 4) pygame.draw.line(surface, colour, (x2, y1), (x2, y2), 4) pygame.draw.line(surface, colour, (x1, y2), (x2, y2), 4) if draw_cross: pygame.draw.line(surface, colour, (x1, y1), (x2, y2), 3) pygame.draw.line(surface, colour, (x2, y1), (x1, y2), 3) item = None if game_data.targeting_formula: item = game_data.targeting_formula elif game_data.targeting_consumable: item = game_data.targeting_consumable assert item max_dist = item.distance * CELL_WIDTH pos = pygame.mouse.get_pos() px, py = pos targeting_surface = pygame.Surface( game_data.constants.window_size.tuple(), pygame.SRCALPHA) # find targeted tile map_screen_pos = self.global_screen_pos_to_map_screen_pos( px, py, game_data) tile = self.map_screen_pos_to_tile(map_screen_pos[0], map_screen_pos[1], gfx_data) rect = self.get_tile_rect(tile[0], tile[1], gfx_data) rect_center = rect[0] + CELL_WIDTH / 2, rect[1] + CELL_HEIGHT / 2 # find player position s_player_x, s_player_y = gfx_data.camera.map_to_screen( game_data.player.pos.x, game_data.player.pos.y) orig = (s_player_x * CELL_WIDTH, s_player_y * CELL_HEIGHT) orig = (orig[0] + CELL_WIDTH / 2, orig[1] + CELL_HEIGHT / 2 ) # centered dist = distance(orig[0], orig[1], rect_center[0], rect_center[1]) if dist > max_dist: from util import Vec vec = Vec(px - orig[0] - self.pos.x, py - orig[1]) normalized = vec.normalize() red_part = ( orig[0] + normalized.x * max_dist, orig[1] + normalized.y * max_dist, ) pygame.draw.line(targeting_surface, (150, 0, 0), orig, red_part) pygame.draw.line(targeting_surface, (100, 100, 100), red_part, rect_center) draw_rect_boundary(targeting_surface, (150, 100, 100), rect, draw_cross=True) elif item.area == 1: # no aoe pygame.draw.line(targeting_surface, (255, 0, 0), orig, rect_center) draw_rect_boundary(targeting_surface, (255, 0, 0), rect, draw_cross=False) else: pygame.draw.line(main, (255, 0, 0), orig, rect_center) for x in range( math.ceil(tile[0] - item.distance), math.ceil(tile[0] + item.distance), ): for y in range( math.ceil(tile[1] - item.distance), math.ceil(tile[1] + item.distance), ): dist = math.sqrt((x - tile[0])**2 + (y - tile[1])**2) if dist < item.area: tile_rect = self.get_tile_rect(x, y, gfx_data) draw_rect_boundary( targeting_surface, (255, 0, 0), tile_rect, draw_cross=False, ) targeting_surface.set_alpha(150) main.blit(targeting_surface, (0, 0))
def set_pos(self, pos=Vec(0, 0)): self.pos = pos return self
def set_pos(self, pos=Vec(0, 0)): super(Ghost, self).set_pos(pos) self.spawn_pos = pos return self
def gram_schmidt(vecs) -> List[Vec]: vecs = [Vec(v) for v in vecs] for i in range(len(vecs)): for j in range(i): vecs[i] -= vecs[i].project(vecs[j]) return [v.normalized for v in vecs]
def load_map(self, parent, path, players, ghosts): EMPTY = " " WALL = "#" FOOD = "+" POWERPELLET = "-" BLINK = "B" CLYDE = "C" INK = "I" SHADOW = "S" GHOSTS = [BLINK, CLYDE, SHADOW, INK, "G"] file = open(path, "r") (x, y) = (0, 0) arr = [] for i in file.readlines(): elem = i.replace(os.linesep, "").replace("\r", "").replace("\n", "").split(";") print(elem) x = 0 row = [] for j in elem: cell = TileUndefined() pos = Vec(x, y) if j == "P": players.append(Player(parent).set_pos(pos)) cell = TileEmpty() elif any((j == x for x in GHOSTS)): fn = Ghost if j == BLINK: fn = Blink elif j == CLYDE: fn = Clyde elif j == INK: fn = Ink elif j == SHADOW: fn = Shadow ghosts.append(fn(parent).set_pos(pos)) cell = TileGhostHome() elif j == EMPTY: cell = TileEmpty() elif j == WALL: cell = TileWall() elif j == FOOD: cell = TileFood() self.total_food += 1 elif j == POWERPELLET: cell = TilePowerPellet() self.total_food += 1 row.append(cell) x += 1 arr.append(row) y += 1 file.close() super(Maze, self).set_buffer(arr)
def resize(self, w, h): self.pos_2 = Vec(self.pos_1.x + w, self.pos_2.y + h)