示例#1
0
class BattleUI(object):
  def __init__(self):
    self.font = Font()
    self.user_sprite = self.get_sprite('pokemon_back_tiled.bmp')
    self.enemy_sprite = self.get_sprite('pokemon.bmp')

  @staticmethod
  def get_sprite(filename):
    if filename == 'pokemon_back_tiled.bmp':
      sprite = Sprite(
        filename,
        width=back_size,
        height=back_size,
        cols=7,
        rows=36,
        offset=(6, 6),
        period=(54, 57),
      )
      sprite.set_pokenum = lambda i: sprite.set_index(i - 1)
    elif filename == 'pokemon.bmp':
      sprite = Sprite(
        filename,
        width=front_size,
        height=front_size,
        cols=10,
        rows=26,
        offset=(8, 24),
        period=(64, 64),
      )
      sprite.set_pokenum = lambda i: sprite.set_index(get_front_index(i))
    else:
      assert(False), 'Unexpected image name: %s' % (filename,)
    return sprite

  def draw(self, surface, battle):
    surface.fill(white)
    display = battle.get_display()
    self.draw_pc_pokemon(surface, battle.all_pcs(), display)
    self.draw_npc_pokemon(surface, battle.all_npcs(), display)
    self.draw_menu(surface, display['menu'])

  def draw_pc_pokemon(self, surface, pc_pokemon, display):
    top = screen_size[1] - ui_height - self.user_sprite.height - status_height
    self.draw_pokemon_row(surface, pc_pokemon, top, 'pc', display)

  def draw_npc_pokemon(self, surface, npc_pokemon, display):
    self.draw_pokemon_row(surface, npc_pokemon, top_row_space, 'npc', display)

  def draw_pokemon_row(self, surface, pokemon_list, top, side, display):
    num = len(pokemon_list)
    total = screen_size[0] + name_size
    sprite = self.user_sprite if side == 'pc' else self.enemy_sprite
    for (i, pokemon) in enumerate(pokemon_list):
      left = int((i + 1)*total/(num + 1)) - name_size
      self.draw_pokemon(surface, sprite, pokemon, left, top, (side, i), display)

  def draw_pokemon(self, surface, sprite, pokemon, far_left, top, index, display):
    # Draw the Pokemon's (back or front) sprite.
    left = far_left + (name_size - sprite.width)/2
    sprite.set_position(left, top)
    sprite.set_pokenum(pokemon.num)
    if draw_sprites and index not in display.get('hidden_indices', ()):
      with self.apply_sprite_offsets(sprite, index, display):
        sprite.draw(surface)
      if pokemon.status:
        char = Status.MARKS[pokemon.status]
        self.font.draw(surface, char, left - font_size - 3, top + font_size/2)
    # Draw the Pokemon's name.
    name = pokemon.name
    left = far_left + (name_size - font_size*len(name))/2
    top += (sprite.height + font_size/2)/(1 if draw_sprites else 2)
    self.font.draw(surface, name, left, top)
    # Draw the Pokemon's level.
    offset = (pokemon.level < 10)*font_size/2
    top += 3*font_size/2
    self.font.draw(surface, 'L%d' % (pokemon.level,), far_left + offset, top)
    # Draw the Pokemon's health bar.
    left = far_left + 7*font_size/2 - offset
    top += font_size/2
    health = float(pokemon.cur_hp)/pokemon.max_hp
    self.draw_health_bar(surface, health, left, top)

  @contextmanager
  def apply_sprite_offsets(self, sprite, index, display):
    height_offset = display.get('height_offsets', {}).get(index, 0)
    absolute_offset = int(math.ceil(height_offset*sprite.height))
    sprite.rect.top += absolute_offset
    sprite.source_rect.height -= absolute_offset
    yield
    sprite.rect.top -= absolute_offset
    sprite.source_rect.height += absolute_offset

  def draw_health_bar(self, surface, health, left, top):
    # Draw the left and right borders of the health bar.
    pygame.draw.rect(surface, black, (
      left,
      top - health_border[1]/2,
      health_border[0],
      health_border[1],
    ))
    pygame.draw.rect(surface, black, (
      left + health_border[0] + health_bar[0],
      top - health_border[1]/2,
      health_border[0],
      health_border[1],
    ))
    # Draw a line underneath the bar. This code may be incorrect...
    pygame.draw.line(surface, black, (
      left + health_border[0],
      top + health_border[1]/2 - health_bar[1]/2 + 1,
    ), (
      left + health_border[0] + health_bar[0],
      top + health_border[1]/2 - health_bar[1]/2 + 1,
    ))
    # Draw the actual health bar in the correct color.
    color = green if health > 0.5 else yellow if health > 0.25 else red
    width = int(math.ceil(health*health_bar[0]))
    if width:
      pygame.draw.rect(surface, color, (
        left + health_border[0],
        top - health_bar[1]/2,
        width,
        health_bar[1],
      ))

  def draw_menu(self, surface, menu):
    self.draw_menu_block(surface, menu, 0, screen_size[0])

  def draw_menu_block(self, surface, lines, left, width):
    pygame.draw.rect(surface, black, (
      left,
      screen_size[1] - ui_height,
      width,
      ui_height,
    ), 1)
    top = screen_size[1] - ui_height + font_size
    for line in self.resize_lines(lines, width):
      self.font.draw(surface, line, left + font_size, top)
      top += 3*font_size/2

  def resize_lines(self, lines, width):
    num_chars = width/font_size - 2
    new_lines = ['']
    for line in lines:
      for word in line.split(' '):
        if len(new_lines[-1]) + len(word) > num_chars:
          new_lines.append('')
        new_lines[-1] += word + ' '
      new_lines.append('')
    return [line.rstrip() for line in new_lines]