Menu
CoddyTech

Bảng chơi

Bài học 12 trên 21 trong khóa học Trò chơi Roblox: Tháp bất tận của Coddy.

Một trò chơi vượt chướng ngại vật diễn ra theo từng vòng: chờ một lát ở sảnh, sau đó là một tòa tháp mới và cuộc đua lên đỉnh. Người chơi cần biết chuyện gì đang diễn ra, vì vậy sảnh có một Board, một tấm phẳng hướng về phía điểm xuất hiện.

Văn bản trên một tấm là một SurfaceGui chứa TextLabel. UDim2.fromScale(1, 1) giúp nhãn phủ kín toàn bộ mặt tấm, còn TextScaled điều chỉnh cỡ chữ cho vừa:

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

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

Đếm ngược là một vòng lặp for đếm lùi với bước giảm 1, mỗi lần chờ một giây:

for i = 3, 1, -1 do
	print("Lift off in " .. i)
	task.wait(1)
end
challenge icon

Thử thách

Trung bình

Đếm ngược đến mỗi tòa tháp trên bảng ở sảnh.

  1. Đặt một SurfaceGui lên workspace.Lobby.Board, trong đó có một TextLabel boardLabel tên là Status, có kích thước UDim2.fromScale(1, 1) và bật TextScaled.
  2. Viết setBoard(text) để đặt boardLabel.Text.
  3. Trước khi xây tòa tháp, đếm ngược i từ Settings.Intermission xuống 1: setBoard("Next tower in " .. i), rồi gọi task.wait(1).

Nhấn Chơi: bảng đếm ngược từ 5, rồi tòa tháp xuất hiện. Sau đó nhấn Kiểm tra.

Tự làm thử

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")

-- Mỗi người chơi đều có Wins trên bảng xếp hạng
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)

-- Bài học 12: Đặt The Board ở đây

-- Bất cứ thứ gì gắn thẻ Kill đều khiến người chơi mất một mạng
local function killOnTouch(hit)
	local humanoid = hit.Parent:FindFirstChild("Humanoid")
	if humanoid then
		humanoid.Health = 0
	end
end

-- Bậc thang biến mất mờ dần ngay sau khi có người đáp xuống, rồi xuất hiện trở lại
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

-- Tia laser trượt đến vị trí lệch Slide rồi quay lại, lặp mãi
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

-- Tấm bật nhảy hất người đáp xuống lên không trung
local function bounce(hit)
	local root = hit.Parent:FindFirstChild("HumanoidRootPart")
	if root then
		root.AssemblyLinearVelocity = Vector3.new(0, Settings.BouncePower, 0)
	end
end

-- Các vật xoay quay một chút sau mỗi khung hình
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)

-- Kích hoạt mọi chướng ngại vật trong một màn chơi dựa trên thẻ của chúng
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

-- Chọn ngẫu nhiên một màn chơi bất kỳ
local function pickStage()
	local all = stages:GetChildren()
	return all[math.random(1, #all)]
end

-- Đặt một bản sao của mô hình lên đỉnh tháp; trả về bản sao và độ cao đỉnh mới
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

-- Xây một tòa tháp ngẫu nhiên mới từ dưới lên
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

-- Dung nham dâng từ mặt đất lên ngay dưới đỉnh tháp
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

startLava(buildTower())

Tất cả bài học trong Trò chơi Roblox: Tháp bất tận

Tự luyện tập: Playground Roblox