O TEMA DO FÓRUM ESTÁ EM MANUTENÇÃO. FEEDBACKS AQUI: ACESSAR

Aula 5: Janelas Base

Iniciado por thiago_d_d, 06/12/2012 às 22:35

[box class=catbg]
Aula 5: Janelas Base[/box]
Índice

  • 5.0 - O que são windows?
  • 5.1 - Fazendo nossa primeira window
  • 5.2 - Terminando nossa window
  • 5.3 - Imprimindo coisas mais interssantes nas windows
  • 5.4 - Dever de casa
[box class=titlebg]
5.0 - O que são windows?
[/box]
       Falaremos nessa aula sobre as importantes Windows.Windows são a segunda parte gráfica mais importante do RGSS2. Elas exibem informações, esclarecem coisas, sem elas eu creio que nenhum jogo de RPG Maker VX seria o que é.Ainda está em dúvida do que é uma window?Olhe então uma window bem simples, e tenho certeza de que se lembrará:
       Para criar uma window , declaramos uma classe. que represente essa window.Cada window do jogo tem sua própria declaração de classe.As windows tem essencialmente 2 métodos essenciais, que quase nunca devem faltar quando você for declará-las:
initialize
       Eu havia comentado sobre este método na aula passada. No caso das windows, esse método serve para que a window seja inicializada e exibida pela primeira vez na tela do jogo.Esse método deve seguir algumas convenções, sobre as quais irei falar na parte prática.É importante frizar:as windows são exibidas automaticamente quando criadas(ou seja, quando um objeto da janela for criado).
refresh
       Método que atualiza a parte estritamente gráfica da window sempre que for necessário, imprimindo textos, imagens, ou qualquer coisa que a window possua.
[box class=titlebg]
5.1 - Fazendo nossa primeira window
[/box]
       Iremos fazer passo a passo nossa primeira window. Ela exibirá apenas um texto simples, de nossa escolha.Para isso, crie um novo projeto para nossa window, sem deletar todos os scripts dessa vez. Depos crie uma página acima de Main, onde iremos digitar o código da window.Aqui vai a screen dela, apesar de que já mostrei várias vezes:
       Começemos então com nossa declaração de classe:
class Window_ShowText < Window_Base
  
end

       Chamamos nossa window de Window_ShowText, pois ela exibe um texto.Mas ops, espera aí, tem algo aí que não vimos ainda, correto?Sim, essa coisa que ainda não vimos é < Window_Base.Essa parte do código representa um conceito muito importante do RGSS2: a herança.Como assim?Irei então dar um exemplo nada a ver.Suponha que temos uma classe chamada "Animal". Nessa classe, temos métodos que todos os animais também terão, por exemplo, o método "viver".Suponha também que queremos criar uma classe "Raposa"(homenagem ao Lumina =D).A classe raposa teria características da classe "Animal", ou melhor a raposa é um animal, ou melhor ainda, a raposa herda a classe animal ou, triplamente melhor ainda,  Raposa < Animal.
       Depois de toda essa analogia você deve ter entendido essa notação, correto?Quando colocamos < Window_Base, queremos dizer que nossa window é uma Window_Base. A classe Window_Base contém métodos comuns a todas as windows, assim como a classe Animal tem o método "viver" comum a todos os animais. Dizer que uma classe herda alguma coisa é o mesmo que dizer que uma classe tem uma superclasse(no caso do exemplo, a superclasse é Animal).Todas as window do jogo DEVEM ter essa notação, caso contrário não irão funcionar corretamente.
       Esquecer de dizer que uma window é uma Window_Base é um erro que fará com que a window não funcione corretamente.
       Depois de declarar nossa window, fazemos então o nosso método initialize:
class Window_ShowText < Window_Base
  def initialize
    super(0, 0, 200, 64)
  end
