Keep your place in this quest

Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.

Nesta lição, vamos finalizar o sistema que começamos na lição anterior criando os botões que se conectarão à lógica da plataforma e completarão a interação entre os dois sistemas.

Durante esse processo, exploraremos vários conceitos importantes no sistema de lógica visual do Cave. Você aprenderá como detectar colisões usando um Rigid Body, usar o nó Delay para controlar quando as ações acontecem ao longo do tempo, mudar a cor de uma Entidade durante a gameplay e também praticar a criação e uso de funções para manter seus Ladrilhos Lógicos organizados e reutilizáveis.

Ao final desta lição, teremos um sistema completo onde os botões podem ser ativados pelo Jogador e se comunicam corretamente com a plataforma criada anteriormente.

1. Criando o Botão

Para começar a criar o botão, primeiro crie um novo Entity Template.

Então, renomeie a Entidade de acordo com seu propósito, configure a Mesh que será usada como sua representação visual e adicione os componentes de física necessários para que ela interaja corretamente dentro do jogo.

Após isso, crie um novo Logic Brick e vincule-o à Entidade do botão.

Esse processo é muito semelhante ao que fizemos anteriormente ao criar a plataforma, então esta também é uma boa oportunidade para praticar os conceitos que você já aprendeu.

No final desta etapa, teremos a estrutura básica do botão pronta para receber sua lógica de ativação.

image.png

Agora, há uma etapa muito importante: não podemos esquecer de adicionar a tag button à Entidade do botão.

Se você se lembra, na lição anterior já preparamos a lógica da plataforma para contar automaticamente quantos botões existem na cena usando essa tag exata.

Por causa disso, a tag precisa ser criada e atribuída ao botão usando o mesmo nome que foi utilizado na lógica da plataforma.

Se o nome da tag for diferente, mesmo que por um pequeno detalhe, a plataforma não conseguirá encontrar os botões corretamente e a contagem não funcionará como esperado.

Então, antes de continuar, certifique-se de criar a tag button e adicioná-la à Entidade do botão.

image.png

Agora vamos também adicionar uma propriedade à Entidade do botão.

Usamos a tag button para identificar o botão dentro do mapa, mas usaremos uma propriedade para controlar parte de seu comportamento.

Crie uma nova propriedade chamada Active Time, do tipo Float.

Esta propriedade armazenará quanto tempo o botão deve permanecer ativo antes de retornar automaticamente ao estado inativo.

Isso torna o sistema mais flexível porque cada botão pode ter um tempo de ativação diferente. Por exemplo, um botão pode permanecer ativo por 3 segundos, enquanto outro botão pode permanecer ativo por 10 segundos, sem alterar o Logic Brick em si.

image.png

2. Criando a Lógica do Botão

Agora que nossa Entidade está pronta, com a tag e a propriedade configuradas, vamos começar a criar o comportamento do botão.

O primeiro passo é detectar a colisão entre a Entidade do botão e o Jogador, para que possamos ativá-lo quando o Jogador tocar nele.

No entanto, antes de implementar essa lógica, precisamos considerar um detalhe importante: só queremos que o botão seja ativado quando estiver atualmente inativo.

Uma vez que o botão terá dois estados diferentes, ativo e inativo, precisamos de uma maneira de armazenar qual estado está sendo usado atualmente.

Para fazer isso, crie uma nova propriedade no Logic Brick do botão chamada Active Button, do tipo Boolean.

Esta propriedade armazenará o estado atual do botão, indicando se ele está ativo ou não. Usaremos este valor nas próximas etapas para controlar todo o comportamento do botão.

image.png

Agora podemos começar a construir a lógica visual.

Em On Update, vamos verificar constantemente se o botão está ativo ou inativo usando a propriedade Active Button que acabamos de criar.

Para fazer isso, pegue seu valor usando Get Active Button e use um nó If para verificar seu estado.

Se a condição for False, isso significa que o botão está inativo e pode ser ativado. Nesse caso, iremos detectar a colisão entre o botão e o Jogador.

Para fazer isso, adicione um nó Collided With.

Esse nó precisa de um Rigid Body Component, então pegue a Entidade do botão e, dela, obtenha o Rigid Body Component que adicionamos ao configurar a física.

Também precisamos informar ao nó qual objeto queremos detectar. Para isso, adicione uma tag player ao personagem e passe essa tag para Collided With.

Dessa forma, a colisão será considerada válida somente quando o botão colidir com o Jogador.

Com essa estrutura, o botão só pode ser ativado quando está inativo e quando o Jogador realmente colide com ele.

image.png

Agora que temos ambos os caminhos definidos, vamos implementar a lógica para quando o botão está ativo.

