Menu
CoddyTech

The Board

Lesson 11 of 18 in Coddy's Roblox Game: Endless Tower course.

An obby runs in rounds: a short wait in the lobby, then a new tower and a race to the top. Players need to see what is happening, so the lobby has a Board, a flat part facing the spawn.

Text on a part is a SurfaceGui holding a TextLabel. UDim2.fromScale(1, 1) makes the label fill the whole face, and TextScaled sizes the words to fit:

local gui = Instance.new("SurfaceGui")
gui.Parent = workspace.Lobby.Board

local label = Instance.new("TextLabel")
label.Size = UDim2.fromScale(1, 1)
label.TextScaled = true
label.Text = "Endless Tower"
label.Parent = gui

A countdown is a for loop that counts backwards with a step of -1, waiting a second each time:

for i = 5, 1, -1 do
	setBoard("Next tower in " .. i)
	task.wait(1)
end
challenge icon

Challenge

Medium
  1. Put a SurfaceGui on workspace.Lobby.Board holding a TextLabel named Status that fills it, with TextScaled on, white text on a dark background.
  2. Write setBoard(text), which sets the label's Text.
  3. Before building the tower, count down from Settings.Intermission to 1, showing Next tower in 3, Next tower in 2, ... and waiting a second each time. Then build the tower and start the lava as before.

Press Play and watch the board. Then Check.

Try it yourself

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local CollectionService = game:GetService("CollectionService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local Settings = require(game.ReplicatedStorage.Settings)

local stages = ServerStorage.Stages
local tower = nil
local lava = nil

print("Each tower has " .. Settings.StageCount .. " stages")

-- Every player gets Wins on the leaderboard
Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local wins = Instance.new("IntValue")
	wins.Name = "Wins"
	wins.Parent = leaderstats
end)

-- Anything tagged Kill ends a life
local function killOnTouch(hit)
	local humanoid = hit.Parent:FindFirstChild("Humanoid")
	if humanoid then
		humanoid.Health = 0
	end
end

-- A vanishing step fades soon after someone lands on it, then comes back
local function makeVanish(part)
	part.Touched:Connect(function(hit)
		if part:GetAttribute("Gone") or not hit.Parent:FindFirstChild("Humanoid") then
			return
		end
		part:SetAttribute("Gone", true)
		task.wait(Settings.VanishDelay)
		part.Transparency = 0.8
		part.CanCollide = false
		task.wait(Settings.VanishTime)
		part.Transparency = 0
		part.CanCollide = true
		part:SetAttribute("Gone", nil)
	end)
end

-- A laser slides to its Slide offset and back, forever
local function makeSlide(part)
	local info = TweenInfo.new(Settings.SlideTime, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, -1, true)
	local goal = { Position = part.Position + part:GetAttribute("Slide") }
	TweenService:Create(part, info, goal):Play()
end

-- A bounce pad throws whoever lands on it up into the air
local function bounce(hit)
	local root = hit.Parent:FindFirstChild("HumanoidRootPart")
	if root then
		root.AssemblyLinearVelocity = Vector3.new(0, Settings.BouncePower, 0)
	end
end

-- Spinners turn a little every frame
RunService.Heartbeat:Connect(function(dt)
	for _, spinner in CollectionService:GetTagged("Spinner") do
		if spinner:IsDescendantOf(workspace) then
			spinner:PivotTo(spinner:GetPivot() * CFrame.Angles(0, math.rad(Settings.SpinSpeed) * dt, 0))
		end
	end
end)

-- Turn on every obstacle in a stage, by its tags
local function setupStage(stage)
	for _, part in stage:GetDescendants() do
		if part:HasTag("Kill") then
			part.Touched:Connect(killOnTouch)
		end
		if part:HasTag("Vanish") then
			makeVanish(part)
		end
		if part:HasTag("Conveyor") then
			part.AssemblyLinearVelocity = part.CFrame.LookVector * Settings.BeltSpeed
		end
		if part:HasTag("Slider") then
			makeSlide(part)
		end
		if part:HasTag("Bounce") then
			part.Touched:Connect(bounce)
		end
	end
end

-- Any stage, at random
local function pickStage()
	local all = stages:GetChildren()
	return all[math.random(1, #all)]
end

-- Put a copy of a model on top of the tower; returns the copy and the new top
local function stack(template, bottom)
	local copy = template:Clone()
	local box, size = copy:GetBoundingBox()
	local lift = bottom - (box.Position.Y - size.Y / 2)
	copy:PivotTo(copy:GetPivot() + Vector3.new(0, lift, 0))
	copy.Parent = tower
	return copy, bottom + size.Y
end

-- Build a new random tower, bottom up
local function buildTower()
	tower = Instance.new("Model")
	tower.Name = "Tower"
	tower.Parent = workspace
	local top = 0
	for i = 1, Settings.StageCount do
		local stage, newTop = stack(pickStage(), top)
		top = newTop
		setupStage(stage)
	end
	stack(ServerStorage.Finish, top)
	return top
end

-- Lava rises from the ground to just under the top of the tower
local function startLava(top)
	lava = Instance.new("Part")
	lava.Name = "Lava"
	lava.Anchored = true
	lava.CanCollide = false
	lava.Size = Vector3.new(30, 2, 30)
	lava.Position = Vector3.new(0, -2, 0)
	lava.Color = Color3.fromRGB(255, 90, 20)
	lava.Material = Enum.Material.Neon
	lava.Parent = workspace
	lava.Touched:Connect(killOnTouch)
	local info = TweenInfo.new(top / Settings.LavaSpeed, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, 0, false, Settings.LavaDelay)
	TweenService:Create(lava, info, { Position = Vector3.new(0, top - 2, 0) }):Play()
end

local top = buildTower()
startLava(top)
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Roblox Game: Endless Tower