end

       Temos como primeira linha super(0, 0, 200, 64).Eu havia dito que nossa window herda Window_Base e, quando isso acontece, podemos chamar métodos da superclasse(por isso o comando se chama super).Por exemplo, no método initialize da nossa window chamamos o método initialize da Window_Base com o super.Entre parênteses temos os parâmetros para inicializar a window.São eles: posição x(no caso zero), posição y(no caso zero), largura(no caso 200) e altura(no caso 64).Então nossa window ficará na posição 0, 0 da tela e terá largura 200 e 64.Todos os valores estão medidos em pixels.
       Com isso, nossa window já foi configurada.Para testar ela, devemos criar um objeto dela.Para isso, crie um evento e adicione um comando de eventos com isso:
window = Window_ShowText.new

       Depois disso, teste o evento com o comando de script que você colocou.Irá aparecer isso:
       Nossa window está basicamente pronta. Só falta uma coisa: fazer com que ela exiba o texto.Para isso, devemos declarar o método refresh, que atualiza e mostra as coisas que estão dentro da window.
[box class=titlebg]
5.2 - Terminando nossa window
[/box]
       No RGSS2, temos uma simplicidade em relação às windows. No RGSS comum, nós devemos criar o conteúdo da window, antes de exibi-la:
class Window_ShowText < Window_Base
  def initialize
    super(0, 0, 200, 64)
    self.contents = Bitmap.new(width - 32, height - 32)
  end
end

       Não é necessário criar o conteúdo no RGSS2, ele já é feito automaticamente , no super. Quando o super é chamado, o método create_contents, presente no código da Window_Base, já faz isso. Veja só lá na Window_Base:
def create_contents
    self.contents.dispose
    self.contents = Bitmap.new(width - 32, height - 32)
  end

       Já que não é necessário criar o conteúdo(falei tudo isso por efeitos de curiosidade), temos de fazer o método refresh da nossa window.Veja só:
class Window_ShowText < Window_Base
  def initialize
    super(0, 0, 200, 64)
  end
  def refresh
    self.contents.clear
    self.contents.draw_text(0, 0, 100, 32, "Texto")
  end
end

       Nosso método refresh primeiro limpa os gráficos do conteúdo.Isso é necessário pois, se o refresh fosse chamado muitas vezes, o texto seria impresso em cima dele mesmo várias vezes, quando o correto é que o texto desapareça e depois seja impresso de novo.Depois, chamamos o método draw_text do nosso conteúdo.O método draw_text imprime o texto no conteúdo.Como parâmetros necessários para o método draw_text, passamos a coordenada x  e y do conteúdo(no caso zero e zero) em que o texto será impresso.Passamos também a largura máxima que o texto pode ter e passamos também sua altura(no caso,  100 e 32).E , por último , passamos o texto que será impresso.No caso, o texto impresso será "Texto".
       Como declarar o refresh não o chama, devemos chamar o refresh no método initialize, para que o texto seja chamado imediatamente quando a window for criada:
class Window_ShowText < Window_Base
  def initialize
    super(0, 0, 200, 64)
    refresh
  end
  def refresh
    self.contents.clear
    self.contents.draw_text(0, 0, 100, 32, "Texto")
  end
end

       Depois de tudo isso, nossa window ficará assim:
       Observe que a window desaparece com o tempo.Isso acontece por um motivo sobre o qual irei falar provavelmente na aula que vem.Irei ensinar também a fazer com que ela não desapareça, e fique como uma HUD.
       Para imprimir o texto uma linha abaixo, apenas mude a coordenada y do texto.
       Por motivos estéticos, todo e qualquer texto deve ter altura de 24 ou 32. É sempre melhor, em vez de colocar o valor da altura como 24 ou 32, colocar WLH, que guarda o valor padrão:
self.contents.draw_text(0, 0, 100, WLH, "Texto")
[box class=titlebg]
5.2 - Imprimindo coisas mais interessantes na window
[/box]
       Podemos mostrar muito mais coisas nas windows, como o nome do primeiro personagem do grupo, dentre outras coisas.A classe Window_Base contém muitos métodos interessantes, como podemos ver:(OBS:eu tirei esse código dos scripts que já existem no RGSS2.O Window_Base fica logo bem acima do Main)
