def _cb_remove_brick(self, arbiter: pymunk.Arbiter, space: pymunk.Space, data): """ callback function :param arbiter: :param space: :param data: :return: """ brick_shape = arbiter.shapes[0] space.remove(brick_shape, brick_shape.body)
def remove(self, space: pymunk.Space): for pivot in self.pivots: space.remove(pivot) for muscle in self.muscles: space.remove(muscle) Creature.__remove(self, space)
def __remove(part, space: pymunk.Space): space.remove(part.body) space.remove(part.shape) for limb in part.limbs: Creature.__remove(limb, space)
class WorldState: """ Contains the objects, the robots and the surrounding space of the 'world' """ def __init__(self, config): self.sprite_list = _arcade.SpriteList() self.obstacles = [] self.static_obstacles = [] self.falling_obstacles = [] self.color_obstacles = [] self.robots = [] self.space = Space() self.space.damping = 0.1 self.board_width = config['board_width'] self.board_height = config['board_height'] board_color = tuple(config['board_color']) board = Board(self.board_width / 2, self.board_height / 2, self.board_width, self.board_height, board_color) self.static_obstacles.append(board) for robot_conf in config['robots']: self.robots.append(RobotState(robot_conf)) edge = Edge(self.board_width, self.board_height) self.static_obstacles.append(edge) self.falling_obstacles.append(edge) for obstacle in config['obstacles']: if obstacle['type'] == 'lake': lake = Lake.from_config(obstacle) self.static_obstacles.append(lake) if lake.hole is not None: self.falling_obstacles.append(lake.hole) self.color_obstacles.append(lake) elif obstacle['type'] == 'rock': rock = Rock.from_config(obstacle) self.obstacles.append(rock) elif obstacle['type'] == 'border': border = Border.from_config(self.board_width, self.board_height, obstacle) self.static_obstacles.append(border) self.color_obstacles.append(border) elif obstacle['type'] == 'bottle': bottle = Bottle.from_config(obstacle) self.obstacles.append(bottle) else: print("unknown obstacle type") self.falling_obstacles.append(board) self.color_obstacles.append(board) self.selected_object = None def reset(self): """ Reset all obstacles in the world (except robots) to their original position. """ for obstacle in self.obstacles: obstacle.reset() def setup_pymunk_shapes(self, scale): """ Setup the shapes that are added to the pymunk space. The robot get a shape filter so it does not interact with itself. """ for idx, robot in enumerate(self.robots): robot_shapes = robot.setup_pymunk_shapes(scale) for shape in robot_shapes: shape.filter = pymunk.ShapeFilter(group=idx + 5) self.space.add(shape) self.space.add(robot.body) for obstacle in self.obstacles: obstacle.create_shape(scale) self.space.add(obstacle.body) self.space.add(obstacle.shape) def rescale(self, new_scale): """ On screen rescale, rescale all sprites. """ for robot in self.robots: robot.shapes = [] for obstacle in self.obstacles: obstacle.shape = None self.space.remove(self.space.shapes) self.space.remove(self.space.bodies) for robot in self.robots: robot.sprite_list = _arcade.SpriteList() self.sprite_list = _arcade.SpriteList() self.setup_pymunk_shapes(new_scale) self.setup_visuals(new_scale) def setup_visuals(self, scale): """ Setup all sprites. """ for obstacle in self.static_obstacles: obstacle.create_shape(scale) for obstacle in self.obstacles: obstacle.create_sprite(scale) self.sprite_list.append(obstacle.sprite) for robot in self.robots: robot.setup_visuals(scale) robot.set_color_obstacles(self.color_obstacles) robot.set_falling_obstacles(self.falling_obstacles) def set_object_at_position_as_selected(self, pos): """ Based on the position given, select the object that is closest (with a maximum of 15) and set as selected. """ max_distance = 15 queried_object = self.space.point_query_nearest( pos, max_distance, pymunk.ShapeFilter()) if queried_object is not None: poly = queried_object.shape if hasattr(poly, 'body'): self.selected_object = poly.body def move_selected_object(self, delta_x, delta_y): """ Move the selected object with the given offset. """ if self.selected_object: self.selected_object.position += (delta_x, delta_y) def rotate_selected_object(self, delta_angle): """ Rotate the selected object with the given angle. """ if self.selected_object is not None: self.selected_object.angle += radians(delta_angle) def unselect_object(self): """ Deselect the previously selected object. """ self.selected_object = None def get_robots(self) -> [RobotState]: """ Gets the objects that are on the playing field. """ return self.robots
class World(PyxelWorld): def __init__(self): super().__init__() self.space = Space(threaded=True) self.space.collision_slop = 0.7 self.iter = 0 self.time = 0.0 self.on_reset = [] self.P, self.I, self.D = 4.25347222, 0.0001041666, -4.67881944 self.I = 0.0 y = 0 L = 500 self.ground = self.line(-L, y, L, y, static=True, friction=0.75, radius=5) handler = self.space.add_wildcard_collision_handler(1) handler.begin = self.on_collision def update(self): dt = 1 / 30 with LOCK: self.space.step(dt) self.time += dt def on_collision(self, arbiter, space, data): for fn in self.on_reset: fn(self) return True def reset(self): global segway self.time = 0.0 self.iter += 1 self.clear() ctrl.object = segway = self.segway() def clear(self): for shape in self.space.shapes: if shape not in self.ground.shapes: self.space.remove(shape) for cons in self.space.constraints: self.space.remove(cons) for body in self.space.bodies: if body is not self.ground: self.space.remove(body) def segway(self): R = 12 L = 60 segway = self.circ(0, R, R, mass=1, moment=1, friction=2.0) arm = self.line(0, R, 0, R + L, mass=2, moment=50) head = self.circ(0, R + L, R, mass=8, moment=8, velocity=(-1, 0), friction=0.1) self.pin([head, arm], collide=False) next(iter(head.shapes)).collision_type = 1 self.pin([segway, arm], anchor=(0, -L / 2), collide=False) segway.update = iter(self.pid(segway, arm)).__next__ segway.radius = R segway.arm = arm segway.head = head return segway def pid(self, wheel, arm): P, I, D = self.P, self.I, self.D cte = 100 R = wheel.radius err_ = 0.0 err_i = 0.0 gamma = 0.02 while True: err = arm.angle err_i = err + 0.9 * err_i err_d = err - err_ w = cte * (P * err - I * err_i - D * err_d) if w == 0: F = 0 else: F = 100 * (1 if w > wheel.angular_velocity else -1) F -= gamma * abs(F) * wheel.angular_velocity wheel.apply_force_at_local_point((0, +F), (+R, 0)) wheel.apply_force_at_local_point((0, -F), (-R, 0)) err_ = err yield
class PlatformerScene(Scene): def __init__(self, game): super().__init__(game) self.player = None self.active = True self.geometry = list() self.space = Space() self.space.gravity = (0, 1000) self.sprites = LayeredUpdates() self.event_handler = event_handling.EventQueueHandler() self.background = resources.gfx("background.png", convert=True) self.load() pygame.mixer.music.load(resources.music_path("zirkus.ogg")) pygame.mixer.music.play(-1) def add_static(self, vertices, rect): body = pymunk.Body(body_type=pymunk.Body.STATIC) body.position = rect.x, rect.y shape = pymunk.Poly(body, vertices) shape.friction = 1.0 shape.elasticity = 1.0 self.space.add(body, shape) def load(self): def box_vertices(x, y, w, h): lt = x, y rt = x + w, y rb = x + w, y + h lb = x, y + h return lt, rt, rb, lb filename = path_join("data", "maps", "untitled.tmx") tmxdata = pytmx.util_pygame.load_pygame(filename) for obj in tmxdata.objects: if obj.type == map_fixed: rect = Rect(obj.x, obj.y, obj.width, obj.height) vertices = box_vertices(0, 0, obj.width, obj.height) self.add_static(vertices, rect) elif obj.type == map_yarn_spawn: ball = sprite.Ball(Rect((obj.x, obj.y), (32, 32))) model = BasicModel() model.sprites = [ball] model.pymunk_objects = ball.pymunk_shapes self.add_model(model) self.player = model elif obj.type == map_player_spawn: self.player = unicyclecat.build(self.space, self.sprites) self.player.position = obj.x, obj.y self.fsm = SimpleFSM(control, "idle") def add_model(self, model): self.sprites.add(*model.sprites) self.space.add(model.pymunk_objects) def remove_model(self, model): self.sprites.remove(*model.sprites) self.space.remove(model.pymunk_objects) def render(self): surface = self._game.screen surface.blit(self.background, (0, 0)) self.sprites.draw(surface) return [surface.get_rect()] def tick(self, dt): step_amount = (1 / 30.) / 30 for i in range(30): self.space.step(step_amount) self.sprites.update(dt) def event(self, pg_event): events = self.event_handler.process_event(pg_event) position = self.player.position for event in events: try: cmd, arg = self.fsm((event.button, event.held)) except ValueError as e: continue if cmd == "move": resources.sfx("cat_wheel.ogg", False, True) resources.sfx("cat_wheel.ogg", True) self.player.accelerate(arg) if cmd == "idle": self.player.brake() elif cmd == "jump": resources.sfx("cat_jump.ogg", True) self.player.main_body.apply_impulse_at_world_point((0, -600), position)
def pre_solve(arb: p.Arbiter, space: p.Space, data: Any) -> bool: space.remove(*arb.shapes) return True
def pre_solve_remove(arb: p.Arbiter, space: p.Space, data: Any) -> bool: space.remove(b, c) space.remove(c, b) self.assertTrue(b in s.bodies) self.assertTrue(c in s.shapes) return True