def init_space(): sp = Space() # Cria quadrado L = 5 player = Body(mass=1, moment=100) shape = Poly(player, [(-L, -L), (L, -L), (L, L), (-L, L)]) player.position = (50, 40) player.velocity = (-25, 25) shape.elasticity = 1.0 shape.color = pyxel.COLOR_RED # Cria margens line = Body(body_type=Body.STATIC) lines = [ Segment(line, (-30, -30), (270, -30), 2), Segment(line, (-30, 210), (270, 210), 2), Segment(line, (-30, -30), (-30, 210), 2), Segment(line, (270, -30), (270, 210), 2), ] for line in lines: line.elasticity = 1.0 # Adiciona elementos ao espaço sp.add(player, shape, *lines) sp.player = player return sp
def __addBoundaries(space: pymunk.Space): global floor1_1, floor1_2 floor1_1 = pymunk.Body(body_type=pymunk.Body.KINEMATIC) floor1_1.velocity = (-groundSpeed, 0) floor1_1.position = (windowSize[0] / 2, windowSize[1]) shape1_1 = pymunk.Segment(floor1_1, (-500, 0), (500, 0), 10) shape1_1.color = (0, 0, 255, 255) shape1_1.friction = 0.69 floor1_2 = pymunk.Body(body_type=pymunk.Body.KINEMATIC) floor1_2.velocity = (-groundSpeed, 0) floor1_2.position = (windowSize[0] + 500, windowSize[1]) shape1_2 = pymunk.Segment(floor1_2, (-500, 0), (500, 0), 10) shape1_2.friction = 0.69 floor2 = pymunk.Body(body_type=pymunk.Body.STATIC) shape2 = pymunk.Segment(floor2, (0, 0), (windowSize[0], 0), 10) shape2.friction = 1.00 floor3 = pymunk.Body(body_type=pymunk.Body.STATIC) shape3 = pymunk.Segment(floor3, (0, 0), (0, windowSize[1]), 10) shape3.friction = 1.00 shape3.color = (255, 0, 0, 255) shape3._set_collision_type(1) floor4 = pymunk.Body(body_type=pymunk.Body.STATIC) shape4 = pymunk.Segment(floor4, (windowSize[0], 0), (windowSize[0], windowSize[1]), 10) shape4.friction = 1.00 space.add(floor1_1, shape1_1, floor1_2, shape1_2, floor2, shape2, floor3, shape3, floor4, shape4)
def build_grid(self, space: pymunk.Space, collision_type_for_brick, collision_type_for_ball, aspect_ratio): grid_position = aspect_ratio.scale(90, 500) brick_size = aspect_ratio.scale(100, 16) brick_width = brick_size.x brick_height = brick_size.y space_between_brick = aspect_ratio.scale(10, 14) x_space_between_brick = space_between_brick.x brick_step_x = brick_width + x_space_between_brick y_space_between_brick = space_between_brick.y brick_step_y = brick_height + y_space_between_brick for x in range(10): pos_x = grid_position.x + x * brick_step_x for y in range(10): pos_y = grid_position.y + y * brick_step_y # http://www.pymunk.org/en/latest/pymunk.html#pymunk.Body.__init__ body = pymunk.Body(body_type=pymunk.Body.KINEMATIC) # position body.position = pos_x, pos_y # shape shape = pymunk.Segment(body, (0, 0), aspect_ratio.scale(100, 0), 8) shape.elasticity = 0.98 shape.collision_type = collision_type_for_brick space.add(body, shape) handler = space.add_collision_handler(collision_type_for_brick, collision_type_for_ball) # http://www.pymunk.org/en/latest/pymunk.html#pymunk.CollisionHandler.separate handler.separate = self._cb_remove_brick
class World(object): def __init__(self, debug_draw=None): self.space = Space() self.debug_draw = debug_draw def step(self, elapsed): if self.debug_draw: self.debug_draw.pre_world_step() self.space.step(elapsed) if self.debug_draw: for shape in self.space.shapes: if isinstance(shape, Poly): self.debug_draw.DrawPolygon(shape) for body in self.space.bodies: body.reset_forces() def add(self, body_or_joint, shape=None): if shape is not None: self.space.add(body_or_joint, shape) else: self.space.add(body_or_joint) def render(self): if self.debug_draw: self.debug_draw.render()
def mark_startingpoint(space: pymunk.Space, sp: SegmentPart) -> None: """Draw Car Simulation Starting point and indicate Starting Direction.""" start_body = pymunk.Body(body_type=pymunk.Body.STATIC) starting_dot = pymunk.Circle(start_body, 6, offset=to_pygame(sp.start)) starting_dot.collision_type = COLLISION_TYPES['start'] space.add(starting_dot)
def static_circ(x: int, y: int, r: int, col: int, space: pymunk.Space, **kwargs): pyxel.circ(x, y, r, col) body = pymunk.Body(body_type=pymunk.Body.STATIC) body.position = (x, y) s = pymunk.Circle(body, radius=r) for k, v in kwargs.items(): setattr(s, k, v) space.add(s)
def create_segment(space: pymunk.Space, segment: Segment) -> None: """Create walls in space.""" seg_body = pymunk.Body(body_type=pymunk.Body.STATIC) for seg_part in segment: seg_shape = pymunk.Segment(seg_body, to_pygame(seg_part.start), to_pygame(seg_part.end), 3) seg_shape.elasticity = 0 seg_shape.collision_type = COLLISION_TYPES['wall'] space.add(seg_shape)
def __init__( self, space: pymunk.Space, paddle_position: Vec2d, collision_type: CollisionType, aspect_ratio: AspectRatio, mass: float = 1, paddle: Paddle = None, ): """ :param space: :param paddle_position: :param collision_type: :param aspect_ratio: :param mass: :param paddle: """ super().__init__(mass=mass, moment=pymunk.inf) self.aspect_ratio = aspect_ratio self.radius = 16 paddle_height = 16 paddle_half_height = paddle_height ball_position = Vec2d( paddle_position.x, paddle_position.y + aspect_ratio.scale_s(paddle_half_height + self.radius)) self.position = ball_position shape = pymunk.Circle(self, radius=aspect_ratio.scale_s(self.radius)) shape.elasticity = 0.98 shape.collision_type = collision_type shape.filter = pymunk.ShapeFilter(categories=2 << collision_type) self.spc = space self.on_paddle = True self.velocity_func = self.constant_velocity self.joint = pymunk.GrooveJoint( space.static_body, self, Vec2d(paddle.groove_joint.groove_a.x, ball_position.y), Vec2d(paddle.groove_joint.groove_b.x, ball_position.y), Vec2d(0, 0), ) space.add(self, shape, self.joint) self.ball_speed = 500 self.segments_q = [] self.points_on_ball = []
def __init__(self, space: pymunk.Space, collision_type: CollisionType, aspect_ratio, mass=10): """ :param space: :param collision_type: :param aspect_ratio: :param mass: """ super().__init__(mass=mass, moment=pymunk.inf) wall_left = 50 wall_right = 1230 wall_bottom = 50 paddle_width = 100 paddle_height = 16 paddle_half_width = paddle_width // 2 paddle_half_height = paddle_height // 2 paddle_position = Vec2d(640, wall_bottom + paddle_height * 3) self.position = aspect_ratio.scale_V2d(paddle_position) shape = pymunk.Segment(self, aspect_ratio.scale(-paddle_half_width, 0), aspect_ratio.scale(+paddle_half_width, 0), aspect_ratio.scale_s(paddle_half_height)) # Don't work with custom pre_solve collision handler (this solver suppose a segment and not # a polygonal shape). Need to fix that ! # shape = pymunk.Poly.create_box(self, (paddle_width, paddle_height)) shape.elasticity = 1.00 shape.collision_type = collision_type shape.filter = pymunk.ShapeFilter(categories=2 << collision_type) self.groove_joint = GroovJoint( aspect_ratio.scale(wall_left + paddle_half_width * 1.50, paddle_position.y), aspect_ratio.scale(wall_right - paddle_half_width * 1.50, paddle_position.y), ) self.joint = pymunk.GrooveJoint( space.static_body, self, self.groove_joint.groove_a, self.groove_joint.groove_b, self.groove_joint.anchor, ) space.add(self, shape, self.joint)
def static_rect(x: int, y: int, w: int, h: int, col: int, space: pymunk.Space, **kwargs): """ Draws a static rectb with collisions. :return: :param kwargs: addition keyword args for Poly. Check pymonk.Poly docs for that. Exmaple: friction """ pyxel.rect(x, y, w, h, col) body = pymunk.Body(body_type=pymunk.Body.STATIC) body.position = (x + w // 2, y + h // 2) # pymunk uses gravity center # No extra body because it's static without any properties s = pymunk.Poly.create_box(body, size=(w, h)) for k, v in kwargs.items(): setattr(s, k, v) space.add(s)
def init_space(): sp = Space() player = Body(mass=1, moment=1) shape = Circle(player, 10) player.position = (20, 90) player.velocity = (5, 0) shape.color = pyxel.COLOR_YELLOW line = Body(body_type=Body.STATIC) line_shape = Segment(line, (0, 1), (240, 1), 2) line_shape.color = pyxel.COLOR_RED sp.add(player, shape, line, line_shape) sp.player = player return sp
def build_dynamic_grid(self, space: pymunk.Space, collision_type_for_brick, collision_type_for_ball, aspect_ratio): wall_left = 50 wall_right = 1230 grid_left_corner = aspect_ratio.scale(wall_left + 40, 500) grid_right_corner = aspect_ratio.scale(wall_right - 40, 500 + (16 + 14) * 10 - 40) nb_bricks = Vec2d(12, 8) spaces_between_brick = aspect_ratio.scale_V2d(Vec2d(10, 14)) grid_size = grid_right_corner - grid_left_corner brick_size = ( grid_size - (nb_bricks - Vec2d(1, 1)) * spaces_between_brick) / nb_bricks brick_steps = brick_size + spaces_between_brick for x in range(nb_bricks.x): pos_x = grid_left_corner.x + x * brick_steps.x for y in range(nb_bricks.y): pos_y = grid_left_corner.y + y * brick_steps.y # https://github.com/viblo/pymunk/blob/master/examples/breakout.py # http://www.pymunk.org/en/latest/pymunk.html#pymunk.Body.__init__ brick_body = pymunk.Body(body_type=pymunk.Body.KINEMATIC) # position brick_body.position = Vec2d(pos_x, pos_y) + brick_size * 0.5 brick_shape = pymunk.Poly.create_box(brick_body, brick_size) brick_shape.elasticity = 0.98 brick_shape.collision_type = collision_type_for_brick brick_shape.filter = pymunk.ShapeFilter( categories=2 << collision_type_for_brick) space.add(brick_body, brick_shape) handler = space.add_collision_handler(collision_type_for_brick, collision_type_for_ball) # http://www.pymunk.org/en/latest/pymunk.html#pymunk.CollisionHandler.separate handler.separate = self._cb_remove_brick
def test_add_to_body(self): disc = Disc(gold, 5, (1, 2)) body = Body(0, 0) space = Space() space.add(body) disc.add_to_body(space, body) self.assertNotNone(disc.shape, "didnt create shape") self.assertEquals(disc.shape.body, body, "didnt add shape to body") self.assertEquals(disc.shape.radius, 5.0, "bad radius") self.assertEquals(disc.shape.center, Vec2d(1.0, 2.0), "bad center") self.assertAlmostEquals(disc.shape.friction, gold.friction, msg="bad friction") self.assertAlmostEquals(disc.shape.elasticity, gold.elasticity, msg="bad elasticity") self.assertEquals(space.shapes, [disc.shape], "didn't add shape to space")
def create_car(self, space: pymunk.Space, sp: SegmentPart, mass=20): """Create a car body and add to Space.""" vertices = [(0, 0), (CAR_SIZE[0], 0), (CAR_SIZE[0], CAR_SIZE[1]), (0, CAR_SIZE[1])] inertia = pymunk.moment_for_poly(mass, vertices) angle = calc_radians_between(sp.start, sp.end) body = pymunk.Body(mass, inertia) body.angle = angle body.position = to_pygame(sp.start) body.velocity = calc_heading_vector(angle) * 0 shape = pymunk.Poly(body, vertices) shape.elasticity = 0 shape.collision_type = COLLISION_TYPES['car'] space.add(body, shape) return shape
class World(object): "Container for everything in the model, eg: Rooms and Chunks" def __init__(self): # pylint: disable-msg=W0212 # Access to a protected member '_space': ack init_pymunk() self.space = Space() self.space.gravity = (0, 0) self.space._space.contents.elasticIterations = 10 self.static_body = Body(inf, inf) self.rooms = {} self.ents = set() self.chunks = set() self.player = None self.material = granite def add_to_pymunk(self): for room in self.rooms.itervalues(): room.add_to_body(self.space, self.static_body) def add_chunk(self, chunk, position, angle=0): chunk.add_to_space(self.space, position, angle) self.chunks.add(chunk) def add_ent(self, ent, position, angle=0.0): ent.body.position = position ent.body.angle = angle self.space.add(ent.body) for shape in ent.shapes: self.space.add(shape) self.ents.add(ent) def tick(self, delta_t): if hasattr(self, 'player'): self.player.move() self.space.step(delta_t)
def __init__(self, space: pymunk.Space, collision_type_for_ball, collision_type_for_bottom, cb_loose_ball, aspect_ratio): """ :param space: :param collision_type_for_ball: :param collision_type_for_bottom: :param cb_loose_ball: call back function to reset game """ left = pymunk.Segment(space.static_body, aspect_ratio.scale(50, 50), aspect_ratio.scale(50, 800), 2) top = pymunk.Segment(space.static_body, aspect_ratio.scale(50, 800), aspect_ratio.scale(1230, 800), 2) right = pymunk.Segment(space.static_body, aspect_ratio.scale(1230, 50), aspect_ratio.scale(1230, 800), 2) left.elasticity = 1.0 right.elasticity = 1.0 top.elasticity = 1.0 bottom = pymunk.Segment(space.static_body, aspect_ratio.scale(50, 50), aspect_ratio.scale(1230, 50), 2) bottom.sensor = True bottom.collision_type = collision_type_for_bottom left.filter = pymunk.ShapeFilter( categories=2 << collision_type_for_bottom) right.filter = pymunk.ShapeFilter( categories=2 << collision_type_for_bottom) top.filter = pymunk.ShapeFilter( categories=2 << collision_type_for_bottom) bottom.filter = pymunk.ShapeFilter( categories=2 << collision_type_for_bottom) # http://www.pymunk.org/en/latest/pymunk.html#pymunk.CollisionHandler handler = space.add_collision_handler(collision_type_for_ball, collision_type_for_bottom) handler.begin = self.reset_game self.cb_loose_ball = cb_loose_ball space.add(left, top, right, bottom)
def init_space(): sp = Space() sp.gravity = (0, 50) sp.damping = 1.0 floor = Body(body_type=Body.STATIC) stick = Body(mass=100, moment=100 * 50**2) L = 20 shapes = [ Poly(stick, [(-L, -L), (L, -L), (L, L), (0, L + L / 2), (-L, L)], radius=3), Segment(floor, (1, 179), (239, 179), 1), Segment(floor, (1, 1), (239, 1), 1), Segment(floor, (1, 1), (1, 179), 1), Segment(floor, (239, 1), (239, 179), 1), ] stick.position = (120, L) bodies = [] for _ in range(L): r = random.uniform(2, 6) mass = pi * r**2 body = Body(mass=mass, moment=mass * r**2 / 2) circle = Circle(body, r) x = random.uniform(r, 240 - r) y = random.uniform(r, 180 - r) body.position = (x, y) vx = random.uniform(-L, L) vy = random.uniform(-L, L) body.velocity = (vx, vy) bodies.append(body) shapes.append(circle) circle.color = random.randint(1, 15) for shape in shapes: shape.elasticity = 1.0 sp.add(floor, stick, *bodies, *shapes) return sp
def init_game(): sp = Space() # sp.gravity = (0,90) # sp.damping = 0.8 # Add Cat to Space generate_cat(sp) # Add pickle to Space generate_pickles(sp) # Add star to Space generate_stars(sp) # Add floor to Space floor = Body(body_type=Body.STATIC) floor_shape = Floor(floor, (0, SCREEN_H - 1), (SCREEN_W, SCREEN_H - 1), 1) floor_shape.elasticity = 0.7 sp.add(floor, floor_shape) return sp
class World(object): def __init__(self): self.items = [] self.words = [] self.springs = [] init_pymunk() self.space = Space() self.space.resize_static_hash() self.space.resize_active_hash() def add_item(self, item): ## self.items.append(item) self.space.add(item.shape) self.space.add(item.body) def add_spring(self, spring): self.springs.append(spring) self.space.add(spring) def add_word(self, word): self.words.append(word) def update(self): self.space.step(1.0)
class PhysicsWorld(object): def __init__(self): self.space = None def init(self): init_pymunk() self.space = Space() self.space.gravity = (0, -0.002) self.space.resize_static_hash() self.space.resize_active_hash() def add(self, item, position, static): item.body.position = position if static: self.space.add_static(item.shape) else: self.space.add(item.body) self.space.add(item.shape) if item.rest_angle_spring: self.space.add(item.rest_angle_spring) def update(self, items): for item in items.itervalues(): item.physics.update() self.space.step(1)
def create(self, space: pymunk.Space): Creature.__create(self.limbs, space, True) space.add(self.body, self.shape) Creature.__create(self.limbs, space, False) for pivot in self.pivots: space.add(pivot) for muscle in self.muscles: space.add(muscle)
def add_rects_to_space(space: pymunk.Space, rects: list) -> list: """This function should executed ONCE""" for rect in rects: def zero_gravity(body, gravity, damping, dt): pymunk.Body.update_velocity(body, (0, 0), damping, dt) _w, _h = rect[0].width, rect[0].height rect_b = pymunk.Body(1, 2, body_type=pymunk.Body.STATIC) rect_b.position = rect[0].x + _w / 2, rect[0].y + _h / 2 rect_b.gameden = {"tile_id": rect[1]} rect_poly = pymunk.Poly(rect_b, [(-_w / 2, -_h / 2), (_w / 2, -_h / 2), (_w / 2, _h / 2), (-_w / 2, _h / 2)]) rect_poly.friction = 0.8 rect_poly.gameden = {"tile_id": rect[1]} space.add(rect_b, rect_poly) rect_b.velocity_func = zero_gravity rect.append(rect_b) rect.append(rect_poly) return rects
def draw_sensor(self, space: pymunk.Space, sensor_size: int = 10) -> pymunk.Shape: """Create Cross for Car Sensors.""" cross_body = pymunk.Body(body_type=pymunk.Body.DYNAMIC) line_one = pymunk.Segment(cross_body, self.position + Coordinate(0, sensor_size), self.position + Coordinate(sensor_size, 0), 2) line_two = pymunk.Segment( cross_body, self.position, self.position + Coordinate(sensor_size, sensor_size), 2) line_one.color, line_two.color = pygame.color.THECOLORS[ 'green'], pygame.color.THECOLORS['green'] line_one.collision_type, line_two.collision_type = COLLISION_TYPES[ 'sensor'], COLLISION_TYPES['sensor'] line_one.sensor, line_two.sensor = True, True space.add([line_one, line_two]) return line_one, line_two
def init_space(): sp = Space() h = 20 * sqrt(2) player = Body(mass=1, moment=400) shape = Poly(player, [(-20, -h / 3), (20, -h / 3), (0, 2 / 3 * h)]) player.position = (90, 90) shape.elasticity = 1.0 shape.color = pyxel.COLOR_YELLOW line = Body(body_type=Body.STATIC) lines = [ Segment(line, (0, 1), (240, 1), 2), Segment(line, (0, 179), (240, 179), 2), Segment(line, (1, 0), (1, 180), 2), Segment(line, (239, 0), (239, 180), 2), ] for line in lines: line.elasticity = 1.0 line.color = pyxel.COLOR_PEACH sp.add(player, shape, *lines) sp.player = player return sp
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 PymunkSimulation: def __init__(self, do_render, sparse, max_motor_force): self.do_render = do_render self.sparse = sparse self.max_motor_force = max_motor_force if self.do_render: pygame.init() self.screen = pygame.display.set_mode((ENV_SIZE, ENV_SIZE)) self.draw_options = pygame_util.DrawOptions(self.screen) self.clock = pygame.time.Clock() self.motors = [] self.segment_bodies = [] self.space = Space() self.space.iterations = 20 no_collision = self.space.add_collision_handler(NO_COLLISION_TYPE, NO_COLLISION_TYPE) no_collision.begin = lambda a, b, c: False ghost_collision = self.space.add_wildcard_collision_handler(GHOST_TYPE) ghost_collision.begin = lambda a, b, c: False def set_motor_rates(self, motor_rates): for i, motor in enumerate(self.motors): motor.rate = motor_rates[i] def set_motor_max_forces(self, motor_forces): for i, motor in enumerate(self.motors): motor.max_force = motor_forces[i] def step(self): dt = 0.03 steps = 30 for i in range(steps): self.space.step(dt / steps) def add_arm(self, segment_lengths, anchor_position): anchor = pymunk.Body(body_type=pymunk.Body.STATIC) anchor.position = anchor_position self.space.add(anchor) segment_anchor = anchor next_anchor_pos = anchor_position for i, segment_length in enumerate(segment_lengths): segment_size = segment_length, 10 segment_body = pymunk.Body(10, pymunk.moment_for_box(10, segment_size)) end_effector_shape = pymunk.Poly.create_box(segment_body, segment_size) end_effector_shape.collision_type = NO_COLLISION_TYPE end_effector_shape.friction = 1.0 end_effector_shape.elasticity = 0.1 alpha = random.random() * math.pi * 2 dx = np.cos(alpha) * segment_length / 2 dy = np.sin(alpha) * segment_length / 2 segment_body.position = next_anchor_pos[0] - dx, next_anchor_pos[1] - dy next_anchor_pos = (next_anchor_pos[0] - 2 * dx, next_anchor_pos[1] - 2 * dy) segment_body.angle = alpha anchor_pin_pos = (0 if i == 0 else -segment_lengths[i - 1] / 2, 0) pin = pymunk.PinJoint(segment_anchor, segment_body, anchor_pin_pos, (segment_length / 2, 0)) self.space.add(pin) self.space.add(segment_body, end_effector_shape) motor = pymunk.SimpleMotor(segment_anchor, segment_body, 0) motor.max_force = self.max_motor_force self.space.add(motor) self.motors.append(motor) self.segment_bodies.append(segment_body) segment_anchor = segment_body return segment_anchor, next_anchor_pos
class Simulator(arcade.Window): def __init__(self, robot_state: RobotState, robot_pos: Tuple[int, int, int], show_fullscreen: bool, show_maximized: bool, use_second_screen_to_show_simulator: bool): self.check_for_unique_instance() self.robot_state = robot_state self.set_screen_to_display_simulator_at_startup( use_second_screen_to_show_simulator) self.scaling_multiplier = get_config().get_scale() self.large_sim_type = get_config().is_large_sim_type() self.cfg = get_config().get_data() self.screen_total_width = int( apply_scaling(self.cfg['screen_settings']['screen_total_width'])) self.screen_width = int( apply_scaling(self.cfg['screen_settings']['screen_width'])) self.screen_height = int( apply_scaling(self.cfg['screen_settings']['screen_height'])) from ev3dev2.version import __version__ as apiversion from ev3dev2simulator.version import __version__ as simversion screen_title = self.cfg['screen_settings'][ 'screen_title'] + " version: " + simversion + " ev3dev2 api: " + apiversion self.frames_per_second = self.cfg['exec_settings']['frames_per_second'] self.falling_msg = self.cfg['screen_settings']['falling_message'] self.restart_msg = self.cfg['screen_settings']['restart_message'] super(Simulator, self).__init__(self.screen_total_width, self.screen_height, screen_title, update_rate=1 / 30, resizable=True) icon1 = pyglet.image.load(r'assets/images/body.png') self.set_icon(icon1) arcade.set_background_color( eval(self.cfg['screen_settings']['background_color'])) self.robot_elements = None self.obstacle_elements = None self.robot = None self.robot_pos = robot_pos self.red_lake = None self.green_lake = None self.blue_lake = None self.rock1 = None self.rock2 = None self.bottle1 = None self.border = None self.edge = None self.ground = None self.space = None self.center_cs_data = 0 self.left_cs_data = 0 self.right_cs_data = 0 self.left_ts_data = False self.right_ts_data = False self.front_us_data = -1 self.rear_us_data = -1 self.text_x = self.screen_width - apply_scaling(220) self.msg_x = self.screen_width / 2 self.msg_counter = 0 self.setup() if show_fullscreen == True: self.toggleFullScreenOnCurrentScreen() if show_maximized == True: self.maximize() self.check_for_activation() def get_screens(self): display = pyglet.canvas.get_display() screens = display.get_screens() return screens def set_screen_to_display_simulator_at_startup( self, use_second_screen_to_show_simulator): """ Set screen to use to display the simulator at startup. For windows this works only in fullscreen mode. By default set current screen to show simulator, but if use_second_screen_to_show_simulator==True then change screen to other screen. On MacOS this works for both fullscreen and none-fullscreen mode. On Windows this only works for fullscreen mode. For none-fullscreen always the first screen is used. """ # get current_screen_index current_screen_index = 0 if use_second_screen_to_show_simulator == True: current_screen_index = 1 screens = self.get_screens() for screen in screens: print(screen) num_screens = len(screens) if num_screens == 1: current_screen_index = 0 self.current_screen_index = current_screen_index # change screen to show simulator # HACK override default screen function to change it. # Note: arcade window class doesn't has the screen parameter which pyglet has, so by overriding # the get_default_screen method we can still change the screen parameter. def get_default_screen(): """Get the default screen as specified by the user's operating system preferences.""" return screens[self.current_screen_index] display = pyglet.canvas.get_display() display.get_default_screen = get_default_screen # note: # for macos get_default_screen() is also used to as the screen to draw the window initially # for windows the current screen is used to to draw the window initially, # however the value set by get_default_screen() is used as the screen # where to display the window fullscreen! # note: BUG: dragging window to other screen in macos messes up view size # for Macos the screen of the mac can have higher pixel ratio (self.get_pixel_ratio()) # then the second screen connected. If you drag the window from the mac screen to the # second screen then the windows may be the same size, but the simulator is drawn in only # in the lower left quart of the window. # => we need somehow make drawing of the simulator larger # how to view simulator window on second screen when dragging not working? # SOLUTION: just when starting up the simulator set it to open on the second screen, # then it goes well, and you can also open it fullscreen on the second screen # see also : https://stackoverflow.com/questions/49302201/highdpi-retina-windows-in-pyglet def check_for_unique_instance(self): """ Detect whether an other instance is already running. If so then trigger the activation for the other instance and terminate this instance. """ tmpdir = tempfile.gettempdir() self.pidfile = os.path.join(tmpdir, "ev3dev2simulator.pid") self.pid = str(os.getpid()) f = open(self.pidfile, 'w') f.write(self.pid) f.flush() f.close() time.sleep(2) file = open(self.pidfile, 'r') line = file.readline() file.close() read_pid = line.rstrip() if read_pid != self.pid: # other process already running sys.exit() def check_for_activation(self): """ checks each interval whether the simulator windows must be activated (bring to front) note: activation can happen when one tries to start another instance of the simulator, and that instance detects an instance is already running. It then triggers the activation for the other instance and terminates itself. """ from pyglet import clock def callback(dt): file = open(self.pidfile, 'r') line = file.readline() file.close() read_pid = line.rstrip() if read_pid != self.pid: # other simulator tries to start running # write pid to pidfile to notify this simulator is already running f = open(self.pidfile, 'w') f.write(self.pid) f.close() import platform if platform.system().lower().startswith('win'): self.windowsActivate() else: self.activate() clock.schedule_interval(callback, 1) def windowsActivate(self): from pyglet.libs.win32 import _user32 from pyglet.libs.win32.constants import SW_SHOWMINIMIZED, SW_SHOWNORMAL _user32.ShowWindow(self._hwnd, SW_SHOWMINIMIZED) _user32.ShowWindow(self._hwnd, SW_SHOWNORMAL) def setup(self): """ Set up all the necessary shapes and sprites which are used in the simulation. These elements are added to lists to make buffered rendering possible to improve performance. """ self.robot_elements = arcade.SpriteList() self.obstacle_elements = arcade.ShapeElementList() if self.large_sim_type: self.robot = RobotLarge(self.cfg, self.robot_pos[0], self.robot_pos[1], self.robot_pos[2]) else: self.robot = RobotSmall(self.cfg, self.robot_pos[0], self.robot_pos[1], self.robot_pos[2]) for s in self.robot.get_sprites(): self.robot_elements.append(s) for s in self.robot.get_sensors(): self.robot_state.load_sensor(s) self.blue_lake = BlueLake(self.cfg) self.green_lake = GreenLake(self.cfg) self.red_lake = RedLake(self.cfg) self.obstacle_elements.append(self.blue_lake.shape) self.obstacle_elements.append(self.green_lake.shape) self.obstacle_elements.append(self.red_lake.shape) self.border = Border( self.cfg, eval(self.cfg['obstacle_settings']['border_settings'] ['border_color'])) self.edge = Edge(self.cfg) for s in self.border.shapes: self.obstacle_elements.append(s) self.space = Space() if self.large_sim_type: self.rock1 = Rock(apply_scaling(825), apply_scaling(1050), apply_scaling(150), apply_scaling(60), arcade.color.DARK_GRAY, 10) self.rock2 = Rock(apply_scaling(975), apply_scaling(375), apply_scaling(300), apply_scaling(90), arcade.color.DARK_GRAY, 130) self.ground = arcade.create_rectangle(apply_scaling(1460), apply_scaling(950), apply_scaling(300), apply_scaling(10), arcade.color.BLACK) self.obstacle_elements.append(self.rock1.shape) self.obstacle_elements.append(self.rock2.shape) self.obstacle_elements.append(self.ground) touch_obstacles = [self.rock1, self.rock2] falling_obstacles = [ self.blue_lake.hole, self.green_lake.hole, self.red_lake.hole, self.edge ] self.space.add(self.rock1.poly) self.space.add(self.rock2.poly) else: self.bottle1 = Bottle(apply_scaling(1000), apply_scaling(300), apply_scaling(40), arcade.color.DARK_OLIVE_GREEN) self.obstacle_elements.append(self.bottle1.shape) touch_obstacles = [self.bottle1] falling_obstacles = [self.edge] self.space.add(self.bottle1.poly) color_obstacles = [ self.blue_lake, self.green_lake, self.red_lake, self.border ] self.robot.set_color_obstacles(color_obstacles) self.robot.set_touch_obstacles(touch_obstacles) self.robot.set_falling_obstacles(falling_obstacles) def on_close(self): sys.exit(0) def on_key_press(self, key, modifiers): """Called whenever a key is pressed. """ # Quit the simulator if key == arcade.key.Q: self.on_close() # Toggle fullscreen between screens (only works at fullscreen mode) if key == arcade.key.T: # User hits T. When at fullscreen, then switch screen used for fullscreen. if self.fullscreen and len(self.get_screens()) > 1: # to switch screen when in fullscreen we first have to back to normal window, and do fullscreen again self.set_fullscreen(False) # switch which screen is used for fullscreen ; Toggle between first and second screen (other screens are ignored) self.toggleScreenUsedForFullscreen() self.setFullScreen() # Maximize window # note: is toggle on macos, but not on windows if key == arcade.key.M: self.maximize() # Toggle between Fullscreen and window # keeps viewport coordinates the same STRETCHED (FULLSCREEN) # Instead of a one-to-one mapping to screen size, we use stretch/squash window to match the constants. # src: http://arcade.academy/examples/full_screen_example.html if key == arcade.key.F: self.updateCurrentScreen() self.toggleFullScreenOnCurrentScreen() #toggle screen for fullscreen # BUG: doesn't work on macos => see explaination in set_screen_to_display_simulator_at_startup() method def toggleScreenUsedForFullscreen(self): # toggle only between screen 0 and 1 (other screens are ignored) self.current_screen_index = (self.current_screen_index + 1) % 2 # override hidden screen parameter in window screens = self.get_screens() self._screen = screens[self.current_screen_index] def updateCurrentScreen(self): """ using the windows position and size we determine on which screen it is currently displayed and make that current screen for displaying in fullscreen!! """ screens = self.get_screens() if len(screens) == 1: return location = self.get_location() topleft_x = location[0] topleft_y = location[1] size = self.get_size() win_width = size[0] win_height = size[1] done = False locations = [ location, (topleft_x + win_width, topleft_y), (topleft_x, topleft_y + win_height), (topleft_x + win_width, topleft_y + win_height) ] for location in locations: if done: break loc_x = location[0] loc_y = location[1] num = 0 for screen in screens: within_screen_width = (loc_x >= screen.x) and ( loc_x < (screen.x + screen.width)) within_screen_height = (loc_y >= screen.y) and ( loc_y < (screen.y + screen.height)) if within_screen_width and within_screen_height: self.current_screen_index = num done = True break num = num + 1 # override hidden screen parameter in window self._screen = screens[self.current_screen_index] def toggleFullScreenOnCurrentScreen(self): # User hits 'f' Flip between full and not full screen. self.set_fullscreen(not self.fullscreen) # Instead of a one-to-one mapping, stretch/squash window to match the # constants. This does NOT respect aspect ratio. You'd need to # do a bit of math for that. self.set_viewport(0, self.screen_width, 0, self.screen_height) # HACK for macos: without this hack fullscreen on the second screen is shifted downwards in the y direction # By also calling the maximize function te position the fullscreen in second screen is corrected!) import platform if self.fullscreen and platform.system().lower() == "darwin": self.maximize() def setFullScreen(self): #self.fullscreen=True self.set_fullscreen(True) # Instead of a one-to-one mapping, stretch/squash window to match the # constants. This does NOT respect aspect ratio. You'd need to # do a bit of math for that. self.set_viewport(0, self.screen_width, 0, self.screen_height) # HACK for macos: without this hack fullscreen on the second screen is shifted downwards in the y direction # By also calling the maximize function te position the fullscreen in second screen is corrected!) import platform if platform.system().lower() == "darwin": self.maximize() def on_resize(self, width, height): """ This method is automatically called when the window is resized. """ # Call the parent. Failing to do this will mess up the coordinates, and default to 0,0 at the center and the # edges being -1 to 1. super().on_resize(width, height) #TODO: fix BUG with resize on large field # the resize works perfect with the small field # but with the large field when use set_viewport on then resize also works, BUT we loose the arm. Same happens when we change window to maximize or fullscreen! if not self.large_sim_type: self.set_viewport(0, self.screen_width, 0, self.screen_height) def on_draw(self): """ Render the simulation. This is done in 30 frames per second. """ arcade.start_render() self.obstacle_elements.draw() self.robot_elements.draw() if self.large_sim_type: self._draw_text_large_sim() else: self._draw_text_small_sim() def _draw_text_small_sim(self): """ Draw all the text fields. """ center_cs = 'CS: ' + str(self.center_cs_data) left_ts = 'TS right: ' + str(self.right_ts_data) right_ts = 'TS left: ' + str(self.left_ts_data) top_us = 'US: ' + str( int(round(self.front_us_data / self.scaling_multiplier))) + 'mm' message = self.robot_state.next_sound_job() sound = message if message else '-' arcade.draw_text(center_cs, self.text_x, self.screen_height - apply_scaling(80), arcade.color.BLACK_LEATHER_JACKET, 10) arcade.draw_text(left_ts, self.text_x, self.screen_height - apply_scaling(100), arcade.color.BLACK_LEATHER_JACKET, 10) arcade.draw_text(right_ts, self.text_x, self.screen_height - apply_scaling(120), arcade.color.BLACK_LEATHER_JACKET, 10) arcade.draw_text(top_us, self.text_x, self.screen_height - apply_scaling(140), arcade.color.BLACK_LEATHER_JACKET, 10) arcade.draw_text('Sound:', self.text_x, self.screen_height - apply_scaling(160), arcade.color.BLACK_LEATHER_JACKET, 10) arcade.draw_text(sound, self.text_x, self.screen_height - apply_scaling(180), arcade.color.BLACK_LEATHER_JACKET, 10, anchor_y='top') if self.msg_counter != 0: self.msg_counter -= 1 arcade.draw_text(self.falling_msg, self.msg_x, self.screen_height - apply_scaling(100), arcade.color.BLACK_LEATHER_JACKET, 14, anchor_x="center") arcade.draw_text(self.restart_msg, self.msg_x, self.screen_height - apply_scaling(130), arcade.color.BLACK_LEATHER_JACKET, 14, anchor_x="center") def _draw_text_large_sim(self): """ Draw all the text fields. """ center_cs = 'CS ctr: ' + str(self.center_cs_data) left_cs = 'CS left: ' + str(self.left_cs_data) right_cs = 'CS right: ' + str(self.right_cs_data) left_ts = 'TS right: ' + str(self.right_ts_data) right_ts = 'TS left: ' + str(self.left_ts_data) top_us = 'US top: ' + str( int(round(self.front_us_data / self.scaling_multiplier))) + 'mm' bottom_us = 'US bot: ' + str(int(round( self.rear_us_data))) + 'mm' message = self.robot_state.next_sound_job() sound = message if message else '-' arcade.draw_text(center_cs, self.text_x, self.screen_height - apply_scaling(70), arcade.color.WHITE, 10) arcade.draw_text(left_cs, self.text_x, self.screen_height - apply_scaling(90), arcade.color.WHITE, 10) arcade.draw_text(right_cs, self.text_x, self.screen_height - apply_scaling(110), arcade.color.WHITE, 10) arcade.draw_text(left_ts, self.text_x, self.screen_height - apply_scaling(130), arcade.color.WHITE, 10) arcade.draw_text(right_ts, self.text_x, self.screen_height - apply_scaling(150), arcade.color.WHITE, 10) arcade.draw_text(top_us, self.text_x, self.screen_height - apply_scaling(170), arcade.color.WHITE, 10) arcade.draw_text(bottom_us, self.text_x, self.screen_height - apply_scaling(190), arcade.color.WHITE, 10) arcade.draw_text('Sound:', self.text_x, self.screen_height - apply_scaling(210), arcade.color.WHITE, 10) arcade.draw_text(sound, self.text_x, self.screen_height - apply_scaling(230), arcade.color.WHITE, 10, anchor_y='top') arcade.draw_text('Robot Arm', apply_scaling(1450), self.screen_height - apply_scaling(50), arcade.color.WHITE, 14, anchor_x="center") if self.msg_counter != 0: self.msg_counter -= 1 arcade.draw_text(self.falling_msg, self.msg_x, self.screen_height - apply_scaling(100), arcade.color.WHITE, 14, anchor_x="center") arcade.draw_text(self.restart_msg, self.msg_x, self.screen_height - apply_scaling(130), arcade.color.WHITE, 14, anchor_x="center") def update(self, delta_time): """ All the logic to move the robot. Collision detection is also performed. """ if self.robot_state.should_reset: self.setup() self.robot_state.reset() else: self._process_movement() self._process_leds() self._process_sensors() self._check_fall() self.robot_state.release_locks() def _process_movement(self): """ Request the movement of the robot motors form the robot state and move the robot accordingly. """ center_dpf, left_ppf, right_ppf = self.robot_state.next_motor_jobs() if left_ppf or right_ppf: self.robot.execute_movement(left_ppf, right_ppf) if center_dpf: self.robot.execute_arm_movement(center_dpf) def _process_leds(self): if self.large_sim_type: self.robot.set_left_brick_led_colors( self.robot_state.left_brick_left_led_color, self.robot_state.left_brick_right_led_color) self.robot.set_right_brick_led_colors( self.robot_state.right_brick_left_led_color, self.robot_state.right_brick_right_led_color) else: self.robot.set_led_colors( self.robot_state.right_brick_left_led_color, self.robot_state.right_brick_right_led_color) def _check_fall(self): """ Check if the robot has fallen of the playing field or is stuck in the middle of a lake. If so display a message on the screen. """ left_wheel_data = self.robot.left_wheel.is_falling() right_wheel_data = self.robot.right_wheel.is_falling() if left_wheel_data or right_wheel_data: self.msg_counter = self.frames_per_second * 3 def _process_sensors(self): """ Process the data of the robot sensors by retrieving the data and putting it in the robot state. """ self.center_cs_data = self.robot.center_color_sensor.get_sensed_color() self.left_ts_data = self.robot.left_touch_sensor.is_touching() self.right_ts_data = self.robot.right_touch_sensor.is_touching() self.front_us_data = self.robot.front_ultrasonic_sensor.distance( self.space) self.robot_state.values[ self.robot.center_color_sensor.address] = self.center_cs_data self.robot_state.values[ self.robot.left_touch_sensor.address] = self.left_ts_data self.robot_state.values[ self.robot.right_touch_sensor.address] = self.right_ts_data self.robot_state.values[ self.robot.front_ultrasonic_sensor.address] = self.front_us_data self.robot.center_color_sensor.set_color_texture(self.center_cs_data) if self.large_sim_type: self.left_cs_data = self.robot.left_color_sensor.get_sensed_color() self.right_cs_data = self.robot.right_color_sensor.get_sensed_color( ) self.rear_ts_data = self.robot.rear_touch_sensor.is_touching() self.rear_us_data = self.robot.rear_ultrasonic_sensor.distance() self.robot_state.values[ self.robot.left_color_sensor.address] = self.left_cs_data self.robot_state.values[ self.robot.right_color_sensor.address] = self.right_cs_data self.robot_state.values[ self.robot.rear_touch_sensor.address] = self.rear_ts_data self.robot_state.values[ self.robot.rear_ultrasonic_sensor.address] = self.rear_us_data self.robot.left_color_sensor.set_color_texture(self.left_cs_data) self.robot.right_color_sensor.set_color_texture(self.right_cs_data)
def add_to_space(self, space: pymunk.Space): space.add(self.leg1, self.leg2, self.leg1.body, self.leg2.body, self.rotation_center_legs_joint, self.legs_rotary_limit_joint)
def add_to(self, space: pymunk.Space): space.add(self.body) for shape in self.shape: space.add(shape) return self
def add_to(self, space: pymunk.Space): space.add(self.body, self.shape) return self
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 load_space( space: pymunk.Space, *, data: Dict[str, Any], global_variables: Optional[Dict[str, Any]] = None) -> Dict[str, pymunk.Body]: logger.debug( f"loading space from data: {data} using global variables: {global_variables}" ) templates = load_json_templates(data.get("templates", {})) new_template = json_template_loader(base_templates=templates) global_variables = global_variables or {} objects = data.get("objects", {}) created_bodies = {} def build(name: str, data: Dict[str, Any]) -> Tuple[pymunk.Body, List[pymunk.Shape]]: logger.info(f"building {name!r}") if "__base__" in data: # Rendering from a base template object_template = new_template(f"anonymous:{name}", data) else: # Inline definition, wrap data in dict for json loader object_template = new_template(f"inline:{name}", {"template": data}) parser = object_template.build_parser(variables={}) parser.eval_context.exposed_variables.update(global_variables) whitelist_common_attribute_names(parser) body_data = object_template.template_data["physics"]["body"] factory = body_factory(body_type=body_types_by_name[body_data["type"]], position=body_data.get("position", None), mass=body_data.get("mass", None), moment=body_data.get("moment", None)) body = factory(parser) shapes = [] for shape_data in object_template.template_data["physics"]["shapes"]: shape_cls = shape_classes_by_name[shape_data["type"]] factory = shape_factory(shape_cls=shape_cls, shape_definition=extract_shape_definition( shape_cls, shape_data), mass=shape_data.get("mass", None), elasticity=shape_data.get( "elasticity", None), friction=shape_data.get("friction", None)) shapes.append(factory(parser, body)) created_bodies[name] = body return body, shapes for object_name, object_data in objects.items(): if isinstance(object_data, list): for i, each_data in enumerate(object_data): each_name = f"{object_name}#{i}" body, shapes = build(each_name, each_data) space.add(body, *shapes) elif isinstance(object_data, dict): body, shapes = build(object_name, object_data) space.add(body, *shapes) return created_bodies
def init_space(): sp = Space() sp.gravity = (0, 50) chain = make_pivot_chain(sp, (0, 0), (240, 30), 30) sp.add(constraint.PivotJoint(chain[0], sp.static_body, chain[0].position)) # Cria quadrado L = 25 player = Body(mass=1, moment=100) shape = Poly(player, [(-L, -L), (L, -L), (L, L), (-L, L)]) player.position = (90, 60) player.velocity = (-25, 25) shape.elasticity = 1.0 shape.color = pyxel.COLOR_RED shape.collision_type = 42 ball = Body(mass=1, moment=200) ball_shape = Circle(ball, 20) ball.position = (player.position.x, 130) ball_shape.elasticity = 1.0 shape.color = pyxel.COLOR_NAVY ball_shape.collision_type = 42 joint1 = constraint.DampedSpring(player, ball, (0, 0), (20, 0), 20, 3, 0.5) joint2 = constraint.PivotJoint(sp.static_body, player, (65, 35)) joint1.collide_bodies = False sp.add(joint1, joint2) body2 = Body(1, 100) sp.add(body2) sp.add(Poly(body2, [(-3, 3), (3, 3), (3, -3), (-3, -3)])) body2.position = 220, 50 sp.add(constraint.DampedRotarySpring(body2, ball, 0, 2, 1)) sp.body2 = body2 # Cria margens line = Body(body_type=Body.STATIC) e = 0 lines = [ Segment(line, (-e, -e), (240 + e, -e), 2), Segment(line, (-e, 180 + e), (240 + e, 180 + e), 2), Segment(line, (-e, -e), (-e, 180 + e), 2), Segment(line, (240 + e, -e), (240 + e, 180 + e), 2), ] for line in lines: line.elasticity = 1.0 lines = [] # Adiciona elementos ao espaço sp.add(player, shape, ball, ball_shape, *lines) sp.player = player #handler = sp.add_collision_handler(42, 42) #handler.begin = lambda *args: False return sp
def __create(listoflimbs: List[Limb], space: pymunk.Space, isUnderBody: bool): for limb in listoflimbs: if limb.isUnderBody == isUnderBody: space.add(limb.body, limb.shape) Creature.__create(limb.limbs, space, isUnderBody)