#==============================================================================
# Window_Base
#------------------------------------------------------------------------------
# Esta é a classe superior à todas as classes de janelas do jogo.
#==============================================================================

class Window_Base < Window
  #--------------------------------------------------------------------------
  # Contantes
  #--------------------------------------------------------------------------
  WLH = 24                  # Altura da linha da janela (Window Line Height)
  #--------------------------------------------------------------------------
  # Inicialização do objeto
  #     x      : coordenada X da janela
  #     y      : coordenada Y da janela
  #     width  : largura da janela
  #     height : altura da janela
  #--------------------------------------------------------------------------
  def initialize(x, y, width, height)
    super()
    self.windowskin = Cache.system("Window")
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.z = 100
    self.back_opacity = 200
    self.openness = 255
    create_contents
    @opening = false
    @closing = false
  end
  #--------------------------------------------------------------------------
  # Dispose
  #--------------------------------------------------------------------------
  def dispose
    self.contents.dispose
    super
  end
  #--------------------------------------------------------------------------
  # Criação do conteúdo da janela
  #--------------------------------------------------------------------------
  def create_contents
    self.contents.dispose
    self.contents = Bitmap.new(width - 32, height - 32)
  end
  #--------------------------------------------------------------------------
  # Atualização da tela
  #--------------------------------------------------------------------------
  def update
    super
    if @opening
      self.openness += 48
      @opening = false if self.openness == 255
    elsif @closing
      self.openness -= 48
      @closing = false if self.openness == 0
    end
  end
  #--------------------------------------------------------------------------
  # Abrir janela
  #--------------------------------------------------------------------------
  def open
    @opening = true if self.openness < 255
    @closing = false
  end
  #--------------------------------------------------------------------------
  # Fechar janela
  #--------------------------------------------------------------------------
  def close
    @closing = true if self.openness > 0
    @opening = false
  end
  #--------------------------------------------------------------------------
  # Configuração da cor da letra
  #     n : cor da letra (0~31)
  #--------------------------------------------------------------------------
  def text_color(n)
    x = 64 + (n % 8) * 8
    y = 96 + (n / 8) * 8
    return windowskin.get_pixel(x, y)
  end
  #--------------------------------------------------------------------------
  # Configuração da cor padrão da letra
  #--------------------------------------------------------------------------
  def normal_color
    return text_color(0)
  end
  #--------------------------------------------------------------------------
  # Configuração da cor da letra do sistema
  #--------------------------------------------------------------------------
  def system_color
    return text_color(16)
  end
  #--------------------------------------------------------------------------
  # Configuração da cor da letra de estado crítico
  #--------------------------------------------------------------------------
  def crisis_color
    return text_color(17)
  end
  #--------------------------------------------------------------------------
  # Configuração da cor da letra da derrota em batalha
  #--------------------------------------------------------------------------
  def knockout_color
    return text_color(18)
  end
  #--------------------------------------------------------------------------
  # Configuração da cor da letra do contador
  #--------------------------------------------------------------------------
  def gauge_back_color
    return text_color(19)
  end
  #--------------------------------------------------------------------------
  # Configuração do medidor de HP 1
  #--------------------------------------------------------------------------
  def hp_gauge_color1
    return text_color(20)
  end
  #--------------------------------------------------------------------------
  # Configuração do medidor de HP 2
  #--------------------------------------------------------------------------
  def hp_gauge_color2
    return text_color(21)
  end
  #--------------------------------------------------------------------------
  # Configuração do medidor de MP 1
  #--------------------------------------------------------------------------
  def mp_gauge_color1
    return text_color(22)
  end
  #--------------------------------------------------------------------------
  # Configuração do medidor de MP 2
  #--------------------------------------------------------------------------
  def mp_gauge_color2
    return text_color(23)
  end
  #--------------------------------------------------------------------------
  # Configuração da cor de um power up na tela de equipamentos
  #--------------------------------------------------------------------------
  def power_up_color
    return text_color(24)
  end
  #--------------------------------------------------------------------------
  # Configuração de um power down na tela de equipamentos
  #--------------------------------------------------------------------------
  def power_down_color
    return text_color(25)
  end
  #--------------------------------------------------------------------------
  # Exibição do ícone
  #     icon_index : número do ícone
  #     x          : exibe na coordenada X
  #     y          : exibe na coordenada Y
  #     enabled    : um espaço permitido. Fica transparente quando falso
  #--------------------------------------------------------------------------
  def draw_icon(icon_index, x, y, enabled = true)
    bitmap = Cache.system("Iconset")
    rect = Rect.new(icon_index % 16 * 24, icon_index / 16 * 24, 24, 24)
    self.contents.blt(x, y, bitmap, rect, enabled ? 255 : 128)
  end
  #--------------------------------------------------------------------------
  # Exibição dos gráficos de face
  #     face_name  : nome do arquivo de face
  #     face_index : número do arquivo de face
  #     x          : exibe na coordenada X
  #     y          : exibe na coordenada Y
  #     size       : exibe o tamanho
  #--------------------------------------------------------------------------
  def draw_face(face_name, face_index, x, y, size = 96)
    bitmap = Cache.face(face_name)
    rect = Rect.new(0, 0, 0, 0)
    rect.x = face_index % 4 * 96 + (96 - size) / 2
    rect.y = face_index / 4 * 96 + (96 - size) / 2
    rect.width = size
    rect.height = size
    self.contents.blt(x, y, bitmap, rect)
    bitmap.dispose
  end
  #--------------------------------------------------------------------------
  # Exibição dos gráficos de movimento
  #     character_name  : nome do arquivo em movimento
  #     character_index : número do arquivo em movimento
  #     x               : exibe na coordenada X destino
  #     y               : exobe na coordenada Y destino
  #--------------------------------------------------------------------------
  def draw_character(character_name, character_index, x, y)
    return if character_name == nil
    bitmap = Cache.character(character_name)
    sign = character_name[/^[\!\$]./]
    if sign != nil and sign.include?('$')
      cw = bitmap.width / 3
      ch = bitmap.height / 4
    else
      cw = bitmap.width / 12
      ch = bitmap.height / 8
    end
    n = character_index
    src_rect = Rect.new((n%4*3+1)*cw, (n/4*4)*ch, cw, ch)
    self.contents.blt(x - cw / 2, y - ch, bitmap, src_rect)
  end
  #--------------------------------------------------------------------------
  # Configuração da cor do HP
  #     actor : herói
  #--------------------------------------------------------------------------
  def hp_color(actor)
    return knockout_color if actor.hp == 0
    return crisis_color if actor.hp < actor.maxhp / 4
    return normal_color
  end
  #--------------------------------------------------------------------------
  # Configuração da cor do MP
  #     actor : herói
  #--------------------------------------------------------------------------
  def mp_color(actor)
    return crisis_color if actor.mp < actor.maxmp / 4
    return normal_color
  end
  #--------------------------------------------------------------------------
  # Exibição dos gráficos do herói
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #--------------------------------------------------------------------------
  def draw_actor_graphic(actor, x, y)
    draw_character(actor.character_name, actor.character_index, x, y)
  end
  #--------------------------------------------------------------------------
  # Exibição dos gráficos de face do herói
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #     size  : exibe o tamanho
  #--------------------------------------------------------------------------
  def draw_actor_face(actor, x, y, size = 96)
    draw_face(actor.face_name, actor.face_index, x, y, size)
  end
  #--------------------------------------------------------------------------
  # Exibição dos nomes
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #--------------------------------------------------------------------------
  def draw_actor_name(actor, x, y)
    self.contents.font.color = hp_color(actor)
    self.contents.draw_text(x, y, 108, WLH, actor.name)
  end
  #--------------------------------------------------------------------------
  # Exibição da classe
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #--------------------------------------------------------------------------
  def draw_actor_class(actor, x, y)
    self.contents.font.color = normal_color
    self.contents.draw_text(x, y, 108, WLH, actor.class.name)
  end
  #--------------------------------------------------------------------------
  # Exibição do nível
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #--------------------------------------------------------------------------
  def draw_actor_level(actor, x, y)
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 32, WLH, Vocab::level_a)
    self.contents.font.color = normal_color
    self.contents.draw_text(x + 32, y, 24, WLH, actor.level, 2)
  end
  #--------------------------------------------------------------------------
  # Exibição do status
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #     width : largura
  #--------------------------------------------------------------------------
  def draw_actor_state(actor, x, y, width = 96)
    count = 0
    for state in actor.states
      draw_icon(state.icon_index, x + 24 * count, y)
      count += 1
      break if (24 * count > width - 24)
    end
  end
  #--------------------------------------------------------------------------
  # Exibição do HP
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #     width : largura
  #--------------------------------------------------------------------------
  def draw_actor_hp(actor, x, y, width = 120)
    draw_actor_hp_gauge(actor, x, y, width)
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 30, WLH, Vocab::hp_a)
    self.contents.font.color = hp_color(actor)
    xr = x + width
    if width < 120
      self.contents.draw_text(xr - 40, y, 40, WLH, actor.hp, 2)
    else
      self.contents.draw_text(xr - 90, y, 40, WLH, actor.hp, 2)
      self.contents.font.color = normal_color
      self.contents.draw_text(xr - 50, y, 10, WLH, "/", 2)
      self.contents.draw_text(xr - 40, y, 40, WLH, actor.maxhp, 2)
    end
  end
  #--------------------------------------------------------------------------
  # Exibição do HP em estado crítico
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #     width : largura
  #--------------------------------------------------------------------------
  def draw_actor_hp_gauge(actor, x, y, width = 120)
    gw = width * actor.hp / actor.maxhp
    gc1 = hp_gauge_color1
    gc2 = hp_gauge_color2
    self.contents.fill_rect(x, y + WLH - 8, width, 6, gauge_back_color)
    self.contents.gradient_fill_rect(x, y + WLH - 8, gw, 6, gc1, gc2)
  end
  #--------------------------------------------------------------------------
  # Exibição do MP
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #     width : largura
  #--------------------------------------------------------------------------
  def draw_actor_mp(actor, x, y, width = 120)
    draw_actor_mp_gauge(actor, x, y, width)
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 30, WLH, Vocab::mp_a)
    self.contents.font.color = mp_color(actor)
    xr = x + width
    if width < 120
      self.contents.draw_text(xr - 40, y, 40, WLH, actor.mp, 2)
    else
      self.contents.draw_text(xr - 90, y, 40, WLH, actor.mp, 2)
      self.contents.font.color = normal_color
      self.contents.draw_text(xr - 50, y, 10, WLH, "/", 2)
      self.contents.draw_text(xr - 40, y, 40, WLH, actor.maxmp, 2)
    end
  end
  #--------------------------------------------------------------------------
  # Exibição do MP com baixo nível
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #     width : largura
  #--------------------------------------------------------------------------
  def draw_actor_mp_gauge(actor, x, y, width = 120)
    gw = width * actor.mp / [actor.maxmp, 1].max
    gc1 = mp_gauge_color1
    gc2 = mp_gauge_color2
    self.contents.fill_rect(x, y + WLH - 8, width, 6, gauge_back_color)
    self.contents.gradient_fill_rect(x, y + WLH - 8, gw, 6, gc1, gc2)
  end
  #--------------------------------------------------------------------------
  # Exibição dos parâmetros
  #     actor : herói
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #     type  : tipo do valor (0~3)
  #--------------------------------------------------------------------------
  def draw_actor_parameter(actor, x, y, type)
    case type
    when 0
      parameter_name = Vocab::atk
      parameter_value = actor.atk
    when 1
      parameter_name = Vocab::def
      parameter_value = actor.def
    when 2
      parameter_name = Vocab::spi
      parameter_value = actor.spi
    when 3
      parameter_name = Vocab::agi
      parameter_value = actor.agi
    end
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 120, WLH, parameter_name)
    self.contents.font.color = normal_color
    self.contents.draw_text(x + 120, y, 36, WLH, parameter_value, 2)
  end
  #--------------------------------------------------------------------------
  # Exibição do nome do item
  #     item    : itens (habilidades, armas e equipamentos são bem-vindos)
  #     x       : exibe na coordenada X
  #     y       : exibe na coordenada Y
  #     enabled : um espaço permitido. Fica translúcido quando falso
  #--------------------------------------------------------------------------
  def draw_item_name(item, x, y, enabled = true)
    if item != nil
      draw_icon(item.icon_index, x, y, enabled)
      self.contents.font.color = normal_color
      self.contents.font.color.alpha = enabled ? 255 : 128
      self.contents.draw_text(x + 24, y, 172, WLH, item.name)
    end
  end
  #--------------------------------------------------------------------------
  # Exibição da unidade monetária com valor em posse
  #     value : valor em posse
  #     x     : exibe na coordenada X
  #     y     : exibe na coordenada Y
  #     width : largura
  #--------------------------------------------------------------------------
  def draw_currency_value(value, x, y, width)
    cx = contents.text_size(Vocab::gold).width
    self.contents.font.color = normal_color
    self.contents.draw_text(x, y, width-cx-2, WLH, value, 2)
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, width, WLH, Vocab::gold, 2)
  end
