quarta-feira, 21 de junho de 2023

Versão final do código Verse do collect_game_device

Este é o último artigo da Parte I. Para concluir o mini game, está faltando implementar apenas duas regras da especificação do mini game.

Essas são as regras que vamos implementar neste artigo: 

  • O nível do jogo determina os pontos que o jogador ganha ao coletar uma moeda.

  • A cada 3 moedas coletadas, o nível do jogo aumenta e é adicionado 5 segundos ao tempo da partida.


O nível do jogo é apenas um valor inteiro que indica o progresso do jogador na partida.

Vamos criar estas 4 variáveis/constantes para implementar as regras:

  • CoinsPerLevel : Constante Verse que indica quantas moedas precisam ser coletadas pelo jogador para aumentar o nível do jogo. Possui o atributo @editable para permitir que o seu valor seja modificado direto no UEFN.
  • BonusTime  : Constante Verse com a quantidade de segundos que será adicionado ao tempo da partida quando o jogador aumentar o nível do jogo. Também possui o atributo @editable.
  • CoinsCollected : Variável Verse que armazena a quantidade de moedas coletadas pelo jogador. Ela é usada para verificarmos quando o jogador aumentou o nível do jogo.
  • GameLevel : Variável Verse que indica o nível de jogo atual. 


Adicione a declaração das variáveis/constantes depois da linha do ScoreManagerDevice:

    @editable
    CoinsPerLevel : int = 3

    @editable
    BonusTime : float = 5.0

    var CoinsCollected : int = 0

    var GameLevel : int = 1

Vamos criar uma função com o nome AddTime que será usada para adicionar tempo em segundos ao Timer DeviceAdicione o código abaixo no final do arquivo Verse:

    AddTime(TimeToAdd:float):void=
        var TimeLeft:float = TimerDevice.GetActiveDuration( )
        TimerDevice.SetActiveDuration( TimeLeft + TimeToAdd)

Esta função pega o tempo atual do Timer Device usando a função  GetActiveDuration. O novo tempo do Timer Device é definido com a função SetActiveDuration usando como parâmetro o resultado da soma do tempo atual com o tempo a ser adicionado.

Existe uma função chamada Mod que retorna o resto de uma divisão entre números inteiros. Usaremos Mod para aumentar o nível do jogo a cada 3 moedas coletadas. Para usar a função Mod é preciso incluir o módulo Verse:

using { /Verse.org/Verse}

As modificações relacionadas as regras que estão faltando serão feitas na função HandleCoinPickedUp que tem de ficar assim:

    HandleCoinPickedUp(Agent:agent):void=

        ScoreManagerDevice.Activate(Agent)

        set CoinsCollected += 1

        if ( Mod[CoinsCollected, CoinsPerLevel] = 0):
            set GameLevel += 1
            ScoreManagerDevice.SetScoreAward( GameLevel )
            AddTime( BonusTime )

        SpawnCoin()

Toda vez que uma moeda for coletada, usamos Mod para verificar se a quantidade de moedas coletadas (CoinsCollected) é múltiplo de 3 (valor padrão de CoinsPerLevel). Se for múltiplo de 3, então o resultado do Mod tem de ser zero indicando que o nível do jogo aumentou.

Observe que a função Mod usa [] ao invés de (). Isto ocorre porque Mod é uma função que pode falhar (failable). 

O código Verse abaixo é a versão final do collect_game_device:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Random }
using { /Verse.org/Simulation/Tags }
using { /Verse.org/Verse}

coin_spawner := class(tag){}

collect_game_device := class(creative_device):

    @editable
    TimerDevice : timer_device = timer_device{}

    @editable
    EndGameDevice : end_game_device = end_game_device{}

    @editable
    var CoinSpawnerDevices : []item_spawner_device = array{}

    @editable
    ScoreManagerDevice : score_manager_device = score_manager_device{}

    @editable
    CoinsPerLevel : int = 3

    @editable
    BonusTime : float = 5.0

    var CoinsCollected : int = 0

    var GameLevel : int = 1

    OnBegin<override>()<suspends>:void=
        TimerDevice.SuccessEvent.Subscribe(HandleTimerFinished)
        SetupCoinSpawnerDevices()
        
    HandleTimerFinished(MaybeAgent:?agent):void=
        if(Agent := MaybeAgent?):
            EndGameDevice.Activate(Agent)

    SpawnCoin():void=    
        if: 
            IndexSpawner: int = GetRandomInt(0, CoinSpawnerDevices.Length - 1)
            NextCoinSpawner := CoinSpawnerDevices[IndexSpawner]
        then:
            NextCoinSpawner.SpawnItem()

    SetupCoinSpawnerDevices():void=

        TaggedActors := GetCreativeObjectsWithTag(coin_spawner{})

        set CoinSpawnerDevices = for:
            TaggedActor : TaggedActors
            ItemDevice := item_spawner_device[TaggedActor]
        do:
            ItemDevice

        for (SpawnerDevice : CoinSpawnerDevices):
            SpawnerDevice.ItemPickedUpEvent.Subscribe(HandleCoinPickedUp)

        SpawnCoin()
    
    HandleCoinPickedUp(Agent:agent):void=

        ScoreManagerDevice.Activate(Agent)

        set CoinsCollected += 1

        if ( Mod[CoinsCollected, CoinsPerLevel] = 0):
            set GameLevel += 1
            ScoreManagerDevice.SetScoreAward( GameLevel )
            AddTime( BonusTime )

        SpawnCoin()

    AddTime(TimeToAdd:float):void=
        var TimeLeft:float = TimerDevice.GetActiveDuration( )
        TimerDevice.SetActiveDuration( TimeLeft + TimeToAdd)

Salve o arquivo e compile o código Verse usando a opção Verse > Build Verse Code do menu do UEFN.

Selecione o collect game device que está no nível. Na aba Details, veja que você pode alterar os valores de CoinsPerLevel e BonusTime para ajustar o gameplay sem precisar recompilar o código Verse: 



Salve o nível e inicie a sessão. Veja qual é a pontuação máxima que você consegue.

O aprendizado da programação requer muita prática. Este mini game é simples mas ele utiliza diversos conceitos essenciais da linguagem Verse como:

  • Variáveis e constantes; 
  • Referências à dispositivos;
  • Registrar funções em eventos;
  • Conversão de referências usando cast;
  • Criação de tags;

Espero que este passo-a-passo para a criação deste mini game tenha sido útil para o seu aprendizado em Verse. 

Se você for instrutor, sinta-se a vontade para usar o mini game como atividade para os seus alunos para que possam discutir os conceitos Verse usados e aprimorar este exemplo.


Sumário Verse