示例#1
0
def draw_rectangle_filled(center_x: float,
                          center_y: float,
                          width: float,
                          height: float,
                          color: Color,
                          tilt_angle: float = 0):
    """
    Draw a filled-in rectangle.

    :param float center_x: x coordinate of rectangle center.
    :param float center_y: y coordinate of rectangle center.
    :param float width: width of the rectangle.
    :param float height: height of the rectangle.
    :param Color color: color, specified in a list of 3 or 4 bytes in RGB or
         RGBA format.
    :param float tilt_angle: rotation of the rectangle. Defaults to zero.
    """
    p1 = [-width // 2 + center_x, -height // 2 + center_y]
    p2 = [width // 2 + center_x, -height // 2 + center_y]
    p3 = [width // 2 + center_x, height // 2 + center_y]
    p4 = [-width // 2 + center_x, height // 2 + center_y]

    if tilt_angle != 0:
        p1 = rotate_point(p1[0], p1[1], center_x, center_y, tilt_angle)
        p2 = rotate_point(p2[0], p2[1], center_x, center_y, tilt_angle)
        p3 = rotate_point(p3[0], p3[1], center_x, center_y, tilt_angle)
        p4 = rotate_point(p4[0], p4[1], center_x, center_y, tilt_angle)

    _generic_draw_line_strip((p1, p2, p4, p3), color, gl.GL_TRIANGLE_STRIP)
示例#2
0
def _create_rects(rect_list: Iterable[Sprite]) -> List[float]:
    """
    Create a vertex buffer for a set of rectangles.
    """

    v2f = []
    for shape in rect_list:
        x1 = -shape.width / 2 + shape.center_x
        x2 = shape.width / 2 + shape.center_x
        y1 = -shape.height / 2 + shape.center_y
        y2 = shape.height / 2 + shape.center_y

        p1 = [x1, y1]
        p2 = [x2, y1]
        p3 = [x2, y2]
        p4 = [x1, y2]

        if shape.angle:
            p1 = rotate_point(p1[0], p1[1], shape.center_x, shape.center_y, shape.angle)
            p2 = rotate_point(p2[0], p2[1], shape.center_x, shape.center_y, shape.angle)
            p3 = rotate_point(p3[0], p3[1], shape.center_x, shape.center_y, shape.angle)
            p4 = rotate_point(p4[0], p4[1], shape.center_x, shape.center_y, shape.angle)

        v2f.extend([p1[0], p1[1],
                   p2[0], p2[1],
                   p3[0], p3[1],
                   p4[0], p4[1]])

    return v2f
示例#3
0
    def _set_angle(self, new_value: float):
        """ Set the angle of the sprite's rotation. """
        if new_value != self._angle:
            old_angle = 0.0
            if self.rot_point_relative:
                old_angle = self._angle
            self.clear_spatial_hashes()
            self._angle = new_value
            self._point_list_cache = None
            self.add_spatial_hashes()
            if self.rotation_point:
                rotate_x, rotate_y = self.rotation_point
                self_x, self_y = self.center_x, self.center_y
                if old_angle:
                    rotate_x += self_x
                    rotate_y += self_y
                    rotate_x, rotate_y = rotate_point(rotate_x, rotate_y,
                                                      self_x, self_y,
                                                      old_angle)
                sprite_rotate = rotate_point(self_x, self_y, rotate_x,
                                             rotate_y, new_value - old_angle)
                self.set_position(sprite_rotate[0], sprite_rotate[1])

            for sprite_list in self.sprite_lists:
                sprite_list.update_angle(self)
    def get_points(self) -> Tuple[Tuple[float, float]]:
        """
        Get the corner points for the rect that makes up the sprite.
        """
        if self._point_list_cache is not None:
            return self._point_list_cache

        if self._points is not None:
            point_list = []
            for point in range(len(self._points)):
                point = (self._points[point][0] + self.center_x,
                         self._points[point][1] + self.center_y)
                point_list.append(point)
            self._point_list_cache = tuple(point_list)
        else:
            x1, y1 = arcade.rotate_point(self.center_x - self.width / 4,
                                         self.center_y - self.width / 4,
                                         self.center_x, self.center_y,
                                         self.angle)
            x2, y2 = arcade.rotate_point(self.center_x + self.width / 4,
                                         self.center_y - self.height / 4,
                                         self.center_x, self.center_y,
                                         self.angle)
            x3, y3 = arcade.rotate_point(self.center_x + self.width / 4,
                                         self.center_y + self.height / 4,
                                         self.center_x, self.center_y,
                                         self.angle)
            x4, y4 = arcade.rotate_point(self.center_x - self.width / 4,
                                         self.center_y + self.height / 4,
                                         self.center_x, self.center_y,
                                         self.angle)

            self._point_list_cache = ((x1, y1), (x2, y2), (x3, y3), (x4, y4))
        return self._point_list_cache
示例#5
0
    def update(self, delta_time, main):
        # Movimiento en mi mismo
        self.a += 10 * math.sin(main.frame_count / 4)
        # Movimiento para mantenerlo donde corresponde
        self.x, self.y = arcade.rotate_point(self.x, self.y,
                                             win.CENTER_W + main.view_left,
                                             win.CENTER_H + main.view_bottom,
                                             main.change_angle)
        # Movimiento para alcanzar al circulo
        self.t += delta_time
        if (self.t > 0):  # seg
            self.t = 0
            # Position the start at the enemy's current location
            start_x = self.x
            start_y = self.y

            # Get the destination location for the bullet
            dest_x = main.circle.x
            dest_y = main.circle.y

            # Do math to calculate how to get the bullet to the destination.
            # Calculation the angle in radians between the start points
            # and end points. This is the angle the bullet will travel.
            x_diff = dest_x - start_x
            y_diff = dest_y - start_y
            self.d = math.atan2(y_diff, x_diff)

        self.x += math.cos(self.d) * 3
        self.y += math.sin(self.d) * 3
示例#6
0
    def get_adjusted_hit_box(self) -> List[List[float]]:
        """
        Get the points that make up the hit box for the rect that makes up the
        sprite, including rotation and scaling.
        """

        # If we've already calculated the adjusted hit box, use the cached version
        if self._point_list_cache is not None:
            return self._point_list_cache

        # If there is no hitbox, use the width/height to get one
        if self._points is None and self._texture:
            self._points = self._texture.hit_box_points

        if self._points is None and self._width:
            x1, y1 = -self._width / 2, -self._height / 2
            x2, y2 = +self._width / 2, -self._height / 2
            x3, y3 = +self._width / 2, +self._height / 2
            x4, y4 = -self._width / 2, +self._height / 2

            self._points = [[x1, y1], [x2, y2], [x3, y3], [x4, y4]]

        if self._points is None and self.texture is not None:
            self._points = self.texture.hit_box_points

        if self._points is None:
            raise ValueError(
                "Error trying to get the hit box of a sprite, when no hit box is set.\nPlease make sure the "
                "Sprite.texture is set to a texture before trying to draw or do collision testing.\n"
                "Alternatively, manually call Sprite.set_hit_box with points for your hitbox."
            )

        # Adjust the hitbox
        point_list = []
        for point in self._points:
            # Get a copy of the point
            point = [point[0], point[1]]

            # Scale the point
            if self.scale != 1:
                point[0] *= self.scale
                point[1] *= self.scale

            # Rotate the point
            if self.angle:
                point = rotate_point(point[0], point[1], 0, 0, self.angle)

            # Offset the point
            point = [point[0] + self.center_x, point[1] + self.center_y]
            point_list.append(point)

        # Cache the results
        self._point_list_cache = point_list

        # if self.texture:
        #     print(self.texture.name, self._point_list_cache)

        return self._point_list_cache
def create_rectangle(center_x: float, center_y: float, width: float,
                     height: float, color: Color,
                     border_width: float = 1, tilt_angle: float = 0,
                     filled=True) -> Shape:
    """
    This function creates a rectangle using a vertex buffer object.
    Creating the rectangle, and then later drawing it with ``render_rectangle``
    is faster than calling ``draw_rectangle``.

    Args:
        center_x:
        center_y:
        width:
        height:
        color:
        border_width:
        tilt_angle:
        filled:

    Returns:

    """
    data: List[Point] = cast(List[Point], get_rectangle_points(center_x, center_y, width, height, tilt_angle))

    if filled:
        shape_mode = gl.GL_TRIANGLE_STRIP
        data[-2:] = reversed(data[-2:])
    else:

        i_lb = center_x - width / 2 + border_width / 2, center_y - height / 2 + border_width / 2
        i_rb = center_x + width / 2 - border_width / 2, center_y - height / 2 + border_width / 2
        i_rt = center_x + width / 2 - border_width / 2, center_y + height / 2 - border_width / 2
        i_lt = center_x - width / 2 + border_width / 2, center_y + height / 2 - border_width / 2

        o_lb = center_x - width / 2 - border_width / 2, center_y - height / 2 - border_width / 2
        o_rb = center_x + width / 2 + border_width / 2, center_y - height / 2 - border_width / 2
        o_rt = center_x + width / 2 + border_width / 2, center_y + height / 2 + border_width / 2
        o_lt = center_x - width / 2 - border_width / 2, center_y + height / 2 + border_width / 2

        data = [o_lt, i_lt, o_rt, i_rt, o_rb, i_rb, o_lb, i_lb, o_lt, i_lt]

        if tilt_angle != 0:
            point_list_2: List[Point] = []
            for point in data:
                new_point = rotate_point(point[0], point[1], center_x, center_y, tilt_angle)
                point_list_2.append(new_point)
            data = point_list_2

        border_width = 1
        shape_mode = gl.GL_TRIANGLE_STRIP

        # _generic_draw_line_strip(point_list, color, gl.GL_TRIANGLE_STRIP)

        # shape_mode = gl.GL_LINE_STRIP
        # data.append(data[0])

    shape = create_line_generic(data, color, shape_mode, border_width)
    return shape
示例#8
0
def test_rotate_point():
    x = 0
    y = 0
    cx = 0
    cy = 0
    angle = 0
    rx, ry = arcade.rotate_point(x, y, cx, cy, angle)
    assert rx == 0
    assert ry == 0

    x = 0
    y = 0
    cx = 0
    cy = 0
    angle = 90
    rx, ry = arcade.rotate_point(x, y, cx, cy, angle)
    assert rx == 0
    assert ry == 0

    x = 50
    y = 50
    cx = 0
    cy = 0
    angle = 0
    rx, ry = arcade.rotate_point(x, y, cx, cy, angle)
    assert rx == 50
    assert ry == 50

    x = 50
    y = 0
    cx = 0
    cy = 0
    angle = 90
    rx, ry = arcade.rotate_point(x, y, cx, cy, angle)
    assert rx == 0
    assert ry == 50

    x = 20
    y = 10
    cx = 10
    cy = 10
    angle = 180
    rx, ry = arcade.rotate_point(x, y, cx, cy, angle)
    assert rx == 0
    assert ry == 10
示例#9
0
def draw_arc_outline(center_x: float, center_y: float, width: float,
                     height: float, color: Color,
                     start_angle: float, end_angle: float,
                     border_width: float = 1, tilt_angle: float = 0,
                     num_segments: int = 128):
    """
    Draw the outside edge of an arc. Useful for drawing curved lines.

    :param float center_x: x position that is the center of the arc.
    :param float center_y: y position that is the center of the arc.
    :param float width: width of the arc.
    :param float height: height of the arc.
    :param Color color: color, specified in a list of 3 or 4 bytes in RGB or
         RGBA format.
    :param float start_angle: start angle of the arc in degrees.
    :param float end_angle: end angle of the arc in degrees.
    :param float border_width: width of line in pixels.
    :param float tilt_angle: angle the arc is tilted.
    :param int num_segments: float of triangle segments that make up this
         circle. Higher is better quality, but slower render time.
    """
    unrotated_point_list = []

    start_segment = int(start_angle / 360 * num_segments)
    end_segment = int(end_angle / 360 * num_segments)

    inside_width = (width - border_width / 2) / 2
    outside_width = (width + border_width / 2) / 2
    inside_height = (height - border_width / 2) / 2
    outside_height = (height + border_width / 2) / 2

    for segment in range(start_segment, end_segment + 1):
        theta = 2.0 * math.pi * segment / num_segments

        x1 = inside_width * math.cos(theta)
        y1 = inside_height * math.sin(theta)

        x2 = outside_width * math.cos(theta)
        y2 = outside_height * math.sin(theta)

        unrotated_point_list.append([x1, y1])
        unrotated_point_list.append([x2, y2])

    if tilt_angle == 0:
        uncentered_point_list = unrotated_point_list
    else:
        uncentered_point_list = []
        for point in unrotated_point_list:
            uncentered_point_list.append(rotate_point(point[0], point[1], 0, 0, tilt_angle))

    point_list = []
    for point in uncentered_point_list:
        point_list.append((point[0] + center_x, point[1] + center_y))

    _generic_draw_line_strip(point_list, color, gl.GL_TRIANGLE_STRIP)
示例#10
0
    def update(self, delta_time):
        """ Movement and game logic """
        self.earth_angle += 1
        self.moon_angle += 5
        earth_center_x, earth_center_y = arcade.rotate_point(
            self.sun_x + self.earth_dist, self.sun_y,
            self.sun_x, self.sun_y, self.earth_angle)
        self.moon_shape_list.center_x = earth_center_x
        self.moon_shape_list.center_y = earth_center_y

        self.earth_shape_list.angle = self.earth_angle
        self.moon_shape_list.angle = self.moon_angle
def get_rectangle_points(center_x: float,
                         center_y: float,
                         width: float,
                         height: float,
                         tilt_angle: float = 0) -> PointList:
    """
    Utility function that will return all four coordinate points of a
    rectangle given the x, y center, width, height, and rotation.

    Args:
        center_x:
        center_y:
        width:
        height:
        tilt_angle:

    Returns:

    """
    x1 = -width / 2 + center_x
    y1 = -height / 2 + center_y

    x2 = -width / 2 + center_x
    y2 = height / 2 + center_y

    x3 = width / 2 + center_x
    y3 = height / 2 + center_y

    x4 = width / 2 + center_x
    y4 = -height / 2 + center_y

    if tilt_angle:
        x1, y1 = rotate_point(x1, y1, center_x, center_y, tilt_angle)
        x2, y2 = rotate_point(x2, y2, center_x, center_y, tilt_angle)
        x3, y3 = rotate_point(x3, y3, center_x, center_y, tilt_angle)
        x4, y4 = rotate_point(x4, y4, center_x, center_y, tilt_angle)

    data = [(x1, y1), (x2, y2), (x3, y3), (x4, y4)]

    return data
示例#12
0
def create_ellipse_filled_with_colors(center_x: float,
                                      center_y: float,
                                      width: float,
                                      height: float,
                                      outside_color: Color,
                                      inside_color: Color,
                                      tilt_angle: float = 0,
                                      num_segments: int = 32) -> Shape:
    """
    Draw an ellipse, and specify inside/outside color. Used for doing gradients.

    The function returns a Shape object that can be drawn with ``my_shape.draw()``.
    Don't create the shape in the draw method, create it in the setup method and then
    draw it in ``on_draw``.

    For even faster performance, add multiple shapes into a ShapeElementList and
    draw that list. This allows nearly unlimited shapes to be drawn just as fast
    as one.


    :param float center_x:
    :param float center_y:
    :param float width:
    :param float height:
    :param Color outside_color:
    :param float inside_color:
    :param float tilt_angle:
    :param int num_segments:

    :Returns Shape:

    """

    # Create an array with the vertex data
    # Create an array with the vertex point_list
    point_list = [(center_x, center_y)]

    for segment in range(num_segments):
        theta = 2.0 * 3.1415926 * segment / num_segments

        x = width * math.cos(theta) + center_x
        y = height * math.sin(theta) + center_y

        if tilt_angle:
            x, y = rotate_point(x, y, center_x, center_y, tilt_angle)

        point_list.append((x, y))
    point_list.append(point_list[1])

    color_list = [inside_color] + [outside_color] * (num_segments + 1)
    return create_line_generic_with_colors(point_list, color_list,
                                           gl.GL_TRIANGLE_FAN)
示例#13
0
    def update(self, delta_time, main):
        # Actualizar la direccion
        self.d += math.radians(main.change_angle)

        # Movimiento para mantenerse en el lugar
        self.x, self.y = arcade.rotate_point(self.x, self.y,
                                             win.CENTER_W + main.view_left,
                                             win.CENTER_H + main.view_bottom,
                                             main.change_angle)
        # Avanzar en linea recta
        self.x += math.cos(self.d) * 5
        self.y += math.sin(self.d) * 5
        """ Special shot
示例#14
0
    def get_adjusted_hit_box(self) -> List[List[float]]:
        """
        Get the points that make up the hit box for the rect that makes up the
        sprite, including rotation and scaling.
        """

        # If we've already calculated the adjusted hit box, use the cached version
        if self._point_list_cache is not None:
            return self._point_list_cache

        # If there is no hitbox, use the width/height to get one
        if self._points is None and self._texture:
            self._points = self._texture.unscaled_hitbox_points

        if self._points is None and self._width:
            x1, y1 = -self._width / 2, -self._height / 2
            x2, y2 = +self._width / 2, -self._height / 2
            x3, y3 = +self._width / 2, +self._height / 2
            x4, y4 = -self._width / 2, +self._height / 2

            self._points = [[x1, y1], [x2, y2], [x3, y3], [x4, y4]]

        if self._points is None:
            raise ValueError(
                "Trying to get the hit box of a sprite that doesn't have one.")

        # Adjust the hitbox
        point_list = []
        for point_idx in range(len(self._points)):
            # Get the point
            point = [self._points[point_idx][0], self._points[point_idx][1]]

            # Scale the point
            if self.scale != 1:
                point[0] *= self.scale
                point[1] *= self.scale

            # Rotate the point
            if self.angle:
                point = rotate_point(point[0], point[1], 0, 0, self.angle)

            # Offset the point
            point = [point[0] + self.center_x, point[1] + self.center_y]
            point_list.append(point)

        # Cache the results
        self._point_list_cache = point_list

        # if self.texture:
        #     print(self.texture.name, self._point_list_cache)
        return self._point_list_cache
示例#15
0
def draw_arc_filled(center_x: float,
                    center_y: float,
                    width: float,
                    height: float,
                    color: Color,
                    start_angle: float,
                    end_angle: float,
                    tilt_angle: float = 0,
                    num_segments: int = 128):
    """
    Draw a filled in arc. Useful for drawing pie-wedges, or Pac-Man.

    :param float center_x: x position that is the center of the arc.
    :param float center_y: y position that is the center of the arc.
    :param float width: width of the arc.
    :param float height: height of the arc.
    :param Color color: color, specified in a list of 3 or 4 bytes in RGB or
         RGBA format.
    :param float start_angle: start angle of the arc in degrees.
    :param float end_angle: end angle of the arc in degrees.
    :param float tilt_angle: angle the arc is tilted.
    :param float num_segments: Number of line segments used to draw arc.
    """
    unrotated_point_list = [[0.0, 0.0]]

    start_segment = int(start_angle / 360 * num_segments)
    end_segment = int(end_angle / 360 * num_segments)

    for segment in range(start_segment, end_segment + 1):
        theta = 2.0 * 3.1415926 * segment / num_segments

        x = width * math.cos(theta) / 2
        y = height * math.sin(theta) / 2

        unrotated_point_list.append([x, y])

    if tilt_angle == 0:
        uncentered_point_list = unrotated_point_list
    else:
        uncentered_point_list = []
        for point in unrotated_point_list:
            uncentered_point_list.append(
                rotate_point(point[0], point[1], 0, 0, tilt_angle))

    point_list = []
    for point in uncentered_point_list:
        point_list.append((point[0] + center_x, point[1] + center_y))

    _generic_draw_line_strip(point_list, color, gl.GL_TRIANGLE_FAN)
示例#16
0
    def _set_angle(self, new_value: float):
        """ Set the angle of the sprite's rotation. """
        if new_value != self._angle:
            self.clear_spatial_hashes()
            self._angle = new_value
            self._point_list_cache = None
            self.add_spatial_hashes()
            rotate_x, rotate_y = self.rotation_point
            if rotate_x or rotate_y:
                sprite_rotate = rotate_point(self.center_x, self.center_y,
                                             rotate_x, rotate_y, new_value)
                self.set_position(sprite_rotate[0], sprite_rotate[1])

            for sprite_list in self.sprite_lists:
                sprite_list.update_angle(self)
示例#17
0
def create_arc_outline(center_x: float,
                       center_y: float,
                       width: float,
                       height: float,
                       color: arcade.Color,
                       start_angle: float,
                       end_angle: float,
                       border_width: float = 1,
                       tilt_angle: float = 0,
                       num_segments: int = 256):
    """
        Creates arc outline
    """
    unrotated_point_list = []

    inside_width = width - border_width / 2
    outside_width = width + border_width / 2
    inside_height = height - border_width / 2
    outside_height = height + border_width / 2

    for segment in range(num_segments + 1):
        theta = math.pi / 180 * (start_angle + segment *
                                 (end_angle - start_angle) / num_segments)

        x1 = inside_width * math.cos(theta)
        y1 = inside_height * math.sin(theta)

        x2 = outside_width * math.cos(theta)
        y2 = outside_height * math.sin(theta)

        unrotated_point_list.append([x1, y1])
        unrotated_point_list.append([x2, y2])

    if tilt_angle == 0:
        uncentered_point_list = unrotated_point_list
    else:
        uncentered_point_list = []
        for point in unrotated_point_list:
            uncentered_point_list.append(
                arcade.rotate_point(point[0], point[1], 0, 0, tilt_angle))

    point_list = []
    for point in uncentered_point_list:
        point_list.append((point[0] + center_x, point[1] + center_y))
    shape_mode = gl.GL_LINE_STRIP
    return arcade.create_line_generic(point_list, color, shape_mode,
                                      border_width)
示例#18
0
def create_ellipse(center_x: float,
                   center_y: float,
                   width: float,
                   height: float,
                   color: Color,
                   border_width: float = 1,
                   tilt_angle: float = 0,
                   num_segments: int = 32,
                   filled=True) -> Shape:
    """
    This creates an ellipse vertex buffer object (VBO).

    The function returns a Shape object that can be drawn with ``my_shape.draw()``.
    Don't create the shape in the draw method, create it in the setup method and then
    draw it in ``on_draw``.

    For even faster performance, add multiple shapes into a ShapeElementList and
    draw that list. This allows nearly unlimited shapes to be drawn just as fast
    as one.

    """
    # Create an array with the vertex point_list
    point_list = []

    for segment in range(num_segments):
        theta = 2.0 * 3.1415926 * segment / num_segments

        x = width * math.cos(theta) + center_x
        y = height * math.sin(theta) + center_y

        if tilt_angle:
            x, y = rotate_point(x, y, center_x, center_y, tilt_angle)

        point_list.append((x, y))

    if filled:
        half = len(point_list) // 2
        interleaved = itertools.chain.from_iterable(
            itertools.zip_longest(point_list[:half],
                                  reversed(point_list[half:])))
        point_list = [p for p in interleaved if p is not None]
        shape_mode = gl.GL_TRIANGLE_STRIP
    else:
        point_list.append(point_list[0])
        shape_mode = gl.GL_LINE_STRIP

    return create_line_generic(point_list, color, shape_mode, border_width)
示例#19
0
def draw_ellipse_filled(center_x: float,
                        center_y: float,
                        width: float,
                        height: float,
                        color: Color,
                        tilt_angle: float = 0,
                        num_segments: int = 128):
    """
    Draw a filled in ellipse.

    :param float center_x: x position that is the center of the circle.
    :param float center_y: y position that is the center of the circle.
    :param float width: width of the ellipse.
    :param float height: height of the ellipse.
    :param Color color: color, specified in a list of 3 or 4 bytes in RGB or
         RGBA format.
    :param float tilt_angle: Angle in degrees to tilt the ellipse.
    :param int num_segments: float of triangle segments that make up this
         circle. Higher is better quality, but slower render time.
    """

    unrotated_point_list = []

    for segment in range(num_segments):
        theta = 2.0 * 3.1415926 * segment / num_segments

        x = (width / 2) * math.cos(theta)
        y = (height / 2) * math.sin(theta)

        unrotated_point_list.append([x, y])

    if tilt_angle == 0:
        uncentered_point_list = unrotated_point_list
    else:
        uncentered_point_list = []
        for point in unrotated_point_list:
            uncentered_point_list.append(
                rotate_point(point[0], point[1], 0, 0, tilt_angle))

    point_list = []
    for point in uncentered_point_list:
        point_list.append((point[0] + center_x, point[1] + center_y))

    _generic_draw_line_strip(point_list, color, gl.GL_TRIANGLE_FAN)
def create_ellipse_filled_with_colors(center_x: float,
                                      center_y: float,
                                      width: float,
                                      height: float,
                                      outside_color: Color,
                                      inside_color: Color,
                                      tilt_angle: float = 0,
                                      num_segments: int = 32) -> Shape:
    """
    Draw an ellipse, and specify inside/outside color. Used for doing gradients.

    :param float center_x:
    :param float center_y:
    :param float width:
    :param float height:
    :param Color outside_color:
    :param float inside_color:
    :param float tilt_angle:
    :param int num_segments:

    :Returns Shape:

    """

    # Create an array with the vertex data
    # Create an array with the vertex point_list
    point_list = [(center_x, center_y)]

    for segment in range(num_segments):
        theta = 2.0 * 3.1415926 * segment / num_segments

        x = width * math.cos(theta) + center_x
        y = height * math.sin(theta) + center_y

        if tilt_angle:
            x, y = rotate_point(x, y, center_x, center_y, tilt_angle)

        point_list.append((x, y))
    point_list.append(point_list[1])

    color_list = [inside_color] + [outside_color] * (num_segments + 1)
    return create_line_generic_with_colors(point_list, color_list,
                                           gl.GL_TRIANGLE_FAN)
def create_ellipse(center_x: float,
                   center_y: float,
                   width: float,
                   height: float,
                   color: Color,
                   border_width: float = 1,
                   tilt_angle: float = 0,
                   num_segments: int = 32,
                   filled=True) -> Shape:
    """
    This creates an ellipse vertex buffer object (VBO). It can later be
    drawn with ``render_ellipse_filled``. This method of drawing an ellipse
    is much faster than calling ``draw_ellipse_filled`` each frame.

    Note: This can't be unit tested on Appveyor because its support for OpenGL is
    poor.
    """
    # Create an array with the vertex point_list
    point_list = []

    for segment in range(num_segments):
        theta = 2.0 * 3.1415926 * segment / num_segments

        x = width * math.cos(theta) + center_x
        y = height * math.sin(theta) + center_y

        if tilt_angle:
            x, y = rotate_point(x, y, center_x, center_y, tilt_angle)

        point_list.append((x, y))

    if filled:
        half = len(point_list) // 2
        interleaved = itertools.chain.from_iterable(
            itertools.zip_longest(point_list[:half],
                                  reversed(point_list[half:])))
        point_list = [p for p in interleaved if p is not None]
        shape_mode = gl.GL_TRIANGLE_STRIP
    else:
        point_list.append(point_list[0])
        shape_mode = gl.GL_LINE_STRIP

    return create_line_generic(point_list, color, shape_mode, border_width)
示例#22
0
def draw_rectangle_outline(center_x: float,
                           center_y: float,
                           width: float,
                           height: float,
                           color: Color,
                           border_width: float = 1,
                           tilt_angle: float = 0):
    """
    Draw a rectangle outline.

    :param float center_x: x coordinate of top left rectangle point.
    :param float center_y: y coordinate of top left rectangle point.
    :param float width: width of the rectangle.
    :param float height: height of the rectangle.
    :param Color color: color, specified in a list of 3 or 4 bytes in RGB or
         RGBA format.
    :param float border_width: width of the lines, in pixels.
    :param float tilt_angle: rotation of the rectangle. Defaults to zero.
    """

    i_lb = center_x - width / 2 + border_width / 2, center_y - height / 2 + border_width / 2
    i_rb = center_x + width / 2 - border_width / 2, center_y - height / 2 + border_width / 2
    i_rt = center_x + width / 2 - border_width / 2, center_y + height / 2 - border_width / 2
    i_lt = center_x - width / 2 + border_width / 2, center_y + height / 2 - border_width / 2

    o_lb = center_x - width / 2 - border_width / 2, center_y - height / 2 - border_width / 2
    o_rb = center_x + width / 2 + border_width / 2, center_y - height / 2 - border_width / 2
    o_rt = center_x + width / 2 + border_width / 2, center_y + height / 2 + border_width / 2
    o_lt = center_x - width / 2 - border_width / 2, center_y + height / 2 + border_width / 2

    point_list: List[Point] = [
        o_lt, i_lt, o_rt, i_rt, o_rb, i_rb, o_lb, i_lb, o_lt, i_lt
    ]

    if tilt_angle != 0:
        point_list_2: List[Point] = []
        for point in point_list:
            new_point = rotate_point(point[0], point[1], center_x, center_y,
                                     tilt_angle)
            point_list_2.append(new_point)
        point_list = point_list_2

    _generic_draw_line_strip(point_list, color, gl.GL_TRIANGLE_STRIP)
示例#23
0
    def on_draw(self):
        ade.start_render()

        for shape in self.g_space.shapes:
            (x, y) = shape.body.position
            type = shape.type

            if (type == "circle"):
                ade.draw_circle_filled(x, y, shape.radius, shape.color)

                rx, ry = ade.rotate_point(x + shape.radius, y, x, y,
                                          shape.body.angle * (180 / 3.1415))

                ade.draw_line(x, y, rx, ry, ade.color.GRAY, 2)

            if (type == "segment"):
                s_x, s_y = shape.a
                e_x, e_y = shape.b

                ade.draw_line(s_x, s_y, e_x, e_y, shape.color, shape.radius)
示例#24
0
    def draw_hit_box(self, color: Color = BLACK, line_thickness: float = 1):
        """
        Draw a sprite's hit-box.

        The 'hit box' drawing is cached, so if you change the color/line thickness
        later, it won't take.

        :param color: Color of box
        :param line_thickness: How thick the box should be
        """

        if self._hit_box_shape is None:

            # Adjust the hitbox
            point_list = []
            for point in self.hit_box:
                # Get a copy of the point
                point = [point[0], point[1]]

                # Scale the point
                if self.scale != 1:
                    point[0] *= self.scale
                    point[1] *= self.scale

                # Rotate the point
                if self.angle:
                    point = rotate_point(point[0], point[1], 0, 0, self.angle)

                point_list.append(point)

            shape = create_line_loop(point_list, color, line_thickness)
            self._hit_box_shape = ShapeElementList()
            self._hit_box_shape.append(shape)

        self._hit_box_shape.center_x = self.center_x
        self._hit_box_shape.center_y = self.center_y
        self._hit_box_shape.angle = self.angle
        self._hit_box_shape.draw()
示例#25
0
    def get_adjusted_hit_box(self) -> PointList:
        """
        Get the points that make up the hit box for the rect that makes up the
        sprite, including rotation and scaling.
        """

        # If we've already calculated the adjusted hit box, use the cached version
        if self._point_list_cache is not None:
            return self._point_list_cache

        # Adjust the hitbox
        point_list = []
        for point in self.hit_box:
            # Get a copy of the point
            point = [point[0], point[1]]

            # Scale the point
            if self.scale != 1:
                point[0] *= self.scale
                point[1] *= self.scale

            # Rotate the point
            if self.angle:
                point = rotate_point(point[0], point[1], 0, 0, self.angle)

            # Offset the point
            point = [point[0] + self.center_x,
                     point[1] + self.center_y]
            point_list.append(point)

        # Cache the results
        self._point_list_cache = point_list

        # if self.texture:
        #     print(self.texture.name, self._point_list_cache)

        return self._point_list_cache
示例#26
0
文件: sprite.py 项目: aburgool/arcade
    def get_adjusted_hit_box(self) -> Tuple[Tuple[float, float], ...]:
        """
        Get the points that make up the hit box for the rect that makes up the
        sprite, including rotation and scaling.
        """

        if self._point_list_cache is not None:
            return self._point_list_cache

        if self._points is None:
            x1, y1 = -self.width / 2, -self.height / 2
            x2, y2 = +self.width / 2, -self.height / 2
            x3, y3 = +self.width / 2, +self.height / 2
            x4, y4 = -self.width / 2, +self.height / 2

            self._points = ((x1, y1), (x2, y2), (x3, y3), (x4, y4))

        point_list = []
        for point_idx in range(len(self._points)):
            # Get the point
            point = [self._points[point_idx][0], self._points[point_idx][1]]

            # Rotate the point
            if self.angle:
                point = rotate_point(point[0], point[1], 0, 0, self.angle)

            # Scale the point
            if self.scale != 1:
                point[0] *= self.scale
                point[1] *= self.scale

            # Offset the point
            point = (point[0] + self.center_x, point[1] + self.center_y)
            point_list.append(point)
        self._point_list_cache = tuple(point_list)

        return self._point_list_cache
示例#27
0
    def get_adjusted_hit_box(self) -> List[List[float]]:
        """
        Get the points that make up the hit box for the rect that makes up the
        sprite, including rotation and scaling.
        """

        # If we've already calculated the adjusted hit box, use the cached version
        if self._point_list_cache is not None:
            return self._point_list_cache

        # If there is no hitbox, use the width/height to get one
        if self._points is None and self._texture:
            self._points = self._texture.hit_box_points

        # Infer points from texture properties
        if self._points is None and self._texture and self._texture.width:
            self._points = points_from_dimensions(
                self._texture.width, self.texture.height)
            self._inferred_points_by_texture = True

        # Infer points from sprite properties
        if self._points is None and self._width:
            self._points = points_from_dimensions(self._width, self._height)

        if self._points is None and self.texture is not None:
            self._points = self.texture.hit_box_points

        if self._points is None:
            raise ValueError("Error trying to get the hit box of a sprite, when no hit box is set.\nPlease make sure the "
                             "Sprite.texture is set to a texture before trying to draw or do collision testing.\n"
                             "Alternatively, manually call Sprite.set_hit_box with points for your hitbox.")

        # Adjust the hitbox
        point_list = []

        # only apply width and height ratio if we get our points from the texture
        width_ratio = 0.
        height_ratio = 0.
        if self._texture:
            # Points should have been gotten from the texture
            # Apply dimensions ratio.
            # Todo: reset _points if texture is set after _points.
            width_ratio = self._width / self._texture.width
            height_ratio = self._height / self._texture.height

        for point in self._points:
            # Get a copy of the point
            point = [point[0], point[1]]

            # take height and width into account
            if width_ratio:
                point[0] *= width_ratio

            if height_ratio:
                point[1] *= height_ratio

            # Rotate the point
            if self.angle:
                point = rotate_point(point[0], point[1], 0, 0, self.angle)

            # Offset the point
            point = [point[0] + self.center_x,
                     point[1] + self.center_y]
            point_list.append(point)

        # Cache the results
        self._point_list_cache = point_list

        # if self.texture:
        #     print(self.texture.name, self._point_list_cache)

        return self._point_list_cache
示例#28
0
def test_rotate_point(mock_window):
    from arcade import rotate_point
    x, y = rotate_point(1, 1, 0, 0, 90)
    assert (-1.0, 1.0) == (x, y)
示例#29
0
def create_rectangle(center_x: float, center_y: float, width: float,
                     height: float, color: Color,
                     border_width: float = 1, tilt_angle: float = 0,
                     filled=True) -> Shape:
    """
    This function creates a rectangle using a vertex buffer object.

    The function returns a Shape object that can be drawn with ``my_shape.draw()``.
    Don't create the shape in the draw method, create it in the setup method and then
    draw it in ``on_draw``.

    For even faster performance, add multiple shapes into a ShapeElementList and
    draw that list. This allows nearly unlimited shapes to be drawn just as fast
    as one.

    :param float center_x:
    :param float center_y:
    :param float width:
    :param float height:
    :param Color color:
    :param float border_width:
    :param float tilt_angle:
    :param bool filled:

    """
    data: List[Point] = cast(List[Point], get_rectangle_points(center_x, center_y, width, height, tilt_angle))

    if filled:
        shape_mode = gl.GL_TRIANGLE_STRIP
        data[-2:] = reversed(data[-2:])
    else:

        i_lb = center_x - width / 2 + border_width / 2, center_y - height / 2 + border_width / 2
        i_rb = center_x + width / 2 - border_width / 2, center_y - height / 2 + border_width / 2
        i_rt = center_x + width / 2 - border_width / 2, center_y + height / 2 - border_width / 2
        i_lt = center_x - width / 2 + border_width / 2, center_y + height / 2 - border_width / 2

        o_lb = center_x - width / 2 - border_width / 2, center_y - height / 2 - border_width / 2
        o_rb = center_x + width / 2 + border_width / 2, center_y - height / 2 - border_width / 2
        o_rt = center_x + width / 2 + border_width / 2, center_y + height / 2 + border_width / 2
        o_lt = center_x - width / 2 - border_width / 2, center_y + height / 2 + border_width / 2

        data = [o_lt, i_lt, o_rt, i_rt, o_rb, i_rb, o_lb, i_lb, o_lt, i_lt]

        if tilt_angle != 0:
            point_list_2: List[Point] = []
            for point in data:
                new_point = rotate_point(point[0], point[1], center_x, center_y, tilt_angle)
                point_list_2.append(new_point)
            data = point_list_2

        border_width = 1
        shape_mode = gl.GL_TRIANGLE_STRIP

        # _generic_draw_line_strip(point_list, color, gl.GL_TRIANGLE_STRIP)

        # shape_mode = gl.GL_LINE_STRIP
        # data.append(data[0])

    shape = create_line_generic(data, color, shape_mode, border_width)
    return shape
示例#30
0
def draw_ellipse_outline(center_x: float,
                         center_y: float,
                         width: float,
                         height: float,
                         color: Color,
                         border_width: float = 1,
                         tilt_angle: float = 0,
                         num_segments: int = 128):
    """
    Draw the outline of an ellipse.

    :param float center_x: x position that is the center of the circle.
    :param float center_y: y position that is the center of the circle.
    :param float width: width of the ellipse.
    :param float height: height of the ellipse.
    :param Color color: color, specified in a list of 3 or 4 bytes in RGB or
         RGBA format.
    :param float border_width: Width of the circle outline in pixels.
    :param float tilt_angle: Angle in degrees to tilt the ellipse.
    :param int num_segments: Number of line segments used to make the ellipse
    """

    if border_width == 1:
        unrotated_point_list = []

        for segment in range(num_segments):
            theta = 2.0 * 3.1415926 * segment / num_segments

            x = (width / 2) * math.cos(theta)
            y = (height / 2) * math.sin(theta)

            unrotated_point_list.append([x, y])

        if tilt_angle == 0:
            uncentered_point_list = unrotated_point_list
        else:
            uncentered_point_list = []
            for point in unrotated_point_list:
                uncentered_point_list.append(
                    rotate_point(point[0], point[1], 0, 0, tilt_angle))

        point_list = []
        for point in uncentered_point_list:
            point_list.append((point[0] + center_x, point[1] + center_y))

        _generic_draw_line_strip(point_list, color, gl.GL_LINE_LOOP)
    else:

        unrotated_point_list = []

        start_segment = 0
        end_segment = num_segments

        inside_width = (width / 2) - border_width / 2
        outside_width = (width / 2) + border_width / 2
        inside_height = (height / 2) - border_width / 2
        outside_height = (height / 2) + border_width / 2

        for segment in range(start_segment, end_segment + 1):
            theta = 2.0 * math.pi * segment / num_segments

            x1 = inside_width * math.cos(theta)
            y1 = inside_height * math.sin(theta)

            x2 = outside_width * math.cos(theta)
            y2 = outside_height * math.sin(theta)

            unrotated_point_list.append([x1, y1])
            unrotated_point_list.append([x2, y2])

        if tilt_angle == 0:
            uncentered_point_list = unrotated_point_list
        else:
            uncentered_point_list = []
            for point in unrotated_point_list:
                uncentered_point_list.append(
                    rotate_point(point[0], point[1], 0, 0, tilt_angle))

        point_list = []
        for point in uncentered_point_list:
            point_list.append((point[0] + center_x, point[1] + center_y))

        _generic_draw_line_strip(point_list, color, gl.GL_TRIANGLE_STRIP)