end
       Aqui vai alguns métodos interessantes, que você irá usar no dever de casa:
draw_actor_name(actor, x, y)
       Imprime o nome do personagem especificado, nas coordenadas x e y especificadas. A array $game_party.members contém todos os personagens do grupo, que podem ser usados nesse método.Exemplo de uso:
class Window_ShowText < Window_Base
  def initialize
    super(0, 0, 200, 64)
    refresh
  end
  def refresh
    self.contents.clear
    draw_actor_name($game_party.members[0], 0, 0)
  end
end
draw_actor_level(actor, x, y)
       Imprime o nível do personagem especificado, nas coordenadas x e y especificadas. A array $game_party.members contém todos os personagens do grupo, que podem ser usados nesse método.O modo de usar é o mesmo modo de se usar o draw_actor_name.
draw_actor_graphic(actor, x, y)
       Imprime o gráfico de character do personagem especificado, nas coordenadas x e y especificadas. A array $game_party.members contém todos os personagens do grupo, que podem ser usados nesse método.O modo de usar é o mesmo modo de se usar o draw_actor_name.
draw_actor_hp(actor, x, y) e draw_actor_mp(actor, x, y)
       Imprime o hp e o mp do personagem especificado, respectivamente, nas coordenadas x e y especificadas. A array $game_party.members contém todos os personagens do grupo, que podem ser usados nesse método.O modo de usar é o mesmo modo de se usar o draw_actor_name.
[box class=titlebg]
5.3 - Conclusão
[/box]
       Então pessoal, espero que tenham gostado dessa quinta aula.Eu creio que ela é a mais difícil de todas até agora e, por isso, estou a disposição de qualquer dúvida, basta postar aqui no tópico.A seguir tem o dever que é bastante interessante para fazer, caso tenha entendido a aula. Na próxima aula, iremos fazer windows selecionáveis(tipo aquela em que se selciona "Novo Jogo", "Continuar"), e confesso que irá complicar a história bastante.Até.
[box class=titlebg]
5.4 - Dever de casa
[/box]
       Faça uma window que use todos os métodos de que falei na seção "5.2 - Imprimindo coisas mais interessantes nas windows". Use também pelo menos um método interessante da Window_Base que não citei.
:wow: :wow: :wow: