quarta-feira, 21 de junho de 2023

Final version of collect_game_device Verse code

This is the last article of Part I. To complete the mini game, it remains to implement only two rules from the mini game specification.

These are the rules that we are going to implement in this article: 

  • The game's level determines the points the player earns when collecting a coin.

  • For every 3 coins collected, the game level increases and 5 seconds are added to the match time.

The game level is just an integer value that indicates the player's progress in the match.

Let's create these 4 variables/constants to implement the rules:

  • CoinsPerLevel Verse constant that indicates how many coins need to be collected by the player to increase the game level. It has the @editable attribute to allow its value to be modified directly in UEFN.
  • BonusTime  : Verse constant with the amount of seconds that will be added to the match time when the player increases the game level. It also has the @editable attribute.
  • CoinsCollected : Verse variable that stores the amount of coins collected by the player. It is used to check when the player increases the game level.
  • GameLevel : Verse variable that indicates the current game level. 


Add the variable/constant declaration after the ScoreManagerDevice line:

    @editable
    CoinsPerLevel : int = 3

    @editable
    BonusTime : float = 5.0

    var CoinsCollected : int = 0

    var GameLevel : int = 1

Let's create a function named AddTime that will be used to add time in seconds to the Timer Device. Add the code below at the end of the Verse file:

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

This function gets the current time from the Timer Device using the GetActiveDuration function. The new Timer Device time is defined with the SetActiveDuration function, using as a parameter the result of the sum of the current time and the time to be added.

There is a function called Mod that returns the remainder of a division between integers. We will use Mod to increase the game level every 3 coins collected. To use the Mod function you need to include the Verse module:

using { /Verse.org/Verse}

The modifications related to the missing rules will be made in the HandleCoinPickedUp function which has to look like this:

    HandleCoinPickedUp(Agent:agent):void=

        ScoreManagerDevice.Activate(Agent)

        set CoinsCollected += 1

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

        SpawnCoin()


Every time a coin is collected, we use Mod to check if the amount of  CoinsCollected is a multiple of 3 (default value of CoinsPerLevel). If it is a multiple of 3 then the Mod result must be zero indicating that the game level has increased.

Notice that the Mod function uses [] instead of (). This is because Mod is a failable function.

The Verse code below is the final version of 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)

Save the file and compile the Verse code using the Verse > Build Verse Code option from the UEFN menu.

Select the collect game device that is on the level. In the Details tab, see that you can change the values of CoinsPerLevel and BonusTime to adjust the gameplay without having to recompile the Verse code: 



Save the level and start the session. See what is the highest score you can get.

Learning programming takes a lot of practice. This mini game is simple but it uses several essential concepts of the Verse language such as:

  • Variables and constants; 
  • Device references;
  • Subscribe functions in events;
  • Conversion of references using cast;
  • Creation of tags;

I hope this step-by-step guide for creating this mini game was useful for learning Verse. 

If you are an instructor, feel free to use this mini game as an activity for your students so they can discuss the Verse concepts used and improve this example.



Table of Contents Verse