def draw_ellipse(self, x, y, width, height, fill=None, outline=None, outline_thickness=1, anti_alias=False, frame=None): """Draw an ellipse on the sprite. Arguments: - ``x`` -- The horizontal location relative to the sprite to position the imaginary rectangle containing the ellipse. - ``y`` -- The vertical location relative to the sprite to position the imaginary rectangle containing the ellipse. - ``width`` -- The width of the ellipse. - ``height`` -- The height of the ellipse. - ``fill`` -- The color of the fill of the ellipse. - ``outline`` -- The color of the outline of the ellipse. - ``outline_thickness`` -- The thickness of the outline of the ellipse. - ``anti_alias`` -- Whether or not anti-aliasing should be used. - ``frame`` -- The frame of the sprite to draw on, where ``0`` is the first frame; set to :const:`None` to draw on all frames. """ outline_thickness = abs(outline_thickness) if outline_thickness == 0: outline = None if fill is None and outline is None: # There's no point in trying in this case. return rect = pygame.Rect(x, y, width, height) for i in xrange(len(self._baseimages)): if frame is None or frame % len(self._baseimages) == i: if fill is not None: c = sge._get_pygame_color(fill) pygame.draw.ellipse(self._baseimages[i], c, rect) if outline is not None: c = sge._get_pygame_color(outline) pygame.draw.ellipse(self._baseimages[i], c, rect, outline_thickness) self._refresh()
def draw_rectangle(self, x, y, width, height, fill=None, outline=None, outline_thickness=1, frame=None): """Draw a rectangle on the sprite. Arguments: - ``x`` -- The horizontal location relative to the sprite to draw the rectangle. - ``y`` -- The vertical location relative to the sprite to draw the rectangle. - ``width`` -- The width of the rectangle. - ``height`` -- The height of the rectangle. - ``fill`` -- The color of the fill of the rectangle. - ``outline`` -- The color of the outline of the rectangle. - ``outline_thickness`` -- The thickness of the outline of the rectangle. - ``frame`` -- The frame of the sprite to draw on, where ``0`` is the first frame; set to :const:`None` to draw on all frames. """ outline_thickness = abs(outline_thickness) if outline_thickness == 0: outline = None if fill is None and outline is None: # There's no point in trying in this case. return rect = pygame.Rect(x, y, width, height) for i in xrange(len(self._baseimages)): if frame is None or frame % len(self._baseimages) == i: if fill is not None: pygame.draw.rect(self._baseimages[i], sge._get_pygame_color(fill), rect, 0) if outline is not None: pygame.draw.rect(self._baseimages[i], sge._get_pygame_color(outline), rect, outline_thickness) self._refresh()
def draw_circle(self, x, y, radius, fill=None, outline=None, outline_thickness=1, anti_alias=False, frame=None): """Draw a circle on the sprite. Arguments: - ``x`` -- The horizontal location relative to the sprite to position the center of the circle. - ``y`` -- The vertical location relative to the sprite to position the center of the circle. - ``radius`` -- The radius of the circle. - ``fill`` -- The color of the fill of the circle. - ``outline`` -- The color of the outline of the circle. - ``outline_thickness`` -- The thickness of the outline of the circle. - ``anti_alias`` -- Whether or not anti-aliasing should be used. - ``frame`` -- The frame of the sprite to draw on, where ``0`` is the first frame; set to :const:`None` to draw on all frames. """ outline_thickness = abs(outline_thickness) if outline_thickness == 0: outline = None if fill is None and outline is None: # There's no point in trying in this case. return for i in xrange(len(self._baseimages)): if frame is None or frame % len(self._baseimages) == i: if fill is not None: c = sge._get_pygame_color(fill) pygame.draw.circle(self._baseimages[i], c, (x, y), radius) if outline is not None: c = sge._get_pygame_color(outline) pygame.draw.circle(self._baseimages[i], c, (x, y), radius, outline_thickness) self._refresh()
def _get_image(self, num, xscale=1, yscale=1, rotation=0, alpha=255, blend=None): num %= len(self._images) # Return the properly sized surface. if (xscale, yscale, rotation, alpha, blend) in self._images[num]: return self._images[num][(xscale, yscale, rotation, alpha, blend)] else: # Hasn't been scaled to this size yet if xscale != 0 and yscale != 0: img = self._set_transparency(self._baseimages[num]) xflip = xscale < 0 yflip = yscale < 0 img = pygame.transform.flip(img, xflip, yflip) img = sge._scale(img, self.width * abs(xscale), self.height * abs(yscale)) if rotation != 0: img = pygame.transform.rotate(img, rotation) if alpha < 255: if img.get_flags() & pygame.SRCALPHA: # Have to do this the more difficult way. img.fill((0, 0, 0, 255 - alpha), None, pygame.BLEND_RGBA_SUB) else: img.set_alpha(alpha, pygame.RLEACCEL) if blend is not None: img.fill(sge._get_pygame_color(blend), None, pygame.BLEND_RGB_MULT) else: img = pygame.Surface((1, 1)) img.set_colorkey((0, 0, 0), pygame.RLEACCEL) self._images[num][(xscale, yscale, rotation, alpha, blend)] = img return img
def draw_line(self, x1, y1, x2, y2, color, thickness=1, anti_alias=False, frame=None): """Draw a line segment on the sprite. Arguments: - ``x1`` -- The horizontal location relative to the sprite of the first end point of the line segment. - ``y1`` -- The vertical location relative to the sprite of the first end point of the line segment. - ``x2`` -- The horizontal location relative to the sprite of the second end point of the line segment. - ``y2`` -- The vertical location relative to the sprite of the second end point of the line segment. - ``color`` -- The color of the line segment. - ``thickness`` -- The thickness of the line segment. - ``anti_alias`` -- Whether or not anti-aliasing should be used. - ``frame`` -- The frame of the sprite to draw on, where ``0`` is the first frame; set to :const:`None` to draw on all frames. """ color = sge._get_pygame_color(color) thickness = abs(thickness) for i in xrange(len(self._baseimages)): if frame is None or frame % len(self._baseimages) == i: if anti_alias and thickness == 1: pygame.draw.aaline(self._baseimages[i], color, (x1, y1), (x2, y2)) else: pygame.draw.line(self._baseimages[i], color, (x1, y1), (x2, y2), thickness) self._refresh()
def draw_ellipse( self, x, y, width, height, fill=None, outline=None, outline_thickness=1, anti_alias=False, frame=None ): """Draw an ellipse on the sprite. Arguments: - ``x`` -- The horizontal location relative to the sprite to position the imaginary rectangle containing the ellipse. - ``y`` -- The vertical location relative to the sprite to position the imaginary rectangle containing the ellipse. - ``width`` -- The width of the ellipse. - ``height`` -- The height of the ellipse. - ``fill`` -- The color of the fill of the ellipse. - ``outline`` -- The color of the outline of the ellipse. - ``outline_thickness`` -- The thickness of the outline of the ellipse. - ``anti_alias`` -- Whether or not anti-aliasing should be used. - ``frame`` -- The frame of the sprite to draw on, where ``0`` is the first frame; set to :const:`None` to draw on all frames. """ outline_thickness = abs(outline_thickness) if outline_thickness == 0: outline = None if fill is None and outline is None: # There's no point in trying in this case. return rect = pygame.Rect(x, y, width, height) for i in xrange(len(self._baseimages)): if frame is None or frame % len(self._baseimages) == i: if fill is not None: c = sge._get_pygame_color(fill) pygame.draw.ellipse(self._baseimages[i], c, rect) if outline is not None: c = sge._get_pygame_color(outline) pygame.draw.ellipse(self._baseimages[i], c, rect, outline_thickness) self._refresh()
def draw_rectangle(self, x, y, width, height, fill=None, outline=None, outline_thickness=1, frame=None): """Draw a rectangle on the sprite. Arguments: - ``x`` -- The horizontal location relative to the sprite to draw the rectangle. - ``y`` -- The vertical location relative to the sprite to draw the rectangle. - ``width`` -- The width of the rectangle. - ``height`` -- The height of the rectangle. - ``fill`` -- The color of the fill of the rectangle. - ``outline`` -- The color of the outline of the rectangle. - ``outline_thickness`` -- The thickness of the outline of the rectangle. - ``frame`` -- The frame of the sprite to draw on, where 0 is the first frame; set to None to draw on all frames. """ outline_thickness = abs(outline_thickness) if outline_thickness == 0: outline = None if fill is None and outline is None: # There's no point in trying in this case. return rect = pygame.Rect(x, y, width, height) for i in xrange(len(self._baseimages)): if frame is None or frame % len(self._baseimages) == i: if fill is not None: pygame.draw.rect(self._baseimages[i], sge._get_pygame_color(fill), rect, 0) if outline is not None: pygame.draw.rect(self._baseimages[i], sge._get_pygame_color(outline), rect, outline_thickness) self._refresh()
def draw_dot(self, x, y, color, frame=None): """Draw a single-pixel dot on the sprite. Arguments: - ``x`` -- The horizontal location relative to the sprite to draw the dot. - ``y`` -- The vertical location relative to the sprite to draw the dot. - ``color`` -- The color of the dot. - ``frame`` -- The frame of the sprite to draw on, where 0 is the first frame; set to None to draw on all frames. """ color = sge._get_pygame_color(color) for i in xrange(len(self._baseimages)): if frame is None or frame % len(self._baseimages) == i: self._baseimages[i].set_at((x, y), color) self._refresh()
def draw_dot(self, x, y, color, frame=None): """Draw a single-pixel dot on the sprite. Arguments: - ``x`` -- The horizontal location relative to the sprite to draw the dot. - ``y`` -- The vertical location relative to the sprite to draw the dot. - ``color`` -- The color of the dot. - ``frame`` -- The frame of the sprite to draw on, where ``0`` is the first frame; set to :const:`None` to draw on all frames. """ color = sge._get_pygame_color(color) for i in xrange(len(self._baseimages)): if frame is None or frame % len(self._baseimages) == i: self._baseimages[i].set_at((x, y), color) self._refresh()
def draw_text( self, font, text, x, y, width=None, height=None, color="black", halign=sge.ALIGN_LEFT, valign=sge.ALIGN_TOP, anti_alias=True, frame=None, ): """Draw text on the sprite. Arguments: - ``font`` -- The font to use to draw the text. - ``text`` -- The text (as a string) to draw. - ``x`` -- The horizontal location relative to the sprite to draw the text. - ``y`` -- The vertical location relative to the sprite to draw the text. - ``width`` -- The width of the imaginary rectangle the text is drawn in; set to :const:`None` to make the rectangle as wide as needed to contain the text without additional line breaks. If set to something other than :const:`None`, a line which does not fit will be automatically split into multiple lines that do fit. - ``height`` -- The height of the imaginary rectangle the text is drawn in; set to :const:`None` to make the rectangle as tall as needed to contain the text. - ``color`` -- The color of the text. - ``halign`` -- The horizontal alignment of the text and the horizontal location of the origin of the imaginary rectangle the text is drawn in. Can be set to one of the following: - :data:`sge.ALIGN_LEFT` -- Align the text to the left of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its left edge. - :data:`sge.ALIGN_CENTER` -- Align the text to the center of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its center. - :data:`sge.ALIGN_RIGHT` -- Align the text to the right of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its right edge. - ``valign`` -- The vertical alignment of the text and the vertical location of the origin of the imaginary rectangle the text is drawn in. Can be set to one of the following: - :data:`sge.ALIGN_TOP` -- Align the text to the top of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its top edge. If the imaginary rectangle is not tall enough to contain all of the text, cut text off from the bottom. - :data:`sge.ALIGN_MIDDLE` -- Align the the text to the middle of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its middle. If the imaginary rectangle is not tall enough to contain all of the text, cut text off equally from the top and bottom. - :data:`sge.ALIGN_BOTTOM` -- Align the text to the bottom of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its top edge. If the imaginary rectangle is not tall enough to contain all of the text, cut text off from the top. - ``anti_alias`` -- Whether or not anti-aliasing should be used. - ``frame`` -- The frame of the sprite to draw on, where ``0`` is the first frame; set to :const:`None` to draw on all frames. """ if not isinstance(font, sge.Font): font = sge.game.fonts[font] lines = font._split_text(text, width) width, height = font.get_size(text, width, height) fake_height = font.get_size(text, width)[1] color = sge._get_pygame_color(color) text_surf = pygame.Surface((width, fake_height), pygame.SRCALPHA) box_surf = pygame.Surface((width, height), pygame.SRCALPHA) text_rect = text_surf.get_rect() box_rect = box_surf.get_rect() for i in xrange(len(lines)): rendered_text = font._font.render(lines[i], anti_alias, color) rect = rendered_text.get_rect() rect.top = i * font._font.get_linesize() if halign == sge.ALIGN_LEFT: rect.left = text_rect.left elif halign == sge.ALIGN_RIGHT: rect.right = text_rect.right elif halign == sge.ALIGN_CENTER: rect.centerx = text_rect.centerx text_surf.blit(rendered_text, rect) if valign == sge.ALIGN_TOP: text_rect.top = box_rect.top elif valign == sge.ALIGN_BOTTOM: text_rect.bottom = box_rect.bottom elif valign == sge.ALIGN_MIDDLE: text_rect.centery = box_rect.centery box_surf.blit(text_surf, text_rect) if halign == sge.ALIGN_LEFT: box_rect.left = x elif halign == sge.ALIGN_RIGHT: box_rect.right = x elif halign == sge.ALIGN_CENTER: box_rect.centerx = x else: box_rect.left = x if valign == sge.ALIGN_TOP: box_rect.top = y elif valign == sge.ALIGN_BOTTOM: box_rect.bottom = y elif valign == sge.ALIGN_MIDDLE: box_rect.centery = y else: box_rect.top = y for i in xrange(len(self._baseimages)): if frame is None or frame % len(self._baseimages) == i: self._baseimages[i].blit(box_surf, box_rect) self._refresh()
def _get_background(self): # Return the static background this frame. background = pygame.Surface((round(sge.game.width * sge.game._xscale), round(sge.game.height * sge.game._yscale))) background.fill(sge._get_pygame_color(self.color)) for view in sge.game.current_room.views: view_x = int(round(view.x * sge.game._xscale)) view_y = int(round(view.y * sge.game._yscale)) view_xport = max(0, min(int(round(view.xport * sge.game._xscale)), background.get_width() - 1)) view_yport = max(0, min(int(round(view.yport * sge.game._yscale)), background.get_height() - 1)) view_w = min(view.width * sge.game._xscale, background.get_width() - view_xport) view_h = min(view.height * sge.game._yscale, background.get_height() - view_yport) surf = background.subsurface(view_xport, view_yport, view_w, view_h) for layer in self.layers: image = layer._get_image() x = int(round( (sge.game.current_room.background_x + layer.x - (view.x * layer.xscroll_rate)) * sge.game._xscale)) y = int(round( (sge.game.current_room.background_y + layer.y - (view.y * layer.yscroll_rate)) * sge.game._yscale)) image_w = max(1, image.get_width()) image_h = max(1, image.get_height()) # These equations bring the position to the largest # values possible while still being less than the # location we're getting the surface at. This is to # minimize the number of repeat blittings. if layer.xrepeat: x = (x % image_w) - image_w if layer.yrepeat: y = (y % image_h) - image_h # Apply the origin so the positions are as expected. x -= int(round(layer.sprite.origin_x * sge.game._xscale)) y -= int(round(layer.sprite.origin_y * sge.game._yscale)) if layer.xrepeat and layer.yrepeat: xstart = x while y < surf.get_height(): x = xstart while x < surf.get_width(): surf.blit(image, (x, y)) x += image_w y += image_h elif (layer.xrepeat and y < view_y + view_h and y + image_h > view_y): while x < surf.get_width(): surf.blit(image, (x, y)) x += image_w elif (layer.yrepeat and x < view_x + view_w and x + image_w > view_x): while y < surf.get_height(): surf.blit(image, (x, y)) y += image_h elif (x < surf.get_width() and x + image_w > 0 and y < surf.get_height() and y + image_h > 0): surf.blit(image, (x, y)) return background
def draw_text(self, font, text, x, y, width=None, height=None, color="black", halign=sge.ALIGN_LEFT, valign=sge.ALIGN_TOP, anti_alias=True, frame=None): """Draw text on the sprite. Arguments: - ``font`` -- The font to use to draw the text. - ``text`` -- The text (as a string) to draw. - ``x`` -- The horizontal location relative to the sprite to draw the text. - ``y`` -- The vertical location relative to the sprite to draw the text. - ``width`` -- The width of the imaginary rectangle the text is drawn in; set to :const:`None` to make the rectangle as wide as needed to contain the text without additional line breaks. If set to something other than :const:`None`, a line which does not fit will be automatically split into multiple lines that do fit. - ``height`` -- The height of the imaginary rectangle the text is drawn in; set to :const:`None` to make the rectangle as tall as needed to contain the text. - ``color`` -- The color of the text. - ``halign`` -- The horizontal alignment of the text and the horizontal location of the origin of the imaginary rectangle the text is drawn in. Can be set to one of the following: - :data:`sge.ALIGN_LEFT` -- Align the text to the left of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its left edge. - :data:`sge.ALIGN_CENTER` -- Align the text to the center of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its center. - :data:`sge.ALIGN_RIGHT` -- Align the text to the right of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its right edge. - ``valign`` -- The vertical alignment of the text and the vertical location of the origin of the imaginary rectangle the text is drawn in. Can be set to one of the following: - :data:`sge.ALIGN_TOP` -- Align the text to the top of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its top edge. If the imaginary rectangle is not tall enough to contain all of the text, cut text off from the bottom. - :data:`sge.ALIGN_MIDDLE` -- Align the the text to the middle of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its middle. If the imaginary rectangle is not tall enough to contain all of the text, cut text off equally from the top and bottom. - :data:`sge.ALIGN_BOTTOM` -- Align the text to the bottom of the imaginary rectangle the text is drawn in. Set the origin of the imaginary rectangle to its top edge. If the imaginary rectangle is not tall enough to contain all of the text, cut text off from the top. - ``anti_alias`` -- Whether or not anti-aliasing should be used. - ``frame`` -- The frame of the sprite to draw on, where ``0`` is the first frame; set to :const:`None` to draw on all frames. """ if not isinstance(font, sge.Font): font = sge.game.fonts[font] lines = font._split_text(text, width) width, height = font.get_size(text, width, height) fake_height = font.get_size(text, width)[1] color = sge._get_pygame_color(color) text_surf = pygame.Surface((width, fake_height), pygame.SRCALPHA) box_surf = pygame.Surface((width, height), pygame.SRCALPHA) text_rect = text_surf.get_rect() box_rect = box_surf.get_rect() for i in xrange(len(lines)): rendered_text = font._font.render(lines[i], anti_alias, color) rect = rendered_text.get_rect() rect.top = i * font._font.get_linesize() if halign == sge.ALIGN_LEFT: rect.left = text_rect.left elif halign == sge.ALIGN_RIGHT: rect.right = text_rect.right elif halign == sge.ALIGN_CENTER: rect.centerx = text_rect.centerx text_surf.blit(rendered_text, rect) if valign == sge.ALIGN_TOP: text_rect.top = box_rect.top elif valign == sge.ALIGN_BOTTOM: text_rect.bottom = box_rect.bottom elif valign == sge.ALIGN_MIDDLE: text_rect.centery = box_rect.centery box_surf.blit(text_surf, text_rect) if halign == sge.ALIGN_LEFT: box_rect.left = x elif halign == sge.ALIGN_RIGHT: box_rect.right = x elif halign == sge.ALIGN_CENTER: box_rect.centerx = x else: box_rect.left = x if valign == sge.ALIGN_TOP: box_rect.top = y elif valign == sge.ALIGN_BOTTOM: box_rect.bottom = y elif valign == sge.ALIGN_MIDDLE: box_rect.centery = y else: box_rect.top = y for i in xrange(len(self._baseimages)): if frame is None or frame % len(self._baseimages) == i: self._baseimages[i].blit(box_surf, box_rect) self._refresh()
def _get_background(self): # Return the static background this frame. background = pygame.Surface( (round(sge.game.width * sge.game._xscale), round(sge.game.height * sge.game._yscale))) background.fill(sge._get_pygame_color(self.color)) for view in sge.game.current_room.views: view_x = int(round(view.x * sge.game._xscale)) view_y = int(round(view.y * sge.game._yscale)) view_xport = max( 0, min(int(round(view.xport * sge.game._xscale)), background.get_width() - 1)) view_yport = max( 0, min(int(round(view.yport * sge.game._yscale)), background.get_height() - 1)) view_w = min(view.width * sge.game._xscale, background.get_width() - view_xport) view_h = min(view.height * sge.game._yscale, background.get_height() - view_yport) surf = background.subsurface(view_xport, view_yport, view_w, view_h) for layer in self.layers: image = layer._get_image() x = int( round((sge.game.current_room.background_x + layer.x - (view.x * layer.xscroll_rate)) * sge.game._xscale)) y = int( round((sge.game.current_room.background_y + layer.y - (view.y * layer.yscroll_rate)) * sge.game._yscale)) image_w = max(1, image.get_width()) image_h = max(1, image.get_height()) # These equations bring the position to the largest # values possible while still being less than the # location we're getting the surface at. This is to # minimize the number of repeat blittings. if layer.xrepeat: x = (x % image_w) - image_w if layer.yrepeat: y = (y % image_h) - image_h # Apply the origin so the positions are as expected. x -= int(round(layer.sprite.origin_x * sge.game._xscale)) y -= int(round(layer.sprite.origin_y * sge.game._yscale)) if layer.xrepeat and layer.yrepeat: xstart = x while y < surf.get_height(): x = xstart while x < surf.get_width(): surf.blit(image, (x, y)) x += image_w y += image_h elif (layer.xrepeat and y < view_y + view_h and y + image_h > view_y): while x < surf.get_width(): surf.blit(image, (x, y)) x += image_w elif (layer.yrepeat and x < view_x + view_w and x + image_w > view_x): while y < surf.get_height(): surf.blit(image, (x, y)) y += image_h elif (x < surf.get_width() and x + image_w > 0 and y < surf.get_height() and y + image_h > 0): surf.blit(image, (x, y)) return background