Depois disso, criaremos o comportamento responsável por ativá-lo.

Para fazer isso, siga a condição True do nó If que verifica se o botão está ativo ou não.

Neste fluxo, usaremos a propriedade Active Time que criamos na Entidade do botão para controlar quanto tempo o botão deve permanecer ativo.

Primeiro, obtenha a Entidade do botão e acesse suas propriedades através do nó Get Properties.

Em seguida, use Get Property, conectando o dicionário retornado anteriormente e usando Active Time como a Key.

Como essa propriedade é um Float, altere o tipo de saída de Get Property para Float, garantindo que podemos usar esse valor corretamente na próxima parte da lógica.

image.png

Agora a saída de Get Property retorna o valor da propriedade Active Time, que define quanto tempo o botão deve permanecer ativo.

Em seguida, adicione um nó Delay e use esse valor como a duração.

Dessa forma, o tempo de espera é controlado diretamente pela propriedade da Entidade, permitindo que diferentes botões tenham tempos de ativação diferentes sem mudar a lógica.

Após o Delay terminar, use Set Active Button e defina seu valor como False.

Com isso, o botão retorna automaticamente ao estado inativo após o tempo especificado em sua propriedade.

image.png

Muito bem. Agora vamos seguir o outro caminho e criar o comportamento responsável por ativar o botão.

A saída do nó Collided With retorna um valor Bool.

Quando esse valor é True, significa que o botão colidiu com o Jogador.

Nesse momento, podemos simplesmente usar Set Active Button e definir seu valor como True.

Ao fazer isso, o botão entra no estado ativo e começa automaticamente a usar a lógica ativa que criamos anteriormente, que o mantém ativo por um certo tempo e, em seguida, o desativa novamente.

Com isso, criamos um ciclo de comportamento completo:

  • quando o Jogador colide com o botão, ele é ativado
  • após o tempo definido em Active Time, ele é desativado
  • depois disso, pode ser ativado novamente por outra colisão

Embora essa lógica seja simples, ela já dá ao botão dois estados diferentes e será a base para os próximos recursos que iremos adicionar.

image.png

Está tudo funcionando, mas ainda falta uma peça importante.

Embora a lógica de ativação e desativação do botão já esteja funcionando corretamente, nossa plataforma ainda não sabe quando um botão foi ativado.

É exatamente aqui que a propriedade Button Count que criamos anteriormente na Scene se torna importante.

Se você se lembra, na lógica da plataforma, definimos que a plataforma só deveria ser removida quando o valor dessa propriedade se torna igual ao número total de botões no mapa.

Em outras palavras, a plataforma já está pronta para reagir, mas até agora nenhum botão está mudando esse valor.

O que precisamos fazer agora é permitir que os botões modifiquem diretamente a propriedade Button Count da Scene sempre que forem ativados e desativados.

Esta é uma ótima oportunidade para praticar outro recurso muito importante dos Ladrilhos Lógicos no Cave: criar funções.

Em vez de repetir a mesma lógica várias vezes, iremos encapsular esse comportamento em funções reutilizáveis, mantendo nosso Gráfico mais organizado, mais fácil de entender e mais fácil de manter.

Como a propriedade Button Count está armazenada na Scene, primeiro precisamos acessá-la.

Para fazer isso, pegue a Scene usando Get Scene, e então use Get Properties.

image.png

3. Criando a Função que Controla Propriedades da Scene

A partir desses nós, criaremos uma função.

Para fazer isso, selecione os nós envolvidos, clique com o botão direito e escolha Promote Selection to Function.

image.png

Em seguida, renomeie a nova função para um nome claro e descritivo que represente sua finalidade dentro da lógica do projeto.

Neste caso, usaremos o nome Set Scene Property.

image.png

Agora vamos estruturar como a função Set Scene Property funcionará.

Primeiro, passe o dicionário de propriedades da Scene para o nó Get Property. Este dicionário vem do fluxo Get Scene → Get Properties.

Em seguida, altere a saída de Get Property para Int, garantindo que estamos trabalhando com valores inteiros.

Em Function Inputs, crie dois novos parâmetros para esta função:

  • Prop Name, do tipo String
  • Value, do tipo Int

O parâmetro Prop Name será usado como a Chave em Get Property, permitindo que a função acesse a propriedade desejada dentro do dicionário de propriedades da Cena.

Em seguida, atualizaremos essa propriedade usando Set Property.

Para fazer isso, obtenha o valor atual da propriedade, adicione a entrada Value a ele e escreva o resultado de volta na mesma propriedade.

Passamos o dicionário de propriedades da Cena novamente e usamos Prop Name como a chave.

