def order_reversed_spritesheet(self, flipped_sheet): """Reorganize the frames in a flipped sprite sheet so that they are in the same order as the original sheet. Args: flipped_sheet: A PyGame Surface containing a flipped sprite sheet. Returns: A PyGame Surface containing the sprite sheet with each frame flipped and in the correct order. """ ordered_sheet = Surface((self.spritesheet.get_width(), self.spritesheet.get_height()), SRCALPHA) ordered_sheet.convert_alpha() for frame_index in xrange(0, self.get_num_of_frames()): frame_x = self.get_width() * frame_index old_frame_index = self.get_num_of_frames() - 1 - frame_index old_region = self.get_frame_region(old_frame_index) ordered_sheet.blit(flipped_sheet, (frame_x, 0), old_region) return ordered_sheet
def update(self, duration): """ update all the contained linewidgets. Return right away if no text has changed. """ if self.dirty == 0: # no new text has been added return # make the box size = self.rect.size bgcolor = self.bgcolor if bgcolor: # completely opaque bg img = Surface(size) img.fill(self.bgcolor) img = img.convert() else: # more or less transparent img = Surface(size, SRCALPHA) # handles transparency transparency = 50 # 0 = transparent, 255 = opaque img.fill((0, 0, 0, transparency)) # black img = img.convert_alpha() # blit each line for wid in self.linewidgets: wid.update(duration) img.blit(wid.image, wid.rect) self.image = img self.dirty = 0
def __init__(self, evManager, numlines=3, rect=(0, 0, 100, 20), txtcolor=(255, 0, 0), bgcolor=None): Widget.__init__(self, evManager) self._em.reg_cb(ChatlogUpdatedEvent, self.on_remotechat) self._em.reg_cb(MGameAdminEvt, self.on_gameadmin) self._em.reg_cb(MNameChangeFailEvt, self.on_namechangefail) self._em.reg_cb(MMyNameChangedEvent, self.on_namechangesuccess) self._em.reg_cb(MNameChangedEvt, self.on_namechangesuccess) self._em.reg_cb(MdHpsChangeEvt, self.on_updatehps) self.font = Font(None, config_get_fontsize()) self.rect = rect size = rect.size self.txtcolor = txtcolor self.bgcolor = bgcolor if bgcolor: # completely opaque bg img = Surface(size) img.fill(self.bgcolor) img = img.convert() else: # more or less transparent img = Surface(self.rect.size, SRCALPHA) # handles transparency transparency = 50 # 0 = transparent, 255 = opaque img.fill((0, 0, 0, transparency)) # black img = img.convert_alpha() self.image = img self.maxnumlines = numlines self.linewidgets = deque(maxlen=numlines) # deque of TextLabelWidgets
def update(self, duration): """ update all the contained linewidgets TODO: check that it works with transparent bg """ if self.dirty == 0: return # make the box size = self.rect.size bgcol = self.bgcolor if bgcol: # only display a bg img if bgcolor specified img = Surface(size) img.fill(bgcol) img = img.convert() else: # more or less transparent img = Surface(size, SRCALPHA) # handles transparency transparency = 50 # 0 = transparent, 255 = opaque img.fill((0, 0, 0, transparency)) img = img.convert_alpha() # blit each line numelemts = min(len(self.texts), self.maxnumlines) for i in range(numelemts): wid = self.linewidgets[i] wid.set_text(self.texts[-i - 1]) wid.update(duration) img.blit(wid.image, wid.rect) self.image = img
def make_surface(size: Tuple[int, int], alpha: bool=True, used_colors: List[Color]=[], bg_color: Optional[Color]=None): if bg_color is not None: fill_color = bg_color else: used_colors = set(used_colors) for i in range(256): fill_color = (i, i, i) if fill_color not in used_colors: break surface = Surface(size) surface.fill(fill_color) if pygame.display.get_init(): if alpha and bg_color is None: surface.convert_alpha() surface.set_colorkey(surface.get_at((0, 0))) else: surface.convert() return surface
def __init__(self, evManager, rect=None): Widget.__init__(self, evManager) # Widget init sets dirty to true, hence the actual rendering # will be done in InputFieldWidget.update(), called by the view renderer. self._em.reg_cb(NonprintableKeyEvent, self.on_invisiblekeypushed) self._em.reg_cb(UnicodeKeyPushedEvent, self.on_visiblekeypushed) self._em.reg_cb(DownClickEvent, self.on_downclick) self.text = "" self.font = Font(None, config_get_fontsize()) if rect: self.rect = rect else: self.rect = Rect((0, 0), (100, config_get_fontsize() + 4)) # 100px = default width, # 25px = font height, 4px = 1 px for each of border-bottom, # padding bottom, padding top, and border top. # rectangle to be drawn around the box as border border_rect = Rect((0, 0), self.rect.size) # draw and store unfocused empty box emptyboxImg = Surface(self.rect.size) self.unfocused_bgcolor = config_get_unfocusedinput_bgcolor() self.unfocused_txtcolor = config_get_unfocusedinput_txtcolor() emptyboxImg.fill(self.unfocused_bgcolor) pygame.draw.rect(emptyboxImg, self.unfocused_txtcolor, border_rect, 2) self.unfocused_emptyboxImg = emptyboxImg.convert_alpha() self.image = emptyboxImg # draw and store focused empty box emptyboxImg = Surface(self.rect.size) self.focused_bgcolor = config_get_focusedinput_bgcolor() self.focused_txtcolor = config_get_focusedinput_txtcolor() emptyboxImg.fill(self.focused_bgcolor) pygame.draw.rect(emptyboxImg, self.focused_txtcolor, border_rect, 2) self.focused_emptyboxImg = emptyboxImg.convert_alpha() self.textPos = (4, 2) # 4px padding-left and 2px padding-top
def update(self, duration): """ reblit the entries on my rect """ if self.dirty == 0: return # make the transparent box size = self.rect.size img = Surface(size, SRCALPHA) transparency = 50 # 0 = transparent, 255 = opaque img.fill((0, 0, 0, transparency)) img = img.convert_alpha() # TODO: alpha or color key? # blit each entry for entry in self.entries: entry.update(duration) img.blit(entry.image, entry.rect) self.image = img
def add_underline(self): """Draws an underline on the text Surface, on top the text.""" # The underline will be drawn from the bottom of the text Surface # and will extend its entire horizontal length. text_width = self.rect.width text_height = self.rect.height start_point = (0, text_height - 4) end_point = (text_width, text_height - 4) # The underline is drawn onto a new Surface with the same dimensions # as the text Surface, but slightly taller to account for the # underline. The text is drawn on top. new_image = Surface((text_width, text_height + 4), pygame.SRCALPHA, 32) new_image = new_image.convert_alpha() draw.line(new_image, UNDERLINE_COLOUR, start_point, end_point, UNDERLINE_SIZE) new_image.blit(self.image, (0, 0)) self.image = new_image
def render_text(text, fontname, font_size, color, bg_color, resource, size, centre=True): """Render the text so it will fit in the given size, reducing font size as needed. Note that this does not do any text wrapping.""" done = False width, height = size color = convert_color(color) bg_color = convert_color(bg_color) surface = Surface(size, SRCALPHA) if resource.CONVERT_ALPHA: surface = surface.convert_alpha() else: # Don't actually render the text when testing return surface surface.fill(bg_color) while not done and font_size > 0: # We bail at font_size 1 and just clip in that case, since we're # out of good options font = resource.get_font(fontname, font_size) text_surf = font.render(text, True, color) if (text_surf.get_width() > width or text_surf.get_height() > height): font_size -= 1 else: done = True if centre: # Centre the text in the rect x = max(0, (width - text_surf.get_width()) // 2) y = max(0, (height - text_surf.get_height()) // 2) else: x = y = 0 surface.blit(text_surf, (x, y)) return surface
class SettingsScreen(Screen): """ The settings screen class. An instance of this class represents a settings screen. Attributes: _settings: The game settings. _entries: The settings entries. _screen: The screen to draw on. _width: The width of the window. _height: The height of the window. _window: The surrounding window. _bg: The background picture. _font: The font to use. _font_height: The height of the used font. _selected: The index of the selected settings entry. _first_y: The y coordinate of the first entry. _delta_y: The difference in the y axis between the entries. _plus_button: The pre-rendered plus button. _minus_button: The pre-rendered minus button. """ # color of an entry SELECTED_COLOR = (255, 255, 0) # color of the selected entry COLOR = (150, 150, 0) def __init__(self, screen, width, height, window, settings): """ Generates a new instance of this class. Generates a new instance of this class and sets the field information. Args: screen: The screen to draw on. width: The width of the screen. height: The height of the screen. window: The surrounding window. settings: The game settings. """ self._settings = settings self._screen = screen self._width = width self._height = height self._window = window self._bg = PictureManager.MANAGER.get_picture("menuBackground.png") self._bg = pygame.transform.scale(self._bg, (width, height)) self._font = pygame.font.SysFont("arial", 24) self._font_height = self._font.get_linesize() self._selected = 0 sound_entry = SettingsEntry(Settings.SOUND_VOLUME, "Sound", SettingsEntry.SCALE10, self._settings.get_value(Settings.SOUND_VOLUME), button_size=self._font_height) music_entry = SettingsEntry(Settings.MUSIC_VOLUME, "Music", SettingsEntry.SCALE10, self._settings.get_value(Settings.MUSIC_VOLUME), button_size=self._font_height) fx_entry = SettingsEntry(Settings.FX_VOLUME, "Effects", SettingsEntry.SCALE10, self._settings.get_value(Settings.FX_VOLUME), button_size=self._font_height) joystick_entry = SettingsEntry(Settings.JOYSTICK, "Controller", SettingsEntry.BOOL, self._settings.get_value(Settings.JOYSTICK), button_size=self._font_height) back_entry = SettingsEntry(None, "back", SettingsEntry.ACTION, None, action=self.back) self._entries = (sound_entry, music_entry, fx_entry, joystick_entry, back_entry) self._first_y = 0.5 * (self._height - len(self._entries) * (self._font_height + 5)) self._delta_y = self._font_height + 5 self._plus_button = None self._minus_button = None self._unchecked_bool = None self._checked_bool = None self._prepare_buttons() def _prepare_buttons(self): """ Prepares the buttons. This method pre-renders the plus and minus buttons. """ # draw plus button self._plus_button = Surface((self._font_height, self._font_height), pygame.SRCALPHA, 32) self._plus_button.convert_alpha() pygame.draw.rect(self._plus_button, SettingsScreen.COLOR, Rect(0, self._font_height/3, self._font_height, self._font_height/3)) pygame.draw.rect(self._plus_button, SettingsScreen.COLOR, Rect(self._font_height/3, 0, self._font_height/3, self._font_height)) # draw minus button self._minus_button = Surface((self._font_height, self._font_height), pygame.SRCALPHA, 32) self._minus_button.convert_alpha() pygame.draw.rect(self._minus_button, SettingsScreen.COLOR, Rect(0, self._font_height/3, self._font_height, self._font_height/3)) # draw unchecked bool button self._unchecked_bool = Surface((self._font_height, self._font_height), pygame.SRCALPHA, 32) self._unchecked_bool.convert_alpha() pygame.draw.rect(self._unchecked_bool, SettingsScreen.COLOR, Rect(0, 0, self._font_height, self._font_height), 3) # draw checked bool button self._checked_bool = Surface((self._font_height, self._font_height), pygame.SRCALPHA, 32) self._checked_bool.convert_alpha() pygame.draw.rect(self._checked_bool, SettingsScreen.COLOR, Rect(0, 0, self._font_height, self._font_height), 3) pygame.draw.line(self._checked_bool, SettingsScreen.COLOR, (0, 0), (self._font_height, self._font_height), 3) pygame.draw.line(self._checked_bool, SettingsScreen.COLOR, (0, self._font_height), (self._font_height, 0), 3) def draw(self): """ Draws the settings. This method draws the settings on the screen. """ self._screen.blit(self._bg, (0, 0)) y = self._first_y i = 0 for entry in self._entries: if self._selected == i: text = self._font.render(entry.text, True, SettingsScreen.SELECTED_COLOR) else: text = self._font.render(entry.text, True, SettingsScreen.COLOR) self._screen.blit(text, (100, y)) if entry.type == SettingsEntry.SCALE10: value = self._font.render(str(entry.value), True, SettingsScreen.COLOR) self._screen.blit(value, (self._width - 100 - value.get_width(), y)) entry.plus.topleft = (self._width - 95, y) self._screen.blit(self._plus_button, entry.plus.topleft) entry.minus.topleft = (self._width - 105 - value.get_width() - self._font_height, y) self._screen.blit(self._minus_button, entry.minus.topleft) elif entry.type == SettingsEntry.BOOL: entry.plus.topleft = (self._width - 100 - self._font_height, y) if entry.value: self._screen.blit(self._checked_bool, entry.plus.topleft) else: self._screen.blit(self._unchecked_bool, entry.plus.topleft) y += self._delta_y i += 1 def back(self): """ Returns to the main menu. This method saves the settings and return to the main menu. """ for entry in self._entries: if entry.name is not None: self._settings.set_value(entry.name, entry.value) self._window.switch(window.Window.MENU) def key_down(self, key): """ Handles key down events. This method handles key down events. The pressing of the up or down key changes the selected settings entry. The pressing of the left or right key changes the value of the selected entry. The pressing of the return key performs the action of the entry. The pressing of the escape key returns to the main menu. Args: key: The key event information provided by pygame. """ if key == K_DOWN: if self._selected < len(self._entries) - 1: self._selected += 1 elif key == K_UP: if self._selected > 0: self._selected -= 1 elif key == K_RIGHT: self._entries[self._selected].inc() elif key == K_LEFT: self._entries[self._selected].dec() elif key == K_ESCAPE: self.back() elif key == K_RETURN or key == K_SPACE: self._entries[self._selected].act() def mouse_click(self, pos, button): """ Handles mouse click events. This method is handles mouse click events. Args: pos: The position of the mouse. button: The button pressed. """ if button == 1: entry = self._entries[self._selected] if entry.plus.collidepoint(pos): entry.inc() elif entry.minus.collidepoint(pos): entry.dec() else: entry.act() def mouse_move(self, pos): """ Handles mouse move events. This method handles mouse movement events. Args: pos: The position of the mouse. """ if pos[1] < self._first_y: self._selected = 0 else: dy = math.trunc((pos[1] - self._first_y) / self._delta_y) if dy >= len(self._entries): dy = len(self._entries)-1 self._selected = dy
pygame.init() screen = pygame.display.set_mode((300, 300)) bg = Surface((200, 200)) bg.fill((255, 0, 0)) bg = bg.convert() screen.blit(bg, (50, 50)) font = Font(None, 25) txt = 'qwertyuiop' txtimg = font.render(txt, 1, (255, 255, 255)) # antialiasing w/o bg => alpha b = Surface((100, 100), SRCALPHA) b.fill((111, 111, 111, 128)) b.blit(txtimg, (10, 10)) b = b.convert_alpha() screen.blit(b, (25, 25)) # what's below has better perf, but bad output when antialias + transparency c = Surface((100, 100)) colkey = (255, 0, 255) c.set_colorkey(colkey, RLEACCEL) c.fill(colkey) # make the surface bg invisible c2 = Surface((100, 100)) c2.fill((111, 111, 111)) c2.set_alpha(128, RLEACCEL) # semi-transparent gray bg #c.blit(c2, (0, 0)) c2 = c2.convert() txtimg2 = txtimg.convert(c) # sucks if txtimg is antialiased c.blit(txtimg2, (10, 10))