Events and Game Loops

Overview

Traditional video games work by creating a game loop with code that repeats 30-60 times per second. This type of games has a clear start and end, and usually only one player. It works by checking all conditions — is a player touching an enemy? Collecting a coin? — every single loop. This can create a lot of repeated computations, and eventually slow down a game. Multiplayer online games have information coming from multiple sources, players connecting at different times, and need to pass that information back and forth over everyone’s internet connections. Putting all code on a game loop would not be feasible here, so instead these games tend to rely more on events, which are a smaller subset of expected behavior that the engine is watching for. You can connect functions to these events, so that they are called whenever one happens.

Threads

Another way to avoid creating long procedures that can tie the computer up at different steps is to use multiple threads. This is a way of setting up a sequence of code that starts executes, but allows the rest of the game code to continue working without waiting for it to finish. We won’t cover multithreaded program design in this course, but you can see some examples of how it works on the Core API Examples page.

Using Events in Core

Core Object Events

Each CoreObject has its own set of Events that represent behaviors that you might want to respond to in a script. Player Events in the Core APIEach event has a Return Type. This will be information that you can use in your code, as an input to your function. For example, all of the Player events return a Player first. You can use this to get a reference to the player involved in the event.

Connecting Functions to Events

Method One: Create a named function

  1. Create a function. It should have parameters for the Return Type.
  2. Use the EventName:Connect(functionName) function to connect it to the event.

Example using the Game.playerJoinedEvent :

function greetPlayersAsTheyJoin(player)     
    print("Hello, " .. player.name .. "!") 
end 

Game.playerJoinedEvent:Connect(greetPlayersAsTheyJoin) Code language: Lua (lua)

Method Two: Create an anonymous function

Since you will never actually call the function you make yourself (that’s the events job), the only thing its name does is allow you to connect it to the event.

You can combine these into one step by defining an anonymous function inside the argument of the Connect() function.

Example:

Game.playerJoinedEvent:Connect(function (player) print("Hello, " .. player.name .. "!") end)Code language: Lua (lua)
-- Another form where the anonymous function is not in a single line
Game.playerJoinedEvent:Connect(function (player)
    print("Hello, " .. player.name .. "!")
end)Code language: Lua (lua)

Create Your Own Event

You can also create your own events, that fire when specific conditions are met, using the Event.Broadcast("YourEventName") function. This can allow you to trigger code that is on separate scripts that are waiting for an event. To receive the event, you must use the Events.Connect method.

In the other script, you will receive the message like this:

Events.Connect("YourEventName", function()
    print("Received YourEventName")
end)Code language: JavaScript (javascript)

Broadcasted messages have a limit of 128 characters, including the name of the event. Try to give appropriate names to your event but keep it short.

You can also send data through events. For example, you can use the line `Events.Broadcast(“DamagePlayer”, { enemy=”Blob”, damage=”10″ })` to send information and receive it in another script:

Events.Connect("DamagePlayer", function(data)
    print(data.enemy.." deals "..data.damage.." to the player.")
end)Code language: JavaScript (javascript)

To check if those conditions are met, however, you will most likely need a repeating game loop.

Game Loops with Tick

The Tick() function does allow you to have code that executes 60 times per second! You can use this, coupled with an if statement, to broadcast an event.

function countAlivePlayers(list)
    local nb = 0
    for _,p in ipairs(list) do
        if p:IsValid and not p.isDead then
            nb = nb + 1
        end
    end
    return nb
end

local nbAlivePlayersAtLastFrame = 0
function Tick()
    local players = Game.GetPlayers()

    local nbAlive = countAlivePlayers(players)
    if nbAlive ~= nbAlivePlayersAtLastFrame then
        Events.Broadcast("UpdateNbAlivePlayers", nbAlive)
    end
    nbAlivePlayersAtLastFrame = nbAlive
endCode language: Lua (lua)
Post a comment

Leave a Comment

Scroll to Top