Exemple #1
0
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
Exemple #2
0
    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
Exemple #4
0
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)
Exemple #6
0
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)
Exemple #8
0
    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)
Exemple #10
0
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)
Exemple #11
0
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
Exemple #13
0
    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
Exemple #15
0
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)
Exemple #16
0
    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)
Exemple #17
0
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
Exemple #18
0
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
Exemple #19
0
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)
Exemple #20
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)
Exemple #21
0
 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)
Exemple #22
0
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
Exemple #24
0
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
Exemple #25
0
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)
Exemple #26
0
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)
Exemple #29
0
 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)
Exemple #30
0
 def add_to(self, space: pymunk.Space):
     space.add(self.body)
     for shape in self.shape:
         space.add(shape)
     return self
Exemple #31
0
 def add_to(self, space: pymunk.Space):
     space.add(self.body, self.shape)
     return self
Exemple #32
0
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)
Exemple #33
0
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
Exemple #34
0
 def add_to(self, space: pymunk.Space):
     space.add(self.body)
     for shape in self.shape:
         space.add(shape)
     return self
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
Exemple #36
0
 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)
Exemple #37
0
 def add_to(self, space: pymunk.Space):
     space.add(self.body, self.shape)
     return self