class Button(object): """docstring for Button""" def __init__(self, text, x, y, width, height, batch, color=(50, 50, 50), scale=unity, **kwargs): super(Button, self).__init__() self.pos = vec2(x, y) * scale self.width = width * scale.x self.height = height * scale.y self.bsize = 2 * scale.x self.color = color self.hcolor = hcolor self.text = Label(text, x=(self.pos.x + self.width / 2), y=(self.pos.y + self.height / 2), anchor_x='center', anchor_y='center', batch=batch, **kwargs) self.bound = Rect(self.pos.x - self.bsize, self.pos.y - self.bsize, self.width+2*self.bsize, self.height+2*self.bsize, color=toplinecolor, batch=batch) self.rect = Rect(self.pos.x, self.pos.y, self.width, self.height, color=self.color, batch=batch) def highlight(self): self.rect.update_color(self.hcolor) def restore(self): if not self.rect.color == self.color: self.rect.update_color(self.color) def over_button(self, x, y): return (0 < x - self.pos.x < self.width and 0 < y - self.pos.y < self.height) def delete(self): self.text.delete() self.rect.delete()
class Scroll(object): def __init__(self, text, pos, batch): self.text = text x, y = self.pos = pos group = OrderedGroup(1) self.label = Label(text, font_name=FONT_NAME, font_size=28, color=COLOUR, x=x + 20, y=y + 15, group=group, batch=batch) w = self.label.content_width + 40 self.bg = ScrollBG(x, x + w, y, batch=batch, group=OrderedGroup(0)) self.left = Sprite(scroll_left, x=x, y=y, group=group, batch=batch) self.right = Sprite(scroll_right, x=x + w, y=y, group=group, batch=batch) def delete(self): self.label.delete() self.left.delete() self.right.delete() self.bg.delete()
def calculate(self): if self.name is None: return from pyglet.text import Label label = Label(self.text, self.name, self.size, self.bold, self.italic, width = self.width) self.calculatedWidth = label.content_width self.calculatedHeight = label.content_height label.delete()
def calculate(self): if self.name is None: return from pyglet.text import Label label = Label(self.text, self.name, self.size, self.bold, self.italic, width = self.width) self.calculatedWidth = label.content_width self.calculatedHeight = label.content_height label.delete()
class FloatingCombatText: def __init__( self, ui, text, x, y, duration=1., scale=1., second_scale=0.5, growth=0.2, velocity=75, color="darkred", batch=None ): self.start_scale = scale self.second_scale = second_scale self.growth = growth self.x, self.y = x, y self.ui = ui wx, wy = self.ui.window.get_windowpos(x, y) self.color = lookup_color(color) self.label = Label( text=str(text), font_name=None, font_size=12 * scale, x=wx, y=wy, anchor_x="center", anchor_y="center", color=self.color, batch=batch, ) self.velocity = velocity self.timer = duration self.duration = duration self.done = False def on_end(self): self.label.delete() self.done = True def update(self, dt): if self.timer <= 0: self.on_end() else: self.timer -= dt perc = self.timer / self.duration scale = ( self.second_scale + ( (self.start_scale - self.second_scale) * perc ) ) self.y += self.velocity * dt self.label.font_size = 9 * scale self.label.x, self.label.y = self.ui.window.get_windowpos( self.x, self.y, precise=True ) opacity = int(255 * perc) if opacity < 0: opacity = 0 self.color = self.color[0], self.color[1], self.color[2], opacity self.label.color = self.color
class HudTitle(GameItem): render_layer = 3 def __init__(self): GameItem.__init__(self) self.titleLabel = None self.pressAnyKeyLabel = None def add_to_batch(self, batch, groups): self.titleLabel = Label( 'Sinister Ducks', font_size=36, x=self.game.width / 2, y=self.game.height / 2 + 30, anchor_x='center', anchor_y='center', batch=batch, group=groups[self.render_layer] ) self.pressAnyKeyLabel = Label( 'Press any key', font_size=18, x=self.game.width / 2, y=self.game.height / 2 - 20, anchor_x='center', anchor_y='center', batch=batch, group=groups[self.render_layer] ) self.blink(None) def remove_from_batch(self, batch): self.titleLabel.delete() self.titleLabel = None self.pressAnyKeyLabel.delete() self.pressAnyKeyLabel = None clock.unschedule(self.blink) def blink(self, _): blink = self.pressAnyKeyLabel.color == colors[0] self.pressAnyKeyLabel.color = colors[blink] clock.schedule_once(self.blink, 0.4 + 0.2 * blink) def on_key_press(self, _, __): clock.schedule_once(lambda _: self.game.start(), 1) self.remove_from_game = True
def take_damage(self, source, dmg): dmg_text = Label(f'{dmg}', x=randint((self.x - 5) // 1, (self.x + self.width + 5) // 1), y=self.y + self.height + 15, font_name='courier new', color=self.damage_text_color, bold=True, batch=self.chunk.draw_batch, group=self.chunk.foreground) clock.schedule_once(lambda df: dmg_text.delete(), 0.5) if (source is not None) and (source is not self): self.in_combat = True if source not in self.in_combat_with: self.in_combat_with.append(source) self.stats.hp -= dmg if self.stats.hp < 1: self.dead = True print( f'{self.name} ({self.stats.hp}/{self.stats.base_hp}) took {dmg} damage from {source.name}!' )
class GameUI(GameObject): """In game UI that shows score etc.""" def __init__(self, *, player: Player, space: pymunk.Space, ui_batch=None, background_batch=None): super().__init__() self.player = player self.space = space self.background_batch = background_batch self.danger_sprite = Sprite(img=resources.danger_image, batch=background_batch, x=128, y=128) self.danger_sprite.visible = False # Internal score modified by the property below self._score = 0 # Show the score self.score_label = Label('', font_name='m5x7', font_size=48, x=WIDTH - 10, y=HEIGHT, anchor_x='right', anchor_y='top', batch=ui_batch) # "call" the property setter below self.score = self._score def tick(self, dt: float): # Don't show danger sprite by default self.danger_sprite.visible = False # Okay so to find out where to possibly show the danger sprite # We need to do a ray cast from the center of the map to the player # And when we hit a wall, that is where it would be shown if it is close enough to the player # The reason we need this, is that the logic for snapping from the players position to a wall position # without raycasting in the case of corners (where two walls meet) is quite complicated so this is simply easier # get some preliminary start and end points start = Vec2d(WIDTH, HEIGHT) / 2 end = (self.player.pos - start) # We can't divide by 0, so make sure the player has moved away from the center if end.get_length_sqrd() > 0: # Then set the length to be the diagonal of the screen, so that the ray will always hit a wall somewhere end.length = math.sqrt(WIDTH**2 + HEIGHT**2) # Remove the start as we don't want vector relative to the center of the screen but rather proper coords end += start # Raycast, finding only wall sensors results = self.space.segment_query( start, end, 1, pymunk.ShapeFilter(mask=CollisionType.WallSensor)) # If we hit something if results: # Find our distance to it wall_result = results[0] distance = (self.player.pos - wall_result.point).length # And if our distance is less than half of danger_sprite's width/height if distance < self.danger_sprite.width / 2: # Show the sprite with increasing opacity as player nears wall self.danger_sprite.visible = True self.danger_sprite.opacity = min( valmap(distance, self.danger_sprite.width / 2, 0, 0, 255), 255) self.danger_sprite.x = wall_result.point.x self.danger_sprite.y = wall_result.point.y @property def score(self): return self._score @score.setter def score(self, value): self._score = value # Update the label text with the new score self.score_label.text = f'Score: {self._score}' def delete(self): self.score_label.delete() self.danger_sprite.delete() super().delete()
class InfoRow(object): """Row of Labels collectively providing player information. Provides information on: Lives, as images of player ship, one image per life remaining. Ammunition stock levels, as series of StockLabels associated with each of player's weapons. Radiation level, as RadiationMonitor.gauge associated with player Score, as created score label. Information positioned right-to-left if player is blue, or from left-to-right if red. METHODS --remove_a_life()-- Remove the life furthest from the screen edge. --update_score_label()-- Update score label --delete()-- Delete all objects that comprise InfoRow """ _text_colors = {'blue': BLUE, 'red': RED} _radiation_symbol = load_image('radiation_20.png', anchor='origin') def __init__(self, window: pyglet.window.Window, batch: pyglet.graphics.Batch, control_sys, num_lives: int, level_label: Label): """ ++window++ Window to which InfoRow to be displayed. ++batch++ Batch to which InfoRow objects to be added. ++control_sys++ .game_objects.ControlSystem of player for whom providing information. ++num_lives++ Number of lives player starts with. ++level_label++ Label that expresses current level. """ self._win = window self._info_row_base = self._win.height - 30 self._batch = batch self._control_sys = control_sys self._color = self._control_sys.color self._text_color = self._text_colors[self._color] self._num_lives = num_lives self._lives = [] self._level_label = level_label # Current position of _x, updated --_advance_x()-- as set objects self._x = self._win.width if self._color == 'blue' else 0 self._set_lives() self._set_stocks_labels() self._set_radiation_gauge() self._create_score_label() def _advance_x(self, pixels: int): """Move _x by +pixels+ pixels in the direction that labels are being sequentially placed. """ pixels *= -1 if self._color == 'blue' else 1 self._x += pixels def _get_object_x(self, obj: Union[Sprite, StockLabel]): """Return 'x' coordinate to place object at required separation on from last object placed ASSUMING +obj+ is anchored to bottom left and --_x-- positioned at the required spacing on from the last object placed. """ if self._color == 'blue': width = obj.content_width if isinstance(obj, StockLabel) \ else obj.width return self._x - width else: return self._x def _set_object(self, obj: Union[Sprite, StockLabel], x: Optional[int] = None, y: Optional[int] = None, batch: Optional[pyglet.graphics.Batch] = None, sep: int = 0): """Position and batch +obj+. Position and batch according to passed parameters, or according to default behaviour otherwise. NB Default behaviour ASSUMES +obj+ anchored to bottom left corner. """ if sep is not 0: self._advance_x(sep) obj.batch = self._batch if batch is None else batch obj.y = self._info_row_base if y is None else y obj.x = self._get_object_x(obj) if x is None else x width = obj.content_width if isinstance(obj, StockLabel)\ else obj.width self._advance_x(width) # Leave _x at end of info row def _set_lives(self): for i in range(self._num_lives): img = copy(self._control_sys.ShipCls[self._color].img) img.anchor_x = 0 img.anchor_y = 0 life = Sprite(img) life.scale = 0.36 self._lives.append(life) self._set_object(life, sep=3) def remove_a_life(self): """Remove the life image furthest from the screen edge.""" self._lives.pop() def _set_stocks_labels(self): for weapon in self._control_sys.weapons: label = weapon.stock_label label.set(style_attrs={'color': self._text_color, 'bold': True}) self._set_object(label, sep=10) label.positioned() def _set_radiation_gauge(self): self._set_object(self._control_sys.radiation_monitor.gauge, sep=15) self._rad_symbol = Sprite(self._radiation_symbol) self._set_object(self._rad_symbol, sep=5) def _score_label_x_coordinate(self) -> int: """Returns x coordinate for score label to position to side of level label. """ direction = 1 if self._color == 'blue' else -1 dist = (self._level_label.content_width // 2) + 34 x = self._level_label.x + (dist * direction) return x def _create_score_label(self): self._score_label = Label('0', x=self._score_label_x_coordinate(), y=self._win.height, font_size=30, bold=True, batch=self._batch, anchor_x='center', anchor_y='top') self._score_label.set_style('color', self._text_color) def update_score_label(self, score: int): """Update score label to +score+.""" self._score_label.text = str(score) def delete(self): """Delete all objects that comprise InfoRow.""" for life in self._lives: life.delete() for weapon in self._control_sys.weapons: weapon.stock_label.delete() self._score_label.delete() self._control_sys.radiation_monitor.gauge.delete() self._rad_symbol.delete()
class InteractiveLabelV2(UIObject, ABC): font_name: str base_color: (int, int, int) placeholder_color: (int, int, int) def __init__(self, logger, parent_viewport): super().__init__(logger, parent_viewport) self.arguments = [] self.text_label = None self.placeholder_label = None self.bold = False self.anchor_x = 'center' self.anchor_y = 'center' self.align = 'left' self.multiline = False self.batch = BATCHES['ui_batch'] self.group = GROUPS['button_text'] self.text_length_limit = 25 self.on_key_press_handlers = [self.on_key_press] self.on_text_handlers = [self.on_text] @final def __len__(self): return len(self.text_label.text) if self.text_label else 0 @abstractmethod def get_x(self): pass @abstractmethod def get_y(self): pass @abstractmethod def get_font_size(self): pass @abstractmethod def get_formatted_text(self): pass @final @is_not_active def on_activate(self): super().on_activate() if not self.placeholder_label: self.placeholder_label = PygletLabel( self.get_formatted_text(), font_name=self.font_name, bold=self.bold, font_size=self.get_font_size(), color=(*self.placeholder_color, self.opacity), x=self.get_x(), y=self.get_y(), anchor_x=self.anchor_x, anchor_y=self.anchor_y, align=self.align, multiline=self.multiline, batch=self.batch, group=self.group) @final def on_update_opacity(self, new_opacity): super().on_update_opacity(new_opacity) if self.text_label: if self.opacity > 0: self.text_label.color = (*self.base_color, self.opacity) else: self.text_label.delete() self.text_label = None if self.placeholder_label: if self.opacity > 0: self.placeholder_label.color = (*self.placeholder_color, self.opacity) else: self.placeholder_label.delete() self.placeholder_label = None @final @window_size_has_changed def on_window_resize(self, width, height): super().on_window_resize(width, height) if self.text_label: self.text_label.begin_update() self.text_label.x = self.get_x() self.text_label.y = self.get_y() self.text_label.font_size = self.get_font_size() self.text_label.end_update() if self.placeholder_label: self.placeholder_label.begin_update() self.placeholder_label.x = self.get_x() self.placeholder_label.y = self.get_y() self.placeholder_label.font_size = self.get_font_size() self.placeholder_label.end_update() @final def on_text(self, text): if not self.text_label: self.placeholder_label.delete() self.placeholder_label = None self.text_label = PygletLabel(text[:self.text_length_limit], font_name=self.font_name, bold=self.bold, font_size=self.get_font_size(), color=(*self.base_color, self.opacity), x=self.get_x(), y=self.get_y(), anchor_x=self.anchor_x, anchor_y=self.anchor_y, align=self.align, multiline=self.multiline, batch=self.batch, group=self.group) else: self.text_label.text = (self.text_label.text + text)[:self.text_length_limit] @final def on_key_press(self, symbol, modifiers): if symbol == BACKSPACE and self.text_label: if len(self.text_label.text) > 0: self.text_label.text = self.text_label.text[:-1] else: self.text_label.delete() self.text_label = None self.placeholder_label = PygletLabel( self.get_formatted_text(), font_name=self.font_name, bold=self.bold, font_size=self.get_font_size(), color=(*self.placeholder_color, self.opacity), x=self.get_x(), y=self.get_y(), anchor_x=self.anchor_x, anchor_y=self.anchor_y, align=self.align, multiline=self.multiline, batch=self.batch, group=self.group) elif modifiers & MOD_CTRL and symbol == V: OpenClipboard() try: self.on_text(GetClipboardData()) except TypeError: pass CloseClipboard()
class LabelV2(UIObject, ABC): font_name: str base_color: (int, int, int) def __init__(self, logger, parent_viewport): super().__init__(logger, parent_viewport) self.arguments = [] self.resource_list_keys = [] self.text_label = None self.bold = False self.anchor_x = 'center' self.anchor_y = 'center' self.align = 'left' self.multiline = False self.batch = BATCHES['ui_batch'] self.group = GROUPS['button_text'] self.undergoing_text_update = False @abstractmethod def get_x(self): pass @abstractmethod def get_y(self): pass @abstractmethod def get_font_size(self): pass def get_width(self): return None @abstractmethod def get_formatted_text(self): pass @final @is_not_active def on_activate(self): super().on_activate() if not self.text_label: self.text_label = PygletLabel(self.get_formatted_text(), font_name=self.font_name, bold=self.bold, font_size=self.get_font_size(), color=(*self.base_color, self.opacity), x=self.get_x(), y=self.get_y(), width=self.get_width(), anchor_x=self.anchor_x, anchor_y=self.anchor_y, align=self.align, multiline=self.multiline, batch=self.batch, group=self.group) @final def on_update_opacity(self, new_opacity): super().on_update_opacity(new_opacity) if self.text_label: if self.opacity > 0: self.text_label.color = (*self.base_color, self.opacity) else: self.text_label.delete() self.text_label = None @final @window_size_has_changed def on_window_resize(self, width, height): super().on_window_resize(width, height) if self.text_label: self.text_label.begin_update() self.text_label.x = self.get_x() self.text_label.y = self.get_y() self.text_label.font_size = self.get_font_size() self.text_label.width = self.get_width() self.text_label.end_update() @final @is_active def on_position_update(self): self.text_label.begin_update() self.text_label.x = self.get_x() self.text_label.y = self.get_y() self.text_label.end_update() @final def begin_update(self): self.undergoing_text_update = True @final def end_update(self): self.undergoing_text_update = False if self.text_label: self.text_label.text = self.get_formatted_text()
class HUD(object): def __init__(self, width, height): self.message_labels = [] self.batch = pyglet.graphics.Batch() self.width = width self.height = height self.money = Label(text=u'0€', x=self.width - 10, y=self.height - 30, font_name=FONT_NAME, font_size=20, anchor_x='right', anchor_y='baseline', color=GOLD + (255, ), batch=self.batch) self.countdown = None def set_countdown(self, seconds): text = '%d:%02d' % (seconds // 60, seconds % 60) if self.countdown: self.countdown.text = text else: self.countdown = Label(text=text, x=self.width // 2, y=self.height - 30, font_name=FONT_NAME, font_size=20, anchor_x='center', anchor_y='baseline', color=RED + (255, ), batch=self.batch) def clear_countdown(self): if self.countdown: self.countdown.delete() self.countdown = None def set_money(self, money): self.money.text = u'%d€' % money def append_message(self, message, colour=DEFAULT_COLOUR): pyglet.clock.schedule_once(self.pop_messages, MESSAGE_TIME, 1) self._add_message(message, colour=colour) self._layout_messages() def append_messages(self, messages, colour=DEFAULT_COLOUR): for m in messages: self._add_message(m, colour=colour) pyglet.clock.schedule_once(self.pop_messages, MESSAGE_TIME, len(messages)) self._layout_messages() def pop_messages(self, dt, count): """Pop count messages.""" ms = self.message_labels[:count] del self.message_labels[:count] for m in ms: m.delete() def _add_message(self, message, colour=DEFAULT_COLOUR): self.message_labels.append( Label(text=message, x=10, y=0, font_name=FONT_NAME, font_size=10, anchor_x='left', anchor_y='baseline', color=colour + (255, ), batch=self.batch)) def _layout_messages(self): n = len(self.message_labels) for i, l in enumerate(self.message_labels): l.y = (n - i) * 20 + 40 def clear_messages(self): for m in self.message_labels: m.delete() del self.message_labels[:] pyglet.clock.unschedule(self.pop_messages) def draw(self): gl.glLoadIdentity() self.batch.draw()
class Hud(object): """docstring for Hud""" def __init__(self, batch, window): super(Hud, self).__init__() self.text_ = 'This is the warmup phase' self.hp_t = '-1' self.armor_t = '-1' self.text_active = 5 self.killmsg_active = False self.chat_active = False self.batch = batch self.scale = vec2(window.width / 1280., window.height / 720.) self.hp = Label(self.hp_t, font_name=font, font_size=36, bold=True, x=80, y=10, anchor_x='center', anchor_y='bottom', batch=self.batch) self.armor = Label(self.armor_t, font_name=font, font_size=36, x=240, y=10, anchor_x='center', anchor_y='bottom', bold=True, batch=self.batch) self.text = Label(self.text_, font_name=font, font_size=36, x=640, y=360, anchor_x='center', anchor_y='center', batch=self.batch) self.weapon = Label('melee', font_name=font, font_size=32, x=1160, y=80, anchor_x='center', anchor_y='bottom', color=(0, 255, 255, 255), batch=self.batch) self.ammo = Label('1', font_name=font, font_size=36, x=1160, y=10, anchor_x='center', anchor_y='bottom', bold=True, batch=self.batch) self.time = Label('0:00', font_name=font, font_size=36, x=640, y=680, anchor_x='center', anchor_y='center', bold=True, batch=self.batch) self.chatdoc = FormattedDocument('\n' * 11) #self.chatlog = document .FormattedDocument('\n') self.chat = ScrollableTextLayout(self.chatdoc, width=500, height=208, multiline=True, batch=self.batch) self.chat.x = 130 self.chat.y = 130 self.chat.content_valign = 'bottom' self.killdoc = FormattedDocument('\n') self.killmsg = ScrollableTextLayout(self.killdoc, width=300, height=104, multiline=True, batch=self.batch) self.killmsg.x = 20 self.killmsg.y = 600 self.scoredoc = FormattedDocument('0 : 0') self.score = ScrollableTextLayout(self.scoredoc, width=150, height=104, multiline=True, batch=self.batch) self.score.x = 1270 self.score.y = 650 self.score.anchor_x = 'right' self.score.anchor_y = 'center' self.normal_hpcol = (255, 255, 255, 255) self.low_hpcol = (255, 128, 0, 255) self.high_hpcol = (0, 204, 255, 255) self.bname = '_' self.aname = '_' self.gametime = 70 self.weaponcolors = {proto.melee: (0, 255, 255, 255), proto.explBlaster: (255, 255, 0, 255)} self.killmsg_count = 0 self.scoreboard = None self.weaponbar = WeaponBar(self.batch, self.scale) self.do_scale() def do_scale(self): for item in (self.armor, self.hp, self.text, self.chat, self.killmsg, self.time, self.ammo, self.weapon, self.score): item.x *= self.scale.x item.y *= self.scale.y def init_player(self, players): if len(players) == 0: self.set_score(0, 0) else: self.bname = players.values()[0].name self.set_score(0, 0) self.init_pers_hud() def init_pers_hud(self): if self.hp._vertex_lists: self.weaponbar.batch = self.batch self.weapon.batch = self.batch self.ammo.batch = self.batch self.hp.batch = self.batch self.armor.begin_update() self.armor.batch = self.batch self.armor.end_update() def init_spec(self): self.weaponbar.remove() self.weapon.delete() self.ammo.delete() self.hp.delete() self.armor.delete() def draw(self): self.active_batch.draw() def update(self, dt): if self.text_active: self.text_active -= dt if self.text_active <= 0: self.text_active = False self.text.delete() if self.killmsg_active: self.killmsg_active -= dt if self.killmsg_active <= 0: self.killmsg_count -= 1 start = self.killdoc.get_paragraph_start(1) end = self.killdoc.get_paragraph_end(1) self.killdoc.delete_text(start, end) if self.killmsg_count > 0: self.killmsg_active = 4 else: self.killmsg_active = False self.killmsg.delete() if self.chat_active: self.chat_active -= dt if self.chat_active <= 0: self.chat_active = False self.chat.delete() self.time.text = self.calc_time(self.gametime) def update_prop(self, armor=False, hp=False, text=False, weapon=False, ammo=False, time=False, name=False, msg=False, chat=None): if armor: if armor != self.armor.text: self.armor.text = armor if int(armor) <= 20: self.armor.color = self.low_hpcol elif int(armor) > 100: self.armor.color = self.high_hpcol else: self.armor.color = self.normal_hpcol if hp: if hp != self.hp.text: self.hp.text = hp if int(hp) <= 20: self.hp.color = self.low_hpcol elif int(hp) > 100: self.hp.color = self.high_hpcol else: self.hp.color = self.normal_hpcol if text: if not self.text_active: self.text.begin_update() self.text.text = text self.text_active = 3 self.text.batch = self.batch self.text.end_update() else: self.text.text = text self.text_active = 3 if weapon: if weapon != self.weapon.text: self.weapon.text = weapon wkey = [key for key, val in allstrings.iteritems() if val == weapon][0] self.weapon.color = weaponcolors[wkey] + [255] if ammo: ammo, weapons = ammo if ammo != self.ammo.text: self.ammo.text = ammo self.weaponbar.update(weapons) if isinstance(time, float): self.gametime = time if name: a, name = name if a: self.aname = name else: self.bname = name #self.score.text = '0:0 ' + self.bname if chat: name, color, msg = chat self.chat.begin_update() #self.chat.text = chat self.chatdoc.insert_text(len(self.chatdoc.text), name, dict(color=list(color) + [255], bold=True)) self.chatdoc.insert_text(len(self.chatdoc.text), '\t' + msg + '\n', dict(color=[255] * 4, bold=False)) start = self.chatdoc.get_paragraph_start(0) end = self.chatdoc.get_paragraph_end(0) self.chatdoc.delete_text(start, end) """self.chatlog.insert_text(len(self.chatlog.text), name, dict(color=list(color) + [255], bold=True)) self.chatlog.insert_text(len(self.chatlog.text), '\t' + msg + '\n', dict(color=[255] * 4, bold=False))""" self.chat.batch = self.batch self.chat.view_y = -self.chat.content_height self.chat.end_update() self.chat_active = 4 def set_score(self, a, b, msg=False, scoreboard=False): self.score.begin_update() self.scoredoc.delete_text(0, len(self.scoredoc.text)) self.scoredoc.insert_text(0, ''.join((str(a), ' ', self.aname, '\n', str(b), ' ', self.bname)), dict(color=[255] * 4)) apos = self.scoredoc.get_paragraph_start(1) bpos = self.scoredoc.get_paragraph_start(len(self.scoredoc.text) - 1) self.scoredoc.set_style(apos, apos+len(str(a)), dict(font_size=24, baseline=-6)) self.scoredoc.set_style(bpos, bpos+len(str(b)), dict(font_size=24, baseline=-6)) self.score.end_update() self.score.width = self.score.content_width + 40 if msg: w, killer, killed = msg if w == 11: w = 4 if w == 12: w = 5 wcol = weaponcolors['w' + str(w-1)] self.killmsg.begin_update() self.killdoc.insert_text(len(self.killdoc.text), killer, dict(color=[255] * 4)) self.killdoc.insert_text(len(self.killdoc.text), ' fragged', dict(color=wcol + [255])) self.killdoc.insert_text(len(self.killdoc.text), ' '.join(('', killed, '\n')), dict(color=[255] * 4)) self.killmsg.batch = self.batch if not self.killmsg_active: self.killmsg_active = 4 self.killmsg_count += 1 self.killmsg.end_update() if scoreboard: if not self.scoreboard: self.scoreboard = ScoreBoard((a, self.aname), (b, self.bname), self.batch, self.scale) else: if not self.scoreboard is None: self.scoreboard.delete() self.scoreboard = None def calc_time(self, gametime): mins = '{:01.0f}'.format(gametime // 60) secs = '{:02.0f}'.format(gametime % 60) return ''.join((mins, ':', secs))
class HudMessage(GameItem): render_layer = 3 color = (255, 255, 255, 255) def __init__(self, text, font_size=36, x=None, y=None, anchor_x='center', anchor_y='center', font_name=None, color=None, remove_after=None, ): GameItem.__init__(self) self._text = text self.font_size = font_size if x is None: x = self.game.width / 2 self.x = x if y is None: y = self.game.height / 2 self.y = y self.anchor_x = anchor_x self.anchor_y = anchor_y self.font_name = font_name if color is None: color = HudMessage.color self.color = color self.label = None # used to detect when Label needs updating self.old_source = None # message removes itself from game after this many seconds self.remove_after = remove_after @property def text(self): return self.source @property def source(self): return self._text def add_to_batch(self, batch, groups): self.label = Label( self.text, font_name=self.font_name, font_size=self.font_size, x=self.x, y=self.y, anchor_x=self.anchor_x, anchor_y=self.anchor_y, color=self.color, batch=batch, group=groups[self.render_layer] ) self.old_source = self.source def remove(_): self.remove_from_game = True if self.remove_after: clock.schedule_once(remove, self.remove_after) def remove_from_batch(self, batch): self.label.delete() def update(self, _): if self.source != self.old_source: self.label.text = self.text self.old_source = self.source
class InventorySlot: def __init__(self, handler, index, x, y, name, count=0, framesize=50): self.handler, self.index, = handler, index, self.x, self.y, = x, y, self.frame = self.createFrame(framesize) self.label = Label('{}\n{}'.format(name, count), anchor_x='center', anchor_y='center', align='center', font_name='Impact', font_size=16, color=(255, 255, 255, 255), bold=False, multiline=True, batch=self.handler.batch, width=100, height=100, x=x, y=100) def __del__(self): self.label.delete() self.frame.delete() def createFrame(self, size): return self.handler.batch.add(4, GL_QUADS, None, ('v2i/static', ( self.x - size, self.y - size, self.x + size, self.y - size, self.x + size, self.y + size, self.x - size, self.y + size, )), ('c4B/static', ( 150, 150, 150, 180, ) * 4)) def updateText(self, selected=False, count=False): self.label.begin_update() if count: self.label.text = '{}\n{}'.format( self.handler.inventory[self.index].name, self.handler.inventory[self.index].get()) if selected: self.label.font_size = 18 else: self.label.font_size = 16 self.label.bold = selected self.label.end_update() def select(self): self.updateText(True) self.setFrame(True) def unselect(self): self.updateText(False) self.setFrame(False) def setFrame(self, selected): self.frame.delete() self.frame = self.createFrame(65 if selected else 50)