def update_state(self, field: World) -> None: self.energy = next(self.lifetime, 0) if self.is_dead(): self.kill() return self.color.a = int(255 * self.alpha()) self.draw_image(self.color) goto = Point(*self.rect.center) goto = self.run_from_zombies(field, goto) goto = self.run_to_food(field, goto) next_pos = Point(goto.x + self.current_dir.x, goto.y + self.current_dir.y) go_to_dir = Direction.from_points(Point(*self.rect.center), next_pos) self.current_dir = go_to_dir super().update_state(field)
def mouse_up(self, event: pygame.event.Event) -> None: if event.button != 1: return pos = Point(*event.pos) self.on_mouse_up(pos) # type: ignore self.on_mouse_up = lambda pos: None self.on_mouse_move = lambda pos: None
def update_state(self, field: World) -> None: if self.attack_wait > 0: self.attack_wait -= 1 return goto = Point(*self.rect.center) goto = self.run_to_humans(field, goto) next_point = Point(goto.x + self.current_dir.x, goto.y + self.current_dir.y) # TODO Revisit victim_angle = Direction.from_points(Point(*self.rect.center), next_point).to_angle() if victim_angle > self.angle: self.angle += math.radians(10) elif victim_angle < self.angle: self.angle -= math.radians(10) self.current_dir = Direction.from_angle(self.angle) super().update_state(field)
def __init__(self, sprite: Entity, pos: Point, on_pos_change: EntityCallback): self.sprite: Entity = sprite self.groups = tuple(sprite.groups()) center: Point = Point(*sprite.rect.center) self.offset: Point = center - pos self.on_pos_change: EntityCallback = on_pos_change
def run_to_food(self, field: World, goto: Point) -> Point: if self.is_hungry(): span = zutil.span(field.bounds) span_mid = span / 2.0 food, _ = self.closest_to(field.food, field.bounds) if food is not None: direc = Direction.from_points(self.position, food.position) dist = self.position.distance(food.position) if dist > span_mid: direc = -direc factor = (float(self.energy) / 4 * HUMAN_VISION)**2 goto = Point(goto.x + (factor * direc.x), goto.y + (factor * direc.y)) return goto
def run_from_zombies(self, field: World, goto: Point) -> Point: span = zutil.span(field.bounds) span_mid = span / 2.0 for zombie in self.zombies_in_vision(field): dist = self.position.distance(zombie.position) rev_dir = False if dist > span_mid: dist = span - dist rev_dir = True factor_dist = float(HUMAN_VISION - dist)**2 direc = Direction.from_points(self.position, zombie.position) if not rev_dir: direc = -direc goto = Point(goto.x + (factor_dist * direc.x), goto.y + (factor_dist * direc.y)) return goto
def mouse_down(self, event: pygame.event.Event) -> None: if event.button != 1: return pos = Point(*event.pos) sprites = self.sprites_under(pos) for each in sprites: self.pick_up(each, pos) def on_up(pos: Point, sprites=sprites): for each in sprites: self.put_down(each, pos) self.on_mouse_up = on_up # type: ignore def on_move(pos:Point, sprites=sprites): for each in sprites: self.update_pick_up(each, pos) self.on_mouse_move = on_move # type: ignore
def run_to_humans(self, field: World, goto: Point) -> Point: humans = self.humans_in_vision(field) bounds = field.bounds victim, _ = self.closest_to(humans, bounds) if victim is None: return goto span = zutil.span(bounds) span_mid = span / 2.0 direc = Direction.from_points(self.position, victim.position) dist = self.position.distance(victim.position) if dist > span_mid: dist = span - dist direc = -direc factor_dist = float(ZOMBIE_VISION - dist) goto = Point(int(goto.x + (factor_dist * direc.x)), int(goto.y + (factor_dist * direc.y))) return goto
def span(rect: Bounds) -> float: return Point(*rect.topleft).distance(Point(*rect.bottomright))
def position(self) -> Point: return Point(*self.center)
def mouse_move(self, event: pygame.event.Event) -> None: if not event.buttons[0]: return pos = Point(*event.pos) self.on_mouse_move(pos) # type: ignore
def random_point(rect: pygame.rect.Rect) -> Point: x = random.randrange(rect.left, rect.right) y = random.randrange(rect.top, rect.bottom) return Point(x, y)