Beispiel #1
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:
        # v2f.extend([-shape.width / 2, -shape.height / 2,
        #            shape.width / 2, -shape.height / 2,
        #            shape.width / 2, shape.height / 2,
        #            -shape.width / 2, shape.height / 2])
        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
Beispiel #2
0
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.
    """
    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
Beispiel #3
0
    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_idx in range(len(self._points)):
                point = (self._points[point_idx][0] + self.center_x,
                         self._points[point_idx][1] + self.center_y)
                point_list.append(point)
            self._point_list_cache = tuple(point_list)
        else:
            x1, y1 = rotate_point(self.center_x - self.width / 2,
                                  self.center_y - self.height / 2,
                                  self.center_x, self.center_y, self.angle)
            x2, y2 = rotate_point(self.center_x + self.width / 2,
                                  self.center_y - self.height / 2,
                                  self.center_x, self.center_y, self.angle)
            x3, y3 = rotate_point(self.center_x + self.width / 2,
                                  self.center_y + self.height / 2,
                                  self.center_x, self.center_y, self.angle)
            x4, y4 = rotate_point(self.center_x - self.width / 2,
                                  self.center_y + self.height / 2,
                                  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
Beispiel #4
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=32) -> Shape:
    """
    Draw an ellipse, and specify inside/outside color. Used for doing gradients.
    """
    # Create an array with the vertex data
    # Create an array with the vertex point_list
    point_list = []

    point_list.append((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)
Beispiel #5
0
    def get_points(self) -> Tuple[Tuple[float, float]]:
        """
        Get the corner points for the rect that makes up the sprite.

        >>> import arcade
        >>> empty_sprite = arcade.Sprite()
        >>> my_points = (0,0),(1,1),(0,1),(1,0)
        >>> empty_sprite.set_points(my_points)
        >>> empty_sprite.get_points()
        ((0, 0), (1, 1), (0, 1), (1, 0))
        """
        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 = rotate_point(self.center_x - self.width / 2,
                                  self.center_y - self.height / 2,
                                  self.center_x,
                                  self.center_y,
                                  self.angle)
            x2, y2 = rotate_point(self.center_x + self.width / 2,
                                  self.center_y - self.height / 2,
                                  self.center_x,
                                  self.center_y,
                                  self.angle)
            x3, y3 = rotate_point(self.center_x + self.width / 2,
                                  self.center_y + self.height / 2,
                                  self.center_x,
                                  self.center_y,
                                  self.angle)
            x4, y4 = rotate_point(self.center_x - self.width / 2,
                                  self.center_y + self.height / 2,
                                  self.center_x,
                                  self.center_y,
                                  self.angle)

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

        self.add_spatial_hashes()
        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
Beispiel #7
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=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.

    >>> import arcade
    >>> arcade.open_window(800, 600, "Drawing Example")
    >>> arcade.start_render()
    >>> rect = arcade.create_ellipse(50, 50, 20, 20, arcade.color.RED, 2, 45)
    >>> arcade.render(rect)
    >>> arcade.finish_render()
    >>> arcade.quick_run(0.25)

    """
    # 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)
Beispiel #8
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=32) -> Shape:

    """
    >>> import arcade
    >>> arcade.open_window(800,600,"Drawing Example")
    >>> point_list = [(0, 0), (100, 0), (100, 100)]
    >>> color_list = [arcade.color.RED, arcade.color.BLUE, arcade.color.GREEN]
    >>> my_shape = arcade.create_ellipse_filled_with_colors(100, 100, 50, 50, arcade.color.AFRICAN_VIOLET, arcade.color.ALABAMA_CRIMSON, tilt_angle=45)
    >>> my_shape_list = ShapeElementList()
    >>> my_shape_list.append(my_shape)
    >>> my_shape_list.draw()
    >>> arcade.finish_render()
    >>> arcade.quick_run(0.25)
    """
    # Create an array with the vertex data
    # Create an array with the vertex point_list
    point_list = []

    point_list.append((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_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=32) -> VertexBuffer:

    """
    >>> import arcade
    >>> arcade.open_window(800,600,"Drawing Example")
    >>> point_list = [(0, 0), (100, 0), (100, 100)]
    >>> color_list = [arcade.color.RED, arcade.color.BLUE, arcade.color.GREEN]
    >>> my_shape = arcade.create_ellipse_filled_with_colors(100, 100, 50, 50, arcade.color.AFRICAN_VIOLET, arcade.color.ALABAMA_CRIMSON, tilt_angle=45)
    >>> my_shape_list = ShapeElementList()
    >>> my_shape_list.append(my_shape)
    >>> my_shape_list.draw()
    >>> arcade.finish_render()
    >>> arcade.quick_run(0.25)
    """
    # Create an array with the vertex data
    vertex_data = []
    color_data = []
    vertex_data.extend((center_x, center_y))
    color_data.append((inside_color))
    for segment in range(num_segments + 1):
        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)

        vertex_data.extend([x, y])
        color_data.append((outside_color))

    # Create an id for our vertex buffer
    vbo_vertex_id = gl.GLuint()

    gl.glGenBuffers(1, ctypes.pointer(vbo_vertex_id))

    # Create a buffer with the data
    # This line of code is a bit strange.
    # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number
    # (*data) initalizes the list with the floats. *data turns the list into a
    # tuple.
    data2 = (gl.GLfloat * len(vertex_data))(*vertex_data)

    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_vertex_id)
    gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2,
                    gl.GL_STATIC_DRAW)

    shape_mode = gl.GL_TRIANGLE_FAN
    # shape_mode = gl.GL_LINE_LOOP

    # Colors
    color_data = _fix_color_list(color_data)
    vbo_color_id = gl.GLuint()
    gl.glGenBuffers(1, ctypes.pointer(vbo_color_id))

    gl_color_list = (gl.GLfloat * len(color_data))(*color_data)
    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_color_id)
    gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl_color_list), gl_color_list, gl.GL_STATIC_DRAW)

    shape = VertexBuffer(vbo_vertex_id, len(vertex_data) // 2, shape_mode, vbo_color_id=vbo_color_id)

    return shape
def create_ellipse(center_x: float, center_y: float,
                   width: float, height: float, color: Color,
                   border_width: float=0,
                   tilt_angle: float=0, num_segments=32,
                   filled=True) -> VertexBuffer:

    """
    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.

    >>> import arcade
    >>> arcade.open_window(800, 600, "Drawing Example")
    >>> arcade.start_render()
    >>> rect = arcade.create_ellipse(50, 50, 20, 20, arcade.color.RED, 2, 45)
    >>> arcade.render(rect)
    >>> arcade.finish_render()
    >>> arcade.quick_run(0.25)

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

    for segment in range(num_segments + 1):
        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)

        data.extend([x, y])

    # Create an id for our vertex buffer
    vbo_id = gl.GLuint()

    gl.glGenBuffers(1, ctypes.pointer(vbo_id))

    # Create a buffer with the data
    # This line of code is a bit strange.
    # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number
    # (*data) initalizes the list with the floats. *data turns the list into a
    # tuple.
    data2 = (gl.GLfloat * len(data))(*data)

    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id)
    gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2,
                    gl.GL_STATIC_DRAW)

    if filled:
        shape_mode = gl.GL_TRIANGLE_FAN
    else:
        shape_mode = gl.GL_LINE_LOOP

    shape = VertexBuffer(vbo_id, len(data) // 2, shape_mode)
    shape.color = color
    shape.line_width = border_width
    return shape