Isso cria uma função genérica e reutilizável que pode modificar propriedades da Cena de forma simples e organizada.

Em vez de apenas definir um valor exato, essa função funciona como um sistema de incremento: ela adiciona o Value recebido ao valor atual da propriedade da Cena.

image.png

Com essa função pronta, não precisamos mais manter toda aquela cadeia de nós diretamente no Graph principal.

Agora, em vez de repetir toda a lógica, chamamos simplesmente a função logo após definir Active Button como True.

Isso significa que, no momento em que o botão é ativado, informamos imediatamente à lógica da plataforma que mais um botão foi pressionado.

Para isso, passe o nome da propriedade Button Count, que é a propriedade armazenada na Cena, e envie o valor 1 como incremento.

A função automaticamente adicionará +1 ao valor atual daquela propriedade.

Dessa forma, qualquer botão ativado atualiza diretamente o progresso global do sistema, sem duplicar a lógica.

Isso também nos dá mais flexibilidade para mudar propriedades da Cena no futuro reutilizando essa mesma função.

image.png

Para demonstrar como isso é simples e flexível, vamos voltar à lógica do botão ativo.

Logo após o tempo de ativação terminar e definirmos Active Button como False, chamaremos Set Scene Property novamente.

O parâmetro Prop Name será Button Count, usando a mesma propriedade da Cena.

Mas desta vez, o parâmetro Value será -1.

Como nossa função adiciona o valor recebido ao valor atual da propriedade da Cena, passar um número negativo automaticamente subtrai 1 do atual Button Count.

image.png

Dessa forma, sempre que um botão é desativado, o sistema também atualiza corretamente o progresso global, mantendo a lógica da plataforma sincronizada com o estado real dos botões no mapa.

image.png

Agora nossa lógica está funcionando como esperado.

Só falta um detalhe importante: criar um efeito visual para deixar claro ao jogador quando o botão está ativo.

Sempre que um botão é ativado, mudaremos diretamente sua cor usando o Tint, destacando visualmente seu estado.

Antes de definir Active Button como True, adicione uma Sequence.

Como não precisamos mais de três fluxos, podemos remover uma das saídas clicando com o botão direito e selecionando Remove Last Flow Output, mantendo apenas dois caminhos.

Em seguida, obtenha a Entidade filha do botão chamada ButtonMesh, acesse seu Mesh Component e ajuste o valor do Tint.

No eixo Y, defina o valor para 25, fazendo com que o botão apareça verde quando ativado.

Isso dá ao jogador um feedback visual claro sempre que um botão é pressionado, melhorando a legibilidade e resposta da interação dentro do jogo.

image.png

Da mesma forma, restauraremos a cor original do botão quando ele se tornar inativo.

Use a mesma lógica, mas no fluxo onde definimos Active Button como False.

Nesse momento, acesse novamente a Entidade filha ButtonMesh, obtenha seu Mesh Component e ajuste o valor do Tint.

Para retornar à cor padrão, basta definir todos os valores de Tint de volta para 1, restaurando o estado visual original do botão.

Dessa forma, sempre que o botão é desativado, ele também retorna à sua aparência inicial, deixando claro ao jogador que pode ser ativado novamente.

image.png

Selecionando uma instância de template de botão que adicionamos à cena, podemos acessar suas propriedades e mudar o valor de Active Time.

Dessa forma, cada botão pode ter uma duração de ativação diferente e funcionar de forma independente.

Isso nos dá mais flexibilidade para criar desafios variados dentro do nível, pois cada botão pode ser configurado individualmente sem alterar a lógica principal do sistema.

image.png

Com isso, podemos adicionar quantos botões quisermos ao mapa, cada um com um tempo de ativação diferente e comportamento independente.

A plataforma segue automaticamente essa configuração sem exigir ajustes manuais, pois a contagem é feita em tempo de execução.

O sistema também continua sincronizado com o estado real do jogo. À medida que os botões são ativados e desativados, o valor global é atualizado, e a plataforma reage quando a condição é atendida, sendo removida da cena no momento correto.

Além da lógica, adicionamos um feedback visual importante para o jogador.

Mudar a cor do botão quando ele é ativado e restaurar sua aparência original quando é desativado torna o sistema muito mais claro e intuitivo. O jogador pode entender visualmente quais botões estão ativos e quais ainda precisam de atenção.

No final, criamos um sistema modular e escalável que combina comunicação entre Entidades, controle centralizado através da Cena e feedback visual direto no mundo do jogo.

Essa mesma estrutura pode ser facilmente expandida para portas, plataformas, elevadores, quebra-cabeças, armadilhas, desafios cronometrados e muitos outros eventos interativos.

image.png