예제 #1
0
    def draw_polyline(self, point_list, line_width, line_color):
        # type: (Sequence[Sequence[Union[int, float]]], Union[int, float], str) -> None  # noqa
        """
        Draw line segments between a list of points.

        If `line_width` > 1, ends are poorly made!

        :param point_list: not empty (tuple or list)
                           of ((int or float, int or float)
                           or [int or float, int or float])
        :param line_width: (int or float) > 0
        :param line_color: str
        """
        assert isinstance(point_list, (tuple, list)), type(point_list)
        assert len(point_list) > 0, len(point_list)

        if __debug__:
            for point in point_list:
                assert isinstance(point, (tuple, list)), type(point)
                assert len(point) == 2, len(point)
                assert isinstance(point[0], (int, float)), type(point[0])
                assert isinstance(point[1], (int, float)), type(point[1])

        assert isinstance(line_width, (int, float)), type(line_width)
        assert line_width > 0, line_width

        assert isinstance(line_color, str), type(line_color)

        if len(point_list) == 1:
            return

        pygamecolor = _simpleguicolor_to_pygamecolor(line_color)

        point_list_rounded = [_pos_round(point) for point in point_list]

        del point_list

        line_width = int(round(line_width))

        if pygamecolor.a == 255:  # without alpha
            pygame.draw.lines(self._pygame_surface, pygamecolor, False,
                              point_list_rounded, line_width)
        elif pygamecolor.a > 0:  # with alpha (not null)
            s_alpha = pygame.surface.Surface(
                (self._width, self._height),  # pylint: disable=too-many-function-args  # noqa
                pygame.SRCALPHA)  # pylint: disable=no-member  # noqa

            pygame.draw.lines(s_alpha, pygamecolor, False, point_list_rounded,
                              line_width)

            self._pygame_surface.blit(s_alpha, (0, 0))
예제 #2
0
    def draw_line(self, point1, point2, line_width, line_color):
        # type: (Sequence[Union[int, float]], Sequence[Union[int, float]], Union[int, float], str) -> None  # noqa
        """
        Draw a line segment from point1 to point2.

        :param point1: (int or float, int or float)
                       or [int or float, int or float]
        :param point2: (int or float, int or float)
                       or [int or float, int or float]
        :param line_width: (int or float) > 0
        :param line_color: str
        """
        assert isinstance(point1, (tuple, list)), type(point1)
        assert len(point1) == 2, len(point1)
        assert isinstance(point1[0], (int, float)), type(point1[0])
        assert isinstance(point1[1], (int, float)), type(point1[1])

        assert isinstance(point2, (tuple, list)), type(point2)
        assert len(point2) == 2, len(point2)
        assert isinstance(point2[0], (int, float)), type(point2[0])
        assert isinstance(point2[1], (int, float)), type(point2[1])

        assert isinstance(line_width, (int, float)), type(line_width)
        assert line_width > 0, line_width

        assert isinstance(line_color, str), type(line_color)

        pygamecolor = _simpleguicolor_to_pygamecolor(line_color)

        if pygamecolor.a == 255:  # without alpha
            pygame.draw.line(self._pygame_surface, pygamecolor,
                             _pos_round(point1), _pos_round(point2),
                             int(round(line_width)))
        elif pygamecolor.a > 0:  # with alpha (not null)
            x1, y1 = _pos_round(point1)
            x2, y2 = _pos_round(point2)  # pylint: disable=invalid-name  # noqa

            width = abs(x2 - x1) + line_width * 2
            height = abs(y2 - y1) + line_width * 2

            x_min = min(x1, x2)
            y_min = min(y1, y2)

            s_alpha = pygame.surface.Surface((width, height), pygame.SRCALPHA)  # pylint: disable=too-many-function-args,no-member  # noqa
            pygame.draw.line(
                s_alpha, pygamecolor,
                (x1 - x_min + line_width, y1 - y_min + line_width),
                (x2 - x_min + line_width, y2 - y_min + line_width),
                int(round(line_width)))
            self._pygame_surface.blit(s_alpha,
                                      (x_min - line_width, y_min - line_width))
