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

Aula 6: Cenas e Janelas Selecionáveis

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

[box class=catbg]
Aula 6: Cenas e Janelas Selecionáveis[/box]
Índice

  • 6.0 - O que são scenes?
  • 6.1 - O que são windows selectables?
  • 6.2 - Nossa primeira scene
  • 6.3 - Fazendo nossa window que exibirá os nomes
  • 6.4 - Fazendo nossa window selectable
  • 6.5 - Finalizando nossa scene
  • 6.6 - Conclusão
  • 6.7 - Deveres de casa
[box class=titlebg]
6.0 - O que são scenes?
[/box]
       Scene são objetos especiais. Eles servem para manipular windows, sprites e muitas outras coisas para que funcionem coordenadamente.No jogo feito pelo RPG Maker, sempre há uma scene ativa, manipulando as coisas do jogo.Por exemplo, temos a Scene_Map, que manipula os gráficos,  interpretador, etc do mapa.Temos o Scene_Title, que manipula a tela de título. A variável $scene guarda a scene que está atualmente rodando.Observe que é uma variável global, e pode ser mudada em qualquer lugar de qualquer script. Nós scripters podemos criar uma scene quando quisermos. É isso que iremos fazer nessa aula.
       Assim como as windows, as scenes também têm métodos importantes. São esses três, basicamente(tem mais):
start
       Ele inicializa tudo que tem de ser inicializado.Se sua window usa janelas, sprites, etc, crie tudo aqui.
update
       O método update encarrega-se de atualizar tudo o que deve ser atualizado na nossa scene.
terminate
       O método terminate se encarrega de terminar com tudo que nossa scene usou. Ocorre quando nossa scene fecha.
[box class=titlebg]
6.1 - O que são windows selectables?
[/box]
       Como o nome diz, são windows selecionáveis.São aquelas em que há a opção de selecionar várias opções(oh não me diga).Um grande exemplo é a window da tela de título, que contém as opções Novo Jogo,  Continuar e Sair. Toda window selectable herda a classe Window_Selectable(assim como uma window normal herda uma Window_Base).A diferença entre uma window selectable e uma window normal é bem sutil, e são poucas as diferenças entre as duas na hora da declaração.
       Você deve estar se perguntando: mas thiago, você disse que toda window tem de ser uma Window_Base! Isso é sim verdade, e porque uma window que é uma Window_Selectable é indiretamente uma Window_Base, porque a Window_Selectable herda a Window_Base. Se um selectable é uma base, algo que é uma selectable também é uma base.Bem simples, eu acho.
[box class=titlebg]
6.2 - Nossa primeira scene
[/box]
       Iremos fazer aqui nossa primeira scene. Nela, haverá uma window selectable e uma window normal. Na window selectable haverá 4 opções: Ator 1, Ator 2, Ator 3 e Ator 4 e, dependendo da escolha na window, exibiremos o nome de cada respectivo personagem do grupo.Confesso que as coisas irão complicar um pouco a partir daqui.No final, nossa scene ficará assim:
       Usando o que eu havia falado antes, nossa scene já fica dessa forma, logo de cara:
class Scene_Exemplo < Scene_Base
  def start
  end
  def terminate
  end
  def update
  end
end
[box class=titlebg]
6.3 - Fazendo nossa window que exibirá os nomes
[/box]

        Nossa window que exibirá o nome de cada actor será uma window normal, uma Window_Base, pois exibirá apenas um nome.Ela só te,  algo de diferente:ela terá de ser atualizada mais de uma vez, e cada vez ela imprimirá um texto diferente, dependendo da opção selecionada na nossa window selectable.Logo de cara, usando os conceitos da aula passada, nossa window fica assim:
class Window_ShowName < Window_Base
  def initialize
    super(192, 0, 192, 160)
    @texto = $game_party.members[0].name
    refresh
  end
  def refresh
    self.contents.clear
    self.contents.draw_text(0, 0, 128, 32, @texto)
  end
end
       Mas temos que fazer com que ela mostre o nome exibido dependendo da escolha de um personagem.Então, iremos criar um novo método, que irá mudar o texto a ser impresso e atualizará a window de novo.Aqui está nossa nova window:
