Ao concluir esta etapa no tutorial Quebra-cabeça de luzes marcadas, você aprenderá a detectar quando o jogador resolve o quebra-cabeça para que você possa gerar um item e evitar mais interação com o quebra-cabeça.
Detectando um enigma resolvido
Esta seção mostra como detectar quando o jogador resolve o quebra-cabeça encontrando a combinação certa de luzes. Quando o quebra-cabeça for resolvido, o dispositivo Gerador de Itens deve ser habilitado para que possa gerar seu item.
Siga estas etapas para detectar quando o jogador resolve o quebra-cabeça:
- Adicione um campo
item_spawner_deviceeditável chamadoItemSpawnerà classetagged_lights_puzzlepara representar o dispositivo do gerador de itens. ~~~(verse) @editable ItemSpawner : item_spawner_device = item_spawner_device{} ~~~ - Em seguida, defina em que estado as luzes devem estar para resolver o quebra-cabeça. Como a representação do estado das luzes é uma matriz
logic, o estado resolvido das luzes também deve ser uma matrizlogicpara comparar facilmente os dois. Crie um campo de matrizlogiceditável chamadoSolvedLightsStatepara a classetagged_lights_puzzle. Neste exemplo, o jogador deve acender todas as luzes para resolver o quebra-cabeça, então inicialize cada elemento com o valortruepara representar a luz acesa. ~~~(verse) @editable SolvedLightsState : []logic = array{true, true, true, true} ~~~ - Salve o arquivo no Visual Studio Code.
- Na barra de ferramentas do UEFN, clique em Compilar Scripts do Verse para atualizar seu dispositivo Verse no nível.
- No Organizador, selecione tagged_lights_puzzle para abrir seu painel Detalhes.
- No painel Detalhes, defina a propriedade Gerador de Itens como o dispositivo Gerador de Itens que está no nível.
- Em seguida, desenvolva o código que verifica se o
LightsStateatual corresponde aSolvedLightsState. Adicione um novo método chamadoIsPuzzleSolved()à classetagged_lights_puzzle. Esse método deve funcionar se o quebra-cabeça for resolvido e falhar se não for, para que seu chamador saiba o resultado da verificação. Isso significa que o método deve ser marcado como falível com o especificadordecides. Como o método possui o especificadordecides, ele também deve ter o especificadortransacts, o que significa que as ações realizadas por esse método poderão ser revertidas (como se nunca tivessem sido realizadas) se houver uma falha em qualquer parte do método. ~~~(verse) IsPuzzleSolved(): void = Logger.Print("Verificando se o quebra-cabeça foi resolvido") ~~~ O Verse usa sucesso/falha para a tomada de decisões. Para obter mais detalhes sobre como o Verse usa falhas, consulte Falha.
- Quando o dispositivo deve verificar se o quebra-cabeça foi resolvido? O melhor momento é sempre quando a matriz
LightsStateacabou de ser atualizada, o que acontece dentro do métodoToggleLights(). Depois que a expressãoforterminar de atualizar a matriz deLightsState, chame o métodoIsPuzzleSolved[]para determinar se o quebra-cabeça foi resolvido e, assim, gerar um item (chamandoItemSpawner.Enable() ComoIsPuzzleSolved[]é uma expressão falível (é por isso que o método tem[]em vez de()quando você a chama), ela deve ser chamada em um contexto de falha. Neste exemplo, o contexto de falha é uma expressão [if`](if-in-verse) e, portanto, você pode executar expressões condicionalmente com base na solução do quebra-cabeça.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices IsLightOn := LightsState[LightIndex] Light := Lights[LightIndex] do: Logger.Print("Acendendo a luz no índice {LightIndex} {if (IsLightOn?) then "Off" else "On"}") NewLightState := if (IsLightOn?): Light.TurnOff() false else: Light.TurnOn() true if (set LightsState[LightIndex] = NewLightState): Logger.Print("Estado da luz atualizado em {LightIndex}") if (IsPuzzleSolved[]): Logger.Print("Quebra-cabeça resolvido!") ItemSpawner.Enable() -
Em seguida, faça o método
IsPuzzleSolved()detectar se o quebra-cabeça foi resolvido. ComoIsPuzzleSolved()é um contexto de falha, você pode usar expressões falíveis no corpo do método sem precisar usar outro contexto de falha, como uma expressãoif. Nesse caso, você precisará verificar se o estado de cada luz é o mesmo do quebra-cabeça resolvido. Para testar se dois valoreslogicsão iguais, você pode usar o operador de igualdade=, que é uma expressão falível. Da primeira vez em que dois valores que você está verificando não forem os mesmos, a expressão falhará e, consequentemente, também o método, retornando ao contexto de seu chamador (neste caso, a expressãoifno métodoToggleLights()). ~~~(verse) IsPuzzleSolved(): void = Logger.Print("Verificando se o quebra-cabeça foi resolvido") for: LightIndex -> IsLightOn : LightsState IsLightOnInSolution := SolvedLightsState[LightIndex] do: IsLightOn = IsLightOnInSolution ~~~
- Salve as alterações no Visual Studio Code.
- Na barra de ferramentas do UEFN, clique em Compilar scripts do Verse para compilar seu código.
- Clique em Play na barra de ferramentas do UEFN para testar o nível.
Ao testar seu nível com as configurações mostradas neste exemplo, interagir com todos os botões uma vez deve resolver o quebra-cabeça e gerar o item.

Removendo a interação do botão quando o enigma é resolvido
Depois que o jogador tiver concluído o quebra-cabeça, ele não poderá interagir com os botões ou acender/apagar as luzes. Esta seção mostra como cancelar a assinatura de um evento, para que seu manipulador de eventos não seja mais chamado quando um jogador interagir com o botão.
Quando você chama Subscribe() em um evento de dispositivo, a chamada de função tem um resultado cancelable. Chamar Cancel() em uma variável cancelable cancela a assinatura da função que manipula o evento, fazendo com que a função não seja mais chamada quando o evento for despachado.
Siga estas etapas para remover as interações de botão assim que o quebra-cabeça for resolvido:
- Adicione um campo de variável de matriz
cancelablechamadoButtonSubscriptionsà classetagged_lights_puzzlepara armazenar o resultado da assinatura de cada evento de botão e inicialize o campo com uma matriz vazia.var ButtonSubscriptions : []cancelable = array{} -
Como esta é a última instrução da expressão
for, seus valores de retorno para todas as iterações bem-sucedidas são coletados em uma matriz do tipo de retorno de expressão. Conforme explicado anteriormente, o tipo de retorno de uma chamada de eventoSubscribeécancelable; isso faz referência a ToggleLights aos resultados deforem uma matriz decancelable([]cancelable). Isso corresponde ao tipoButtonsSubscription, para que você possa atribuir o resultado da expressãoforà matrizButtonsSubscription. Adicione este código à funçãoOnBegindepois deSetupPuzzleLights: ~~~(verse) OnBegin() : void = SetupPuzzleLights() set ButtonSubscriptions = for: ButtonIndex -> Button : Buttons LightIndices := ButtonsToLights[ButtonIndex] do: Button.InteractedWithEvent.Subscribe(button_event_handler{Indices := LightIndices, PuzzleDevice := Self}.OnButtonPressed) ~~~
-
Por fim, lembre-se que os botões devem ser desabilitados para que o jogador não possa mais alterar o
LightsState. Isso é obtido cancelando a assinatura dos indicadoresInteractedWithEventde cada botão com uma chamada para sua assinaturacancelable. EssesButtonSubscriptionsforam salvos quando os identificadores de eventos foram criados emOnBegin. Tudo o que resta a fazer é iterar por essa matriz e chamar cancelar em cadaButtonSubcription: ~~~(verse) ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices IsLightOn := LightsState[LightIndex] Light := Lights[LightIndex] do: Logger.Print("Acendendo a luz no índice {LightIndex} {if (IsLightOn?) then "Apagada" else "Acesa"}") NewLightState := if (IsLightOn?): Light.TurnOff() false else: Light.TurnOn() true if (set LightsState[LightIndex] = NewLightState): Logger.Print("Atualização do estado da luz em {LightIndex}")if (IsPuzzleSolved[]): Logger.Print("Quebra-cabeça resolvido!") ItemSpawner.Enable()
for (ButtonSubscription : ButtonSubscriptions): ButtonSubscription.Cancel() ~~~
- Salve as alterações no Visual Studio Code.
- Na barra de ferramentas do UEFN, clique em Compilar scripts do Verse para compilar seu código.
- Clique em Play na barra de ferramentas do UEFN para testar o nível.
Com as propriedades padrão, interagir com todos os botões uma vez deve resolver o quebra-cabeça, gerar o item e desativar outras interações com botões.
Próxima etapa
Na última etapa deste tutorial, você pode ver o script completo do tutorial e ideias para alterar ainda mais o exemplo.