예제 #3
0
    def draw_point(self, position, color):
        # type: (Sequence[Union[int, float]], str) -> None
        """
        Draw a point.

        :param position: (int or float, int or float)
                         or [int or float, int or float]
        :param color: str
        """
        assert isinstance(position, (tuple, list)), type(position)
        assert len(position) == 2, len(position)
        assert isinstance(position[0], (int, float)), type(position[0])
        assert isinstance(position[1], (int, float)), type(position[1])

        assert isinstance(color, str), type(color)

        pygamecolor = _simpleguicolor_to_pygamecolor(color)

        if pygamecolor.a == 255:  # without alpha
            self._pygame_surface.set_at(_pos_round(position), pygamecolor)
        elif pygamecolor.a > 0:  # with alpha (not null)
            s_alpha = pygame.surface.Surface((1, 1), pygame.SRCALPHA)  # pylint: disable=too-many-function-args,no-member  # noqa
            s_alpha.set_at((0, 0), pygamecolor)
            self._pygame_surface.blit(s_alpha, _pos_round(position))
예제 #4
0
    def draw_text(
            self,  # pylint: disable=too-many-arguments
            text,
            point,
            font_size,
            font_color,
            font_face='serif',
            _font_size_coef=3 / 4):
        # type: (str, Sequence[Union[int, float]], Union[int, float], str, str, Union[int, float]) -> None  # noqa
        """
        Draw the `text` string at the position `point`.

        (`point[0]` is the left of the text,
        `point[1]` is the bottom of the text.)

        If correponding font in Pygame is not founded,
        then use the default `pygame.font.Font`.

        `_font_size_coef` is used to adjust the vertical positioning.
        **(This paramater is not available in SimpleGUI of CodeSkulptor.)**

        :warning: This method can't draw multiline text.

        To draw multiline text, see `simplegui_lib_draw.draw_text_multi()`_ .

        .. _`simplegui_lib_draw.draw_text_multi()`: ../simplegui_lib_draw.html#SimpleGUICS2Pygame.simplegui_lib_draw.draw_text_multi

        :param text: str
        :param point: (int or float, int or float)
                      or [int or float, int or float]
        :param font_size: (int or float) >= 0
        :param font_color: str
        :param font_face: str == 'monospace', 'sans-serif', 'serif'
        :param _font_size_coef: int or float

        :raise: ValueError if text contains unprintable whitespace character

        **(Alpha color channel don't work!!!)**
        """  # noqa
        assert isinstance(text, str), type(text)

        assert isinstance(point, (tuple, list)), type(point)
        assert len(point) == 2, len(point)
        assert isinstance(point[0], (int, float)), type(point[0])
        assert isinstance(point[1], (int, float)), type(point[1])

        assert isinstance(font_size, (int, float)), type(font_size)
        assert font_size >= 0, font_size

        assert isinstance(font_color, str), type(font_color)

        assert isinstance(font_face, str), type(font_face)
        assert font_face in _SIMPLEGUIFONTFACE_TO_PYGAMEFONTNAME, font_face

        assert isinstance(_font_size_coef, (int, float)), type(_font_size_coef)

        if text == '':
            return

        if _RE_UNPRINTABLE_WHITESPACE_CHAR.search(text):
            raise ValueError('text may not contain non-printing characters')

        pygamecolor = _simpleguicolor_to_pygamecolor(font_color)
        font_size = int(round(font_size))

        if (pygamecolor.a > 0) and (font_size > 0):
            pygame_surface_text = _simpleguifontface_to_pygamefont(
                font_face, font_size).render(text, True, pygamecolor)

            # if pygamecolor.a == 255:  # without alpha
            self._pygame_surface.blit(
                pygame_surface_text,
                (point[0],
                 (point[1] -
                  pygame_surface_text.get_height() * _font_size_coef)))
