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

Janela que mostra o gráfico do personagem no menu.

Iniciado por Rhyan, 15/04/2020 às 09:35

15/04/2020 às 09:35 Última edição: 15/04/2020 às 10:54 por Rhyan
Acho que o nome em si já explica o propósito do código, que é fazer uma janelinha no menu onde mostra o atual gráfico do personagem.

Imagens de como ficou (é bem simpleszinho, nada de mais):


class Window_Character_IMG < Window_Base
  def initialize
    super(10,220, window_width, window_height)
    
    @sc_menu_img = Scene_Menu.new
    @sc_menu_img.create_player
    
    $imagem_do_player.x = 80
    $imagem_do_player.y = 300
  end
  
  def window_width
    return 140
  end
  
  def window_height
    return 120
  end
end

class Scene_Menu < Scene_MenuBase
  
  alias player_window_start start
  alias player_window_terminate terminate
  
  def start
    super
    player_window_start
    @nova_janela_personagem = Window_Character_IMG.new
  end
  
  def terminate
    player_window_terminate
    $imagem_do_player.dispose
    super
  end
  
  def create_player
    $imagem_do_player = Sprite_Character.new(@viewport, $game_player)
  end
end
[/img]
^~^) -Rhyan.

15/04/2020 às 11:13 #1 Última edição: 15/04/2020 às 11:15 por Raizen
Bom, vamos ao trabalho  :malvado:

Primeira parte, não use variáveis globais, tipo a menos que sejam extremamente necessários, você deve sempre reduzir o escopo da sua variável o máximo possível, isso ajuda no gerenciamento de memória, além de facilitar a leitura e a organização do código. Nesse caso especifico, só de bater o olho eu consigo ver que a variável $imagem_do_player pode ser facilmente uma variável de instância, aquela que começa com @.

agora aonde você errou aqui para criar a variável com escoplo global? Foi no fato de você usar a Scene_Menu para criar e destruir a imagem mesmo que tem parâmetros no Window_Character_IMG...

Agora, eu coloquei isso primeiro para respirar, porque você fez um erro fatal nesse script  :bravo:

    @sc_menu_img = Scene_Menu.new
    @sc_menu_img.create_player


Sabe o que você fez aqui? vou te explicar mais ou menos, você criou um método create_player para criar a imagem, até ai nada de mais, porém você colocou dentro do Scene_Menu e instanciou ele no seu objeto @sc_menu_img, o Scene_Menu é uma subclasse de Scene_MenuBase que é subclasse de Scene_Base...
Como você mesmo pode ver aqui:

Scene_Menu < Scene_MenuBase


Isso em outra metáfora é a mesma coisa de ... "Olá, preciso de um copo de água." E ai você tacou o cara dentro da piscina e falou TOMA. Resumindo, você usou um tanque pra abrir uma porta emperrada, acho que pegou a ideia. Você está instanciando uma classe que tem sei lá, seus 80 métodos, suas 100 variáveis para fazer um trabalho mínimo como esse. E vou um pouco além, isso não travou seu PC? Isso tá com cara de dar stack error, ele empilhar Scene_Menu em cima de Window em cima de Scene_Menu etc...

Resumindo três coisas para fazer e ai depois você volta aqui com o código reescrito.

Coloque todo o gerenciamento do Sprite dentro do Window ao invés de ter qualquer coisa no Scene_Menu, ah um detalhe, mas isso pode ser feito depois, o Window já é uma espécie de Sprite, então normalmente é criado o bitmap direto nela, vide exemplo do próprio Ojima:
  def draw_face(face_name, face_index, x, y, enabled = true)
    bitmap = Cache.face(face_name)
    rect = Rect.new(face_index % 4 * 96, face_index / 4 * 96, 96, 96)
    contents.blt(x, y, bitmap, rect, enabled ? 255 : translucent_alpha)
  end

Mas isso é o de menos no momento.

Coloque esse create dentro da window, você pode chamar o create no Scene_Menu, tipo
@nova_janela_personagem.create_player.