class Window_ShowName < Window_Base
  def initialize
    super(192, 0, 192, 160)
    @texto = $game_party.members[0].name
    refresh
  end
  def refresh
    self.contents.clear
    self.contents.draw_text(0, 0, 128, 32, @texto)
  end
  def mudar_texto(novo_texto)
    @texto = novo_texto
    refresh
  end
end
      Aqui implementamos um método mudar_texto, que muda a variável @texto para o texto recebido e reatualiza nossa window, que mostrará o novo texto atribuído a nossa variável.Podem perceber que fui bem direto nessa parte, pois espero logo de cara que vocês já saibam como manipular uma window comum, pois já lhes ensinei isso.
[box class=titlebg]
6.4 - Fazendo nossa window selectable
[/box]
       O modo de se fazer uma window selectable é bem semelhante ao modo de se fazer uma window normal: nós fazemos o método initialize, que inicializará nossa window, e depois fazemos um método refresh, que atualiza a parte gráfica da nossa window.Usando isso pura e simplesmente, nossa window já fica assim:
class Window_SelectHero < Window_Selectable
  def initialize
    super(0, 0, 192, 160)
    refresh
  end
  def refresh
    self.contents.clear
  end
end
       Observe aí que usamos a notação < Window_Selectable. Colocar < Window_Base é um erro comum, e fazer isso daria erro com certeza, pois não podemos tratar uma window comum como uma window selectable.
       Porém, só fazer isso não funciona para nossa window. Temos de especificar duas coisas:seu número de colunas(no caso 1), mudando a variável @column_max e o número de opções, mudando @item_max.Como temos "Ator 1", "Ator 2", etc, somando tudo dá 4.Então nossa window ficará assim:
class Window_SelectHero < Window_Selectable
  def initialize
    super(0, 0, 192, 160)
    @item_max = 4
    refresh
  end
  def refresh
    self.contents.clear
  end
end
       Observe que não mudamos a variável @column_max.Isso ocorreu porque 1 é o número de colunas padrão, e não há necessidade de especificar.Como @item_max colocamos o número de opções que vamos ter, no caso 4.Após isso, devemos especificar quais das opções estão selecionadas atualmente.Para isso, mudamos a variável self.index.Logo, nossa window já fica assim:
class Window_SelectHero < Window_Selectable
  def initialize
    super(0, 0, 192, 160)
    @item_max = 4
    refresh
    self.index = 0
  end
  def refresh
    self.contents.clear
  end
end
       Observe que colocamos 0 como o a opção atualmente selecionada, isso significa que nossa primeira opção é a selecionada.Se colocassemos 1, a opção atualmente selecionada seria a segunda.Funciona exatamente como um índice de array, como zero sendo a primeira opção, e não 1 como seria esperado.Após especificar tudo isso, falta apenas uma coisa: imprimir os texto das opções.Fazendo isso, nossa window ficará assim:
class Window_SelectHero < Window_Selectable
  def initialize
    super(0, 0, 192, 160)
    @item_max = 4
    refresh
    self.index = 0
  end
  def refresh
    self.contents.clear
    textos = ["Ator 1", "Ator 2", "Ator 3", "Ator 4"]
    for i in [0, 1, 2, 3]
      self.contents.draw_text(0, WLH * i, 128, WLH, textos[i])
    end
  end
end
       Observe aí que usei de forma inteligente o for para imprimir os textos de forma fácil.Agrupar os textos a imprimir em uma variável só ajuda em uma posterior modificação, bastaria apenas que fosse editada a tal array.Imprimir os textos poderia ter sido feito de uma forma mais simples, porém menos inteligente:
class Window_SelectHero < Window_Selectable
  def initialize
    super(0, 0, 192, 160)
    @item_max = 4
    refresh
    self.index = 0
  end
  def refresh
    self.contents.clear
    textos = ["Ator 1", "Ator 2", "Ator 3", "Ator 4"]
    self.contents.draw_text(0, 0, 128, WLH, "Ator 1")
    self.contents.draw_text(0, WLH, 128, WLH, "Ator 2")
    self.contents.draw_text(0, WLH * 2, 128, WLH, "Ator 3")
    self.contents.draw_text(0, WLH * 3, 128, WLH, "Ator 4")
  end
