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

[Tutorial] Detecção de Posicionamento e Distância de Eventos - Parte 2

Iniciado por anticasper, 12/07/2014 às 19:18

Introdução

Salve Galera!

Dando sequência a série de tutoriais sobre detecção de eventos, rotinas e behaviors, trago agora a segunda parte, focada especialmente nas demais detecções. Na tutorial anterior falei sobre como criar uma verificação de distância entre dois characters e também pude introduzir um pouco da metodologia de desenvolvimento que sigo.

Para via de consulta, se você ainda não leu o tutorial anterior, segue o link:

Detecção de Posicionamento e Distância de Eventos - Parte 1




Detecção de Posicionamento e Distância de Eventos

Seguindo nossa linha de trabalho, hoje falaremos das detecções em linha.



Utilizando os códigos criados previamente, vamos partir para a segunda detecção, a mais simples de todas: Estar na frente do evento. Esta detecção vai exigir outra variável além das anteriormente vista, precisamos saber qual direção o evento está direcionado:

Coordenadas X e Y de cada Evento
Coordenadas X e Y do personagem Herói
Direção para aonde o evento está virado
Direção para aonde o herói está virado

Esta variável também pode ser encontrada no Game_CharacterBase com a alcunha de @direction:



Esta é uma variável de números inteiros e dito isso precisamos entender os valores que significam cada direção. A imagem abaixo ilustra os valores:



Os valores escrito na cor roxa significam valores padrão do RPG Maker e os em Amarelo são valores que usaremos futuramente.

Já sabemos como detectar para onde o evento está virado, agora precisamos criar um método que verifique se o herói está na frente do evento. Uma outra característica importante é dar um range máximo de visão, estipulando quando tiles o evento consegue ver.

Como não precisamos colocar nenhuma informação em nosso evento, podemos partir diretamente para o Game_Interpreter e criar lá nossa verificação. Começamos criando um método para verificar se o herói está na frente do evento e recebendo uma quantidade de tiles máximo que ele pode ser visto:



A partir disso podemos começar a fazer nossas verificações. Vamos tentar entender o que precisa ser checado:



Detalhando as verificações




Onde Range é a coordenada somando ou diminuindo a quantidadede tiles solicitada. E com esse entendimento, podemos construir o nosso código.

Façamos um case para múltiplas opções e nele façamos os retornos. O método deve ficar parecido com a imagem abaixo:



Comentei apenas o primeiro case para poder caber dentro da imagem, mas no código deixarei completamente comentado. Com nosso método pronto, podemos testa-lo com alguns eventos no mapa configurados assim:



E nas condições:



Porém temos um bug aí. Vocês podem perceber que a detecção de visão tem um erro quando encontra alguma parede, como a imagem abaixo:



Então, temos que mudar nosso método na_frente. Precisamos agora verificar a passabilidade entre o centro até o ponto máximo de visão. Caso tenha algo fechando a visão, precisamos retornar falso. Podemos fazer isso usando o comado for e alterando um pouco o método.



Agora sim, resolvi o meu problema de verificar visão do evento.

Veja um vídeo do funcionamento:



Material

Spoiler
Game_Interpreter

#============================================================================
# ** Game_Interpreter
#============================================================================
class Game_Interpreter
  #--------------------------------------------------------------------------
  # * Retorna o tamanho da distancia
  #--------------------------------------------------------------------------	
	def distancia
    # Verifica se o evento de fato existe
		if $game_map.events[@event_id] # Leia a nota 1
      # x do herói
      x = $game_player.x
      # y do herói
      y = $game_player.y
      # Chamamos o método para definir distância
			return $game_map.events[@event_id].define_distancia(x, y)
		else
			return false
		end
	end
  # ----------------
  # - Nota 1
  #
  #   $game_map é a variavel que gerencia os mapas.
  #   Ela contem uma lista de eventos do mapa que 
  #   são acessados através da sua id.
  #
  #   @event_id é a variavel que armazena a id do evento
  #   que chamou o interpretador
  # ----------------
  #--------------------------------------------------------------------------
  # * Verifica se o herói está na frente do evento
  #-------------------------------------------------------------------------- 
  def na_frente(tiles)
    # Armazena o evento numa variavel temporária para facil entendimento
    evento = $game_map.events[@event_id]
    # Armazena a direção do evento numa variavel temporária
		direcao = $game_map.events[@event_id].direction    
    # Inicia o Case e cria as possibilidades
		case direcao
			when 2 # Verificação para Baixo
        # Evita verificações desnecessárias
        return false if $game_player.x != evento.x
        # Armazena o x
        x = evento.x
        # Cria o range de ação
        range = evento.y + tiles
        # Variável para controle Retorno
        ret = false
        # Faz o laço entre as posições y
        for y in evento.y..range
          # Checa a passabilidade
          break if !$game_map.passable?(x, y, 2)
          # Verifica se a posição y é a mesma
          if $game_player.y == y
            ret = true
          end
        end
        # Retorna as informações
        return ret 
			when 4 # Verificação para Esquerda
        # Evita verificações desnecessárias
        return false if $game_player.y != evento.y
        # Armazena o y
        y = evento.y
        # Cria o range de ação
        range = evento.x - tiles
        # Variável para controle Retorno
        ret = false
        # Faz o laço entre as posições x
        for x in evento.x.downto(range)
          # Checa a passabilidade
          break if !$game_map.passable?(x, y, 4)
          # Verifica se a posição y é a mesma
          if $game_player.x == x
            ret = true
          end
        end
        # Retorna as informações
        return ret
			when 6 # Verificação para Direita
        # Evita verificações desnecessárias
        return false if $game_player.y != evento.y
        # Armazena o y
        y = evento.y
        # Cria o range de ação
        range = evento.x + tiles
        # Variável para controle Retorno
        ret = false
        # Faz o laço entre as posições x
        for x in evento.x..range
          # Checa a passabilidade
          break if !$game_map.passable?(x, y, 6)
          # Verifica se a posição y é a mesma
          if $game_player.x == x
            ret = true
          end
        end
        # Retorna as informações
        return ret 						
      when 8 # Verificação para Cima
        # Evita verificações desnecessárias
        return false if $game_player.x != evento.x
        # Armazena o x
        x = evento.x
        # Cria o range de ação
        range = evento.y - tiles
        # Variável para controle Retorno
        ret = false
        # Faz o laço entre as posições y
        for y in evento.y.downto(range)
          # Checa a passabilidade
          break if !$game_map.passable?(x, y, 8)
          # Verifica se a posição y é a mesma
          if $game_player.y == y
            ret = true
          end
        end
        # Retorna as informações
        return ret 			
		end
	end  
#--------------------------------------------------------------------------
end
[close]

Link para download do Projeto.




Até o próximo tutorial da série!


Como eu disse na parte 1, o mais legal é o leque de possibilidades que esses sistemas abrem.

Parabéns anticasper, isso é muito bacana; e ainda tem gente que fica pedindo scripts complexos para sistemas de vigias, guardas, etc...

Metal Gear Solid here we go.
"Um gênio é 1% de inspiração e 99% de transpiração."

Thomas Edson