Menu
CoddyTech

Lên đến đỉnh

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

Miếng đệm FinishPad màu vàng trên đỉnh tháp kết thúc cuộc leo trèo: bạn thắng và được đưa về sảnh. stack trả về Finish mà nó đã đặt, vậy nên hãy kết nối sự kiện Touched của miếng đệm ngay tại đó.

Touched đưa cho bạn chi thể đã chạm vào. Parent của nó là nhân vật, còn Players:GetPlayerFromCharacter trả về Player sở hữu nhân vật đó, hoặc nil nếu là thứ khác:

local player = Players:GetPlayerFromCharacter(hit.Parent)
if player then
	print(player.Name .. " stepped on the pad")
end

Touched kích hoạt một lần cho mỗi chi thể, nên nếu không cẩn thận, một lần tiếp đất có thể khiến người chơi thắng ba hoặc bốn lần. Hãy lưu những người đã hoàn thành vòng này vào một bảng, và chỉ cho mỗi người chơi thắng một lần:

local finished = {}

if finished[player] then
	return
end
finished[player] = true

Bảng có thể dùng Player làm khóa, nên finished[player] là mục của người chơi đó. Vòng mới sẽ xóa sạch bảng để mọi người có thể thắng lần nữa.

challenge icon

Thử thách

Trung bình

Tấm đệm vàng trên đỉnh sẽ giúp bạn chiến thắng.

  1. Thêm local lobbySpawn = workspace.Lobby.SpawnLocation và local finished = {}; startRound xóa hết nội dung của finished.
  2. Viết reachTop(hit): dừng lại nếu Players:GetPlayerFromCharacter(hit.Parent) không trả về người chơi chưa hoàn thành. Đánh dấu người chơi đó, cộng 1 vào Wins, print(player.Name .. " reached the top"), di chuyển hit.Parent lên vị trí cao hơn lobbySpawn 4 stud.
  3. Trong buildTower, kết nối FinishPad.Touched với hàm đó.

Nhấn Chơi và chạm đến tấm đệm vàng: bạn sẽ thắng và đáp xuống sảnh. 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 towerStages = {}
local lava = nil

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

-- Mỗi người chơi 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ảng thông báo trong sảnh chờ
local gui = Instance.new("SurfaceGui")
gui.Parent = workspace.Lobby.Board

local boardLabel = Instance.new("TextLabel")
boardLabel.Name = "Status"
boardLabel.Size = UDim2.fromScale(1, 1)
boardLabel.BackgroundColor3 = Color3.fromRGB(25, 25, 35)
boardLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
boardLabel.TextScaled = true
boardLabel.Text = "Endless Tower"
boardLabel.Parent = gui

local function setBoard(text)
	boardLabel.Text = text
end

-- Chạm vào bất kỳ vật nào gắn thẻ Kill sẽ 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 sẽ mờ đi 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 theo 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 nả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 quay xoay một chút ở 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 tầng theo 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 tầng bất kỳ
local function pickStage()
	local all = stages:GetChildren()
	return all[math.random(1, #all)]
end

-- Đặt bản sao của một 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

-- Bài học 14: Chạm tới đỉnh nằm ở đây

-- 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
	towerStages = {}
	local top = 0
	for i = 1, Settings.StageCount do
		local stage, newTop = stack(pickStage(), top)
		top = newTop
		setupStage(stage)
		towerStages[i] = stage
	end
	stack(ServerStorage.Finish, top)
	return top
end

-- Dung nham dâng từ mặt đất lên sát đỉ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

local function startRound()
	local top = buildTower()
	startLava(top)
	for _, player in Players:GetPlayers() do
		if player.Character then
			player.Character:PivotTo(towerStages[1].Start.CFrame + Vector3.new(0, 4, 0))
		end
	end
end

-- Một vòng chơi
for i = Settings.Intermission, 1, -1 do
	setBoard("Next tower in " .. i)
	task.wait(1)
end
startRound()
for i = Settings.RoundLength, 1, -1 do
	setBoard("Climb! " .. i .. " seconds left")
	task.wait(1)
end

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