end
       O RGSS tem essas características peculiares:às vezes, uma mesma coisa pode ser feita com códigos diferentes.Depende de cada scripter utilizar a forma mais preferida.Se preferiu a primeira forma, use-a, se preferiu a segunda, use-a.Além dessas duas, existem muitas mais formas de se fazer.É aí que entra aí sua inteligência, não a minha:depende apenas de VOCÊ escolher de que forma fazer.É aí que você começa a conseguir seu próprio jeito de pensar em scripts.Pois é...parece que nossas window estão prontas...Falta apenas manipulá-las usando nossa scene!
[box class=titlebg]
6.5 - Finalizando nossa scene
[/box]

       Para começar colocamos na scene o código que cria nossas windows:
class Scene_Exemplo < Scene_Base
  def start
    @select_window = Window_SelectHero.new
    @name_window = Window_ShowName.new
  end
  def terminate
  end
  def update
  end
end

       Observe que criamos as window dentro do método start. Ele serve justamente para isso.Ao acabar nossa scene, devemos remover nossas windows da tela.Para isso, chamamos o método dispose delas:
class Scene_Exemplo < Scene_Base
  def start
    @select_window = Window_SelectHero.new
    @name_window = Window_ShowName.new
  end
  def terminate
    @name_window.dispose
    @select_window.dispose
  end
  def update
  end
end
       Observe que o dispose foi colocado no terminate. Como eu falei, no terminate colocamos o código que termina com os recursos utilizados pela nossa scene(no caso, windows).
       Esquecer de dar dispose nas windows logo após a scene acabar resultará que as windows irão permanecer na tela, e desaparecerão depois de um certo tempo.
       Por último, implementamos nosso método update.Lembre-se que ele executa muitas vezes por segundo, e deve sempre atualizar nossa scene.Nele, atualizamos nossas duas windows, com o método update.O método update das windows não atualiza a parte gráfica, como o refresh, apenas partes não gráficas.Logo após disso, analisamos se nesse meio tempo o botão Z do teclado foi pressionado, com a expressão Input.trigger?(Input::C).Por enquanto só saiba que essa expressão analisa se o botão foi pressionado, depois vou explicá-la detalhadamente.
       Se o Z foi pressionado, quer dizer que um novo ator foi selecionado.Devemos então atualizar nossa window que mostra o nome do ator.Fazemos isso chamando aquele método que criamos...mudar_texto, se lembram?Depois disso o código completo, incluindo com o update de que falei acima e não mostrei, com todas as windows e nossa scene fica assim:
class Window_SelectHero < Window_Selectable
  def initialize
    super(0, 0, 192, 160)
    @item_max = 4
    refresh
    self.index = 0
  end
  def refresh
    self.contents.clear
    textos = ["Ator 1", "Ator 2", "Ator 3", "Ator 4"]
    for i in [0, 1, 2, 3]
      self.contents.draw_text(0, WLH * i, 128, WLH, textos[i])
    end
  end
end
class Window_ShowName < Window_Base
  def initialize
    super(192, 0, 192, 160)
    @texto = $game_party.members[0].name
    refresh
  end
  def refresh
    self.contents.clear
    self.contents.draw_text(0, 0, 128, 32, @texto)
  end
  def mudar_texto(novo_texto)
    @texto = novo_texto
    refresh
  end
end
class Scene_Exemplo < Scene_Base
  def start
    @select_window = Window_SelectHero.new
    @name_window = Window_ShowName.new
  end
  def terminate
    @name_window.dispose
    @select_window.dispose
  end
  def update
    @name_window.update
    @select_window.update
    if Input.trigger?(Input::C)
      @name_window.mudar_texto($game_party.members[@select_window.index].name)
    end
  end
end
       Observe a linha @name_window.mudar_texto($game_party.members[@select_window.index].name).Ela muda o texto exibido pela nossa window para o nome do ator atualmente selecionado, que depende do índice da window selectable.Se o índice for 0, o ator selecionado será 0.Se o índice for 1, o ator será 1 também.Por isso podemos utilizar o índice para localizar qual ator está selecionado.Cool.
       Na aula passada eu havia dito que explicaria porque a window desaparecia depois de um tempo.Isso ocorre porque, quando um evento termina de acontecer, toda variável criada por scripts nesse evento acaba desaparecendo e, caso essa variável não tenha onde ser utilizada, o que ela guarda acaba sumindo também, no caso uma window.Quando colocamos uma window numa scene, essa window poderá ser utlizada enquanto essa scene existir.Quando a scene deixar de existir, a window acaba desaparecendo com o tempo também.Mas como queremos isso imediatamente, usamos o método dispose do qual falei.
       Até agora, só declaramos nossas windows e nossas scenes.Mas só declarar não basta, certo?Então vamos colocar nossa scene para funcionar!Para isso, coloque um comando de script de evento com o seguinte código, depois teste:
$scene = Scene_Exemplo.new

       Toda vez que queremos que nossa scene execute, substituimos a variável $scene.Observe que após isso o mapa some, isso pois ele deixa de ser a scene atual.Mas como retornar ao mapa?Basta atribuir o mapa ao $scene, assim:
$scene = Scene_Map.new

       No dever de casa pedirei uma aplicação disso.
[box class=titlebg]
6.6 - Conclusão
[/box]

       Puxa vida que aulinha que deu trabalho! Tenho certeza que , além disso, essa aula será considerada difícil para muitos.É por isso que estou aqui! Quaisqueres dúvias, basta postar no tópico que eu responderei prontamente.Tenho certeza que aqui é que surgirão muitas dúvidas.E lá vem os deveres de casa...Com certeza serão os mais difíceis de todos!Já chega de vocês pensarem com minha mente.Vocês agora terão que quebrar a cabeça e usar a mente de vocês.
[box class=titlebg]
6.7 - Deveres de casa
[/box]

[box title=Dever 1]
       Esse dever é bem fácil.No dever, quero que modifique nossa window selectable para exibir não 4 opções, porém 5.A 5ª opção será "Voltar".Quando essa opção for selecionada, a scene atual será trocada para o mapa.Boa sorte.Ah e para certos Mertholates, não façam nem mais nem menos do que eu pedi no dever ¬¬.
[/box]
[box title=Dever 2]
       Faça uma scene do zero.Essa scene permitirá selecionar os atores da equipe.Quando selecionado um ator, haverá uma outra window que exibirá informações daquele ator.Essa window pode ser a window do dever passado, modificada para funcionar do jeito que queremos.Também deve ter uma opção "Voltar", para voltar ao mapa.
[/box]
Eu queria realmente dar mais deveres legais, porém eu acho que mataria vocês, então por enquanto é só isso.Até mais.
:wow: :wow: :wow:

Cara eu fiz tudo certin mais quando eu vo la no evento onde coloquei o codigo pra começar a scene, eu clico enter e nada acontece.
O que há de errado?
OBS.: Eu uso o RPG Maker VX Ace, então fiz isso usando ele. Será esse o motivo de não estar funcionando? :será:

Desde já agradeço a sua atenção.

Citação de: mask.alves online 18/02/2013 às 03:57
Cara eu fiz tudo certin mais quando eu vo la no evento onde coloquei o codigo pra começar a scene, eu clico enter e nada acontece.
O que há de errado?
OBS.: Eu uso o RPG Maker VX Ace, então fiz isso usando ele. Será esse o motivo de não estar funcionando? :será:

Desde já agradeço a sua atenção.
Essa aula foi feita antes de lançarem o RMVXAce, então assim, no VXAce funciona da seguinte maneira.
SceneManager.call(Nome da Scene)

Mano agora dá erro nessa linha.
Veja:

self.contents.draw_text(0, WLH * i, 128, WLH, textos)

O que tem de errado aí?

Agradeço a atenção.
Abraços.

Essa é uma aula que foi criada com base no RMVX e RMXP x_x, tem muita coisa especifica para eles, porque assim veja o seguinte.
A linguagem é a mesma, Ruby, porém coisas especificas como Scenes e Windows, que são do RGSS, tem muita coisa diferente entre os makers, acho que se você pegar bem a ideia dessa aula, você consegue reproduzir por conta própria no Ace, fuçando as windows e scenes que tem lá por padrão.