예제 #5
0
    def draw_polygon(self,
                     point_list,
                     line_width,
                     line_color,
                     fill_color=None):
        # type: (Sequence[Sequence[Union[int, float]]], Union[int, float], str, Optional[str]) -> None  # noqa
        """
        Draw a polygon from a list of points.
        A segment is automatically drawed
        between the last point and the first point.

        If `fill color` is not None
        then fill with this color.

        If `line_width` > 1, ends are poorly made!

        :param point_list: not empty (tuple or list)
                           of ((int or float, int or float)
                           or [int or float, int or float])
        :param line_width: (int or float) > 0
        :param line_color: str
        :param fill_color: None or str
        """
        assert isinstance(point_list, (tuple, list)), type(point_list)
        assert len(point_list) > 0, len(point_list)

        if __debug__:
            for point in point_list:
                assert isinstance(point, (tuple, list)), type(point)
                assert len(point) == 2, len(point)
                assert isinstance(point[0], (int, float)), type(point[0])
                assert isinstance(point[1], (int, float)), type(point[1])

        assert isinstance(line_width, (int, float)), type(line_width)
        assert line_width >= 0, line_width

        assert isinstance(line_color, str), type(line_color)
        assert (fill_color is None) or isinstance(fill_color, str), \
            type(fill_color)

        if len(point_list) == 1:
            return

        pygamecolor = _simpleguicolor_to_pygamecolor(line_color)
        pygamefillcolor = (None if fill_color is None else
                           _simpleguicolor_to_pygamecolor(fill_color))

        point_list_rounded = [_pos_round(point) for point in point_list]

        del point_list

        line_width = int(round(line_width))

        if ((pygamecolor.a == 255)
                and ((pygamefillcolor is None) or (pygamefillcolor.a == 255))):
            # Without alpha
            if pygamefillcolor is not None:
                pygame.draw.polygon(self._pygame_surface, pygamefillcolor,
                                    point_list_rounded, 0)
            if pygamecolor != pygamefillcolor:
                pygame.draw.lines(self._pygame_surface, pygamecolor, True,
                                  point_list_rounded, line_width)
        elif ((pygamecolor.a > 0)
              or ((pygamefillcolor is not None) and (pygamefillcolor.a > 0))):
            # With one or two alpha (not null)
            s_alpha = pygame.surface.Surface(
                (self._width, self._height),  # pylint: disable=too-many-function-args  # noqa
                pygame.SRCALPHA)  # pylint: disable=no-member  # noqa

            if (pygamefillcolor is not None) and (pygamefillcolor.a > 0):
                pygame.draw.polygon(s_alpha, pygamefillcolor,
                                    point_list_rounded, 0)
            if (pygamecolor != pygamefillcolor) and (pygamecolor.a > 0):
                pygame.draw.lines(s_alpha, pygamecolor, True,
                                  point_list_rounded, line_width)

            self._pygame_surface.blit(s_alpha, (0, 0))
