📝 github.com/codeninjasgg/roblox-royale-camp/edit/master/pages/Day 3.md

Day 3

Overview 👀

Today we will utilize BindableEvents and script out the logic for our game's timer.

Follow Along! 👍

First, we will download today's file here. Once downloaded, let's open it up in Roblox studio and begin our quest for today.

Fun Quiz 🧠

Here are some quiz questions that we will be able to answer as we complete today's instructions.

What does 'WaitForChild' do? The 'WaitForChild' method is used by variables that represent folders in our explorer. This method allows us to reach into the folder that it's instance represents and pick a file programmatically.
What does 'Connect' do? The 'Connect' method takes a function as its argument and calls it once the event is resolved (completed).
What does 'Wait' do? The 'Wait' method stops the script from continuing until the event has been resolved (completed).

Then we will work on programming by following these instructions.

When we are done, our scripts should resemble the following samples:

ServerScriptService > GameManager

-- Services
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
 
-- Module Scripts
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
 
-- Events
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
 
while true do
    repeat
        wait(gameSettings.intermissionDuration)
        print("Restarting intermission")
    until Players.NumPlayers >= gameSettings.minimumPlayers
 
    print("Intermission over")
    wait(gameSettings.transitionTime)
    
    matchManager.prepareGame()
    -- Placeholder wait for the length of the game.
    matchEnd.Event:Wait()
 
end

ServerStorage > ModuleScripts > MatchManager

local MatchManager = {}
 
-- Services
local ServerStorage = game:GetService("ServerStorage")
 
-- Module Scripts
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local timer = require(moduleScripts:WaitForChild("Timer"))
 
-- Events
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
 
-- Creates a new timer object to be used to keep track of match time. 
local myTimer = timer.new()
 
-- Local Functions
local function timeUp()
    print("Time is up!")
end
 
local function startTimer()
    print("Timer started")
    myTimer:start(gameSettings.matchDuration)
    myTimer.finished:Connect(timeUp)    
end
 
-- Module Functions
function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
end
 
matchStart.Event:Connect(startTimer)
 
return MatchManager

ServerStorage > ModuleScripts > Timer

local Timer = {}
Timer.__index = Timer
 
function Timer.new()
    local self = setmetatable({}, Timer)
 
    self._finishedEvent = Instance.new("BindableEvent")
    self.finished = self._finishedEvent.Event
    
    self._running = false
    self._startTime = nil
    self._duration = nil
    
    return self
end
 
function Timer:start(duration)
    if not self._running then
        local timerThread = coroutine.wrap(function()
            self._running = true
            self._duration = duration
            self._startTime = tick()
            while self._running and tick() - self._startTime < duration do
                wait()
            end
            local completed = self._running
            self._running = false
            self._startTime = nil
            self._duration = nil
            self._finishedEvent:Fire(completed)
        end)
        timerThread()
    else
        warn("Warning: timer could not start again as it is already running.")
    end
end
 
function Timer:getTimeLeft()
    if self._running then
        local now = tick()
        local timeLeft = self._startTime + self._duration - now
        if timeLeft < 0 then
            timeLeft = 0
        end
        return timeLeft
    else
        warn("Warning: could not get remaining time, timer is not running.")
    end
end
 
function Timer:isRunning()
    return self._running
end
 
function Timer:stop()
    self._running = false
end
 
return Timer

A complete example project of the scripting we have done in class today can be found here.

Optional Homework 📄

Read the following articles to acheive a full understanding of what we are working on for day 4.


See you tomorrow for day 4!