Colocado tudo dentro do Window, pode essa variável global para variável de instância.

E PORFAVOR tire isso @sc_menu_img = Scene_Menu.new, isso é muito poder para uma variável XD.

de resto a gente arruma depois desses erros críticos :)

15/04/2020 às 11:42 #2 Última edição: 15/04/2020 às 11:43 por Rhyan
Citação de: Raizen online 15/04/2020 às 11:13
Bom, vamos ao trabalho  :malvado:

Primeira parte, não use variáveis globais, tipo a menos que sejam extremamente necessários, você deve sempre reduzir o escopo da sua variável o máximo possível, isso ajuda no gerenciamento de memória, além de facilitar a leitura e a organização do código. Nesse caso especifico, só de bater o olho eu consigo ver que a variável $imagem_do_player pode ser facilmente uma variável de instância, aquela que começa com @.

agora aonde você errou aqui para criar a variável com escoplo global? Foi no fato de você usar a Scene_Menu para criar e destruir a imagem mesmo que tem parâmetros no Window_Character_IMG...

Agora, eu coloquei isso primeiro para respirar, porque você fez um erro fatal nesse script  :bravo:

    @sc_menu_img = Scene_Menu.new
    @sc_menu_img.create_player


Sabe o que você fez aqui? vou te explicar mais ou menos, você criou um método create_player para criar a imagem, até ai nada de mais, porém você colocou dentro do Scene_Menu e instanciou ele no seu objeto @sc_menu_img, o Scene_Menu é uma subclasse de Scene_MenuBase que é subclasse de Scene_Base...
Como você mesmo pode ver aqui:

Scene_Menu < Scene_MenuBase


Isso em outra metáfora é a mesma coisa de ... "Olá, preciso de um copo de água." E ai você tacou o cara dentro da piscina e falou TOMA. Resumindo, você usou um tanque pra abrir uma porta emperrada, acho que pegou a ideia. Você está instanciando uma classe que tem sei lá, seus 80 métodos, suas 100 variáveis para fazer um trabalho mínimo como esse. E vou um pouco além, isso não travou seu PC? Isso tá com cara de dar stack error, ele empilhar Scene_Menu em cima de Window em cima de Scene_Menu etc...

Resumindo três coisas para fazer e ai depois você volta aqui com o código reescrito.

Coloque todo o gerenciamento do Sprite dentro do Window ao invés de ter qualquer coisa no Scene_Menu, ah um detalhe, mas isso pode ser feito depois, o Window já é uma espécie de Sprite, então normalmente é criado o bitmap direto nela, vide exemplo do próprio Ojima:
  def draw_face(face_name, face_index, x, y, enabled = true)
    bitmap = Cache.face(face_name)
    rect = Rect.new(face_index % 4 * 96, face_index / 4 * 96, 96, 96)
    contents.blt(x, y, bitmap, rect, enabled ? 255 : translucent_alpha)
  end

Mas isso é o de menos no momento.

Coloque esse create dentro da window, você pode chamar o create no Scene_Menu, tipo
@nova_janela_personagem.create_player.

Colocado tudo dentro do Window, pode essa variável global para variável de instância.

E PORFAVOR tire isso @sc_menu_img = Scene_Menu.new, isso é muito poder para uma variável XD.

de resto a gente arruma depois desses erros críticos :)

Hay, Raizen! Vou anotar o que disse. Na verdade (vou sair um pouquinho do assunto do tópico), eu estou meio que adotando um método de... Na verdade, não sei, só sei que está me ajudando bastante em evitar erros antigos como o "start" na Scene e coisas do tipo. Se trata mais ou menos de uma verificaçãozinha ou um aperfeiçoamento, como quiser chamar.

Basicamente, a medida que eu vou criando scripts e os mesmos vão tendo alguns erros daqui e ali, eu vou adicionando esses erros em uma lista. Então, simplesmente eu checo se o script não está com nenhum dos erros que está anotado. Enfim, comentários como o seu que mostram os erros acabam me ajudando bastante. O que acontece que só 20, 30, 40% das pessoas que veem o tópico acabam comentando :(...

Enfim, obrigado! Já anotei e isso não acontecerá de novo!

Por último, esse método de verificação é eficaz? 

Té mais!  :ok:
^~^) -Rhyan.

Citação de: Rhyan online 15/04/2020 às 11:42
Hay, Raizen! Vou anotar o que disse. Na verdade (vou sair um pouquinho do assunto do tópico), eu estou meio que adotando um método de... Na verdade, não sei, só sei que está me ajudando bastante em evitar erros antigos como o "start" na Scene e coisas do tipo. Se trata mais ou menos de uma verificaçãozinha ou um aperfeiçoamento, como quiser chamar.

Basicamente, a medida que eu vou criando scripts e os mesmos vão tendo alguns erros daqui e ali, eu vou adicionando esses erros em uma lista. Então, simplesmente eu checo se o script não está com nenhum dos erros que está anotado. Enfim, comentários como o seu que mostram os erros acabam me ajudando bastante. O que acontece que só 20, 30, 40% das pessoas que veem o tópico acabam comentando :(...

Enfim, obrigado! Já anotei e isso não acontecerá de novo!

Por último, esse método de verificação é eficaz? 

Té mais!  :ok:
Você diz isso?
Sprite_Character.new(@viewport, $game_player)


Aparentemente sim, é o mesmo que foi feito lá, e agora que falou eu nem tinha olhado o código do Ace, mas dei uma zoiada e consigo entender +ou- como foi a sua ideia em relação a colocar dentro do Scene_Menu, é porque o @viewport está visivel apenas lá correto?

Você pode fazer isso passando ele como parâmetro, ai você mantém a manipulação no Window tipo.
@nova_janela_personagem.create_player(@viewport).

Porém o ideal mesmo é do modo que eu tinha mostrado antes, criar o bitmap dentro do Window, tem um exemplo no meu post anterior, e se for pra character já inclusive existe o método dentro do Window_Base que você pode usar, e por isso eu recomendo ele ao invés de fazer esse rolê com o Sprite_Character, olha:
  #--------------------------------------------------------------------------
  # * Desenho do gráfico do personagem
  #     character_name  : nome do gráfico do personagem
  #     character_index : índice do gráfico de personagem
  #     x               : coordenada X
  #     y               : coordenada Y
  #--------------------------------------------------------------------------
  def draw_character(character_name, character_index, x, y)
    return unless character_name
    bitmap = Cache.character(character_name)
    sign = character_name[/^[\!\$]./]
    if sign && 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)
    contents.blt(x - cw / 2, y - ch, bitmap, src_rect)
  end


Basta usar esse ai,

tipo
dentro do seu window
draw_character($game_party.members.first.name, $game_party.members.first.character_index, x, y)

Citação de: Raizen online 15/04/2020 às 11:56
Você diz isso?

Sprite_Character.new(@viewport, $game_player)


Aparentemente sim, é o mesmo que foi feito lá, e agora que falou eu nem tinha olhado o código do Ace, mas dei uma zoiada e consigo entender +ou- como foi a sua ideia em relação a colocar dentro do Scene_Menu, é porque o @viewport está visivel apenas lá correto?

Você pode fazer isso passando ele como parâmetro, ai você mantém a manipulação no Window tipo.
@nova_janela_personagem.create_player(@viewport).

Porém o ideal mesmo é do modo que eu tinha mostrado antes, criar o bitmap dentro do Window, tem um exemplo no meu post anterior, e se for pra character já inclusive existe o método dentro do Window_Base que você pode usar, e por isso eu recomendo ele ao invés de fazer esse rolê com o Sprite_Character, olha:
  #--------------------------------------------------------------------------
  # * Desenho do gráfico do personagem
  #     character_name  : nome do gráfico do personagem
  #     character_index : índice do gráfico de personagem
  #     x               : coordenada X
  #     y               : coordenada Y
  #--------------------------------------------------------------------------
  def draw_character(character_name, character_index, x, y)
    return unless character_name
    bitmap = Cache.character(character_name)
    sign = character_name[/^[\!\$]./]
    if sign && 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)
    contents.blt(x - cw / 2, y - ch, bitmap, src_rect)
  end


Basta usar esse ai,

tipo
dentro do seu window
draw_character($game_party.members.first.name, $game_party.members.first.character_index, x, y)

"Você diz isso?" Não kk. Estou falando do método que adotei para verificar se os scripts tem algum tipo de erro. Mas mesmo assim, a ideia do draw_character foi uma boa, vou adicionar no script.
^~^) -Rhyan.

O método que você deveria adotar para saber se seu script tem algum erro deveria ser estudar e aprender a analisar o próprio código, encontrando os erros através da observação. Contar com feedback é bom e essencial, mas você não pode querer depender dos outros pra sempre.

Falando em observação, você teria evitado todos os problemas do seu código se simplesmente tivesse parado para observar como todas as windows do RPG Maker funcionam. Já viu que a classe Window_Base tem um método chamado draw_character que desenha o gráficos dos personagens? Pois é...


Citação de: Gabriel online 16/04/2020 às 03:11
O método que você deveria adotar para saber se seu script tem algum erro deveria ser estudar e aprender a analisar o próprio código, encontrando os erros através da observação. Contar com feedback é bom e essencial, mas você não pode querer depender dos outros pra sempre.

Falando em observação, você teria evitado todos os problemas do seu código se simplesmente tivesse parado para observar como todas as windows do RPG Maker funcionam. Já viu que a classe Window_Base tem um método chamado draw_character que desenha o gráficos dos personagens? Pois é...

:holmes:, segundo minhas últimas observações do meu código, como lá não tem a função "draw_character", não, eu não sabia da existência da mesma. Obrigado por responder, Gabriel.
^~^) -Rhyan.

Acho que o Raizen já deu as sugestões necessárias pra arrumar o código. No geral, o que você fez não está errado do ponto de vista prático, porque até que funciona; o problema é a forma que você implementou, que foge demais dos padrões, e eles existem por um motivo: entre eles, garantir manutenabilidade do código e evitar reinventar a roda (até porque geralmente alguém já inventou uma melhor).

Sobre seu "método de verificação", acho que é uma abordagem bem ruim. Se você está cometendo tanto os mesmo erros a ponto de ter que anotar e ficar checando, acredito que seja mais produtivo só voltar seis casas e estudar o básico de novo antes de sair tentando fazer as coisas sem rumo. Todo aprendizado é baseado em uma mistura bem dosada de tentativa-e-erro e estudo; você não vai se desenvolver só lendo aulas e tutoriais e o que seja, mas também não vai avançar se sair tentando fazer coisas sem saber se estão corretas ou não. Lembrando que funcionar =/= estar correto.

Assino em baixo do comentário do Gabriel: é positivo pedir feedback, sugestões e etc., mas tenha certeza antes que você fez tudo que podia sozinho. Se não estiver conseguindo estudar, melhor achar outra fonte ou contratar um professor particular ou algo do tipo. É bem desgastante para os outros ter que ficar corrigindo scripts e ensinando o modo certo de fazer as coisas, especialmente se os problemas que aparecem poderiam ser evitados simplesmente estudando melhor antes.

Quanto à taxa de de respostas por visualização, é assim mesmo, seria estranho se não fosse. É muito mais fácil ler o tópico que elaborar uma resposta, nem todo mundo que lê o tópico de fato tem algo a contribuir com o tópico (e nesse caso, melhor não responder mesmo que floodar o fórum), e afinal ninguém tem obrigação de responder. Nem todo mundo tem tempo livre pra gastar, alguns trabalham e têm seus próprios projetos, dúvidas e estudos para tocar. Se você sequer tem respostas no seu tópico (especialmente respostas com mais de três linhas), já está no lucro.
~ Masked