예제 #6
0
    def draw_circle(
            self,  # pylint: disable=too-many-arguments
            center_point,
            radius,
            line_width,
            line_color,
            fill_color=None):
        # type: (Sequence[Union[int, float]], Union[int, float], Union[int, float], str, Optional[str]) -> None  # noqa
        """
        Draw a circle.

        If `fill_color` != `None`
        then fill with this color.

        :param center_point: (int or float, int or float)
                             or [int or float, int or float]
        :param radius: (int or float) > 0
        :param line_width: (int or float) > 0
        :param line_color: str
        :param fill_color: None or str
        """
        assert isinstance(center_point, (tuple, list)), type(center_point)
        assert len(center_point) == 2, len(center_point)
        assert isinstance(center_point[0], (int, float)), type(center_point[0])
        assert isinstance(center_point[1], (int, float)), type(center_point[1])

        assert isinstance(radius, (int, float)), type(radius)
        assert radius > 0, radius

        assert isinstance(line_width, (int, float)), type(line_width)
        assert line_width > 0, line_width

        assert isinstance(line_color, str), type(line_color)
        assert (fill_color is None) or isinstance(fill_color, str), \
            type(fill_color)

        line_width = (1 if line_width <= 1 else int(round(line_width)))

        radius = int(round(radius)) + int(round(line_width // 2))

        if radius > 1:
            pygamecolor = _simpleguicolor_to_pygamecolor(line_color)
            pygamefillcolor = (None if fill_color is None else
                               _simpleguicolor_to_pygamecolor(fill_color))

            center_point_rounded = _pos_round(center_point)

            if ((pygamecolor.a == 255) and ((pygamefillcolor is None) or
                                            (pygamefillcolor.a == 255))):
                # Without alpha
                if pygamefillcolor is not None:
                    pygame.draw.circle(self._pygame_surface, pygamefillcolor,
                                       center_point_rounded, radius, 0)
                if pygamecolor != pygamefillcolor:
                    pygame.draw.circle(self._pygame_surface, pygamecolor,
                                       center_point_rounded, radius,
                                       min(line_width, radius))
            elif ((pygamecolor.a > 0) or ((pygamefillcolor is not None) and
                                          (pygamefillcolor.a > 0))):
                # With one or two alpha (not null)
                diameter = radius * 2
                s_alpha = pygame.surface.Surface(
                    (diameter, diameter),  # pylint: disable=too-many-function-args  # noqa
                    pygame.SRCALPHA)  # pylint: disable=no-member  # noqa

                if (pygamefillcolor is not None) and (pygamefillcolor.a > 0):
                    pygame.draw.circle(s_alpha, pygamefillcolor,
                                       (radius, radius), radius, 0)
                if (pygamecolor != pygamefillcolor) and (pygamecolor.a > 0):
                    pygame.draw.circle(s_alpha, pygamecolor, (radius, radius),
                                       radius, min(line_width, radius))

                self._pygame_surface.blit(s_alpha,
                                          (center_point_rounded[0] - radius,
                                           center_point_rounded[1] - radius))
        elif radius > 0:  # == 1
            self.draw_point(center_point, line_color)
예제 #7
0
    def draw_arc(
            self,  # pylint: disable=too-many-arguments
            center_point,
            radius,
            start_angle,
            end_angle,
            line_width,
            line_color):
        # type: (Sequence[Union[int, float]], Union[int, float], Union[int, float], Union[int, float], Union[int, float], str) -> None  # noqa
        """
        Draw an arc of circle, from `start_angle` to `end_angle`.
        Angles given in radians are clockwise
        and start from 0 at the 3 o'clock position.

        (Available in CodeSkulptor3 but *not in CodeSkulptor2*!)

        :param center_point: (int or float, int or float)
                             or [int or float, int or float]
        :param radius: (int or float) > 0
        :param start_angle: int or float
        :param end_angle: int or float
        :param line_width: (int or float) > 0
        :param line_color: str
        """
        assert isinstance(center_point, (tuple, list)), type(center_point)
        assert len(center_point) == 2, len(center_point)
        assert isinstance(center_point[0], (int, float)), type(center_point[0])
        assert isinstance(center_point[1], (int, float)), type(center_point[1])

        assert isinstance(radius, (int, float)), type(radius)
        assert radius > 0, radius

        assert isinstance(start_angle, (int, float)), (start_angle)
        assert isinstance(end_angle, (int, float)), type(end_angle)

        assert isinstance(line_width, (int, float)), type(line_width)
        assert line_width > 0, line_width

        assert isinstance(line_color, str), type(line_color)

        line_width = (1 if line_width <= 1 else int(round(line_width)))

        radius = int(round(radius)) + int(round(line_width // 2))

        # Adapt Codeskulptor angles to Pygame
        if start_angle == end_angle:
            return

        start_angle = -start_angle
        end_angle = -end_angle
        start_angle, end_angle = end_angle, start_angle

        double_pi = math.pi * 2
        start_angle %= double_pi
        end_angle %= double_pi

        if start_angle == end_angle:
            return

        # Draw
        if radius > 1:
            pygamecolor = _simpleguicolor_to_pygamecolor(line_color)

            if pygamecolor.a > 0:
                diameter = radius * 2
                s_tmp = pygame.surface.Surface(
                    (diameter, diameter),  # pylint: disable=too-many-function-args  # noqa
                    pygame.SRCALPHA)  # pylint: disable=no-member  # noqa

                pygame.draw.arc(s_tmp, pygamecolor,
                                s_tmp.get_rect(), start_angle, end_angle,
                                min(line_width, radius))

                self._pygame_surface.blit(
                    s_tmp,
                    (center_point[0] - radius, center_point[1] - radius))
        elif radius > 0:  # == 1
            self.draw_point(center_point, line_color)