Hiển thị thời gian chờ
Bài học 9 trên 25 trong khóa học Trò chơi Roblox: Đấu trường của Coddy.
Người chơi cần biết khi nào một kỹ năng sẵn sàng. HUD có một khung Cooldowns với một nhãn cho mỗi kỹ năng, và máy chủ đã lưu DashReadyAt trên người chơi để client có thể đọc.
Thời gian đếm ngược thay đổi theo từng khung hình, nên client vẽ lại nội dung trên RunService.Heartbeat, sự kiện này chạy một lần mỗi khung hình. string.format giữ lại một chữ số thập phân:
string.format("%s %.1f", "Dash", 2.345) --> "Dash 2.3"Client chỉ hiển thị thời gian hồi chiêu. Phần kiểm tra của máy chủ từ bài học trước vẫn quyết định.
Thử thách
Trung bìnhHiển thị thời gian hồi chiêu của từng kỹ năng trên HUD.
- Trong
BattleClient: RunService vàlocal hud = script.Parent. - Ở mỗi
RunService.Heartbeat, với từng name tronglocal shown = { "Dash" }:left = (me:GetAttribute(name .. "ReadyAt") or 0) - workspace:GetServerTimeNow(). - Đặt
hud.Cooldowns[name].Textthànhstring.format("%s %.1f", name, left)khileft > 0, nếu không thì đặt thànhname .. " ready".
Nhấn Chơi rồi nhấn Q: nhãn đếm ngược đến Dash ready. Sau đó nhấn Kiểm tra.
Tự làm thử
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)
local remotes = game.ReplicatedStorage.Remotes
local lastSwing = {} -- player -> thời điểm vung kiếm gần nhất
-- Hoạt ảnh vung kiếm có sẵn của Roblox
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"
print("Swords deal " .. Settings.SwordDamage .. " damage")
-- Một lần vung kiếm: chạy hoạt ảnh, rồi đánh trúng mọi người trong vùng phía trước bạn
local function swing(player)
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if not root or character.Humanoid.Health <= 0 then
return
end
local now = time()
if lastSwing[player] and now - lastSwing[player] < Settings.SwingCooldown then
return
end
lastSwing[player] = now
character.Humanoid.Animator:LoadAnimation(slash):Play()
-- Vùng phía trước bạn, không bao gồm cơ thể bạn
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local box = root.CFrame * CFrame.new(0, 0, -3)
local hit = {} -- Mỗi humanoid chỉ trúng đòn một lần trong mỗi lần vung kiếm
for _, part in workspace:GetPartBoundsInBox(box, Settings.HitboxSize, params) do
local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
if humanoid and not hit[humanoid] then
hit[humanoid] = true
humanoid:TakeDamage(Settings.SwordDamage)
print(humanoid.Parent.Name .. " is at " .. humanoid.Health)
end
end
end
-- Các kỹ năng theo tên và tác dụng của từng kỹ năng
local abilities = {}
-- Thiết bị của người chơi điều khiển nhân vật, nên thao tác lướt diễn ra trên thiết bị đó
function abilities.Dash(player)
remotes.Ability:FireClient(player, "Dash")
end
-- Máy khách yêu cầu kỹ năng theo tên. Máy chủ kiểm tra: kỹ năng có tồn tại,
-- người chơi còn sống và thời gian hồi chiêu đã hết. Thời điểm kỹ năng sẵn sàng trở lại
-- là một thuộc tính của người chơi, để màn hình của họ có thể hiển thị.
remotes.Ability.OnServerEvent:Connect(function(player, name)
if typeof(name) ~= "string" or not abilities[name] then
return
end
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if not root or character.Humanoid.Health <= 0 then
return
end
local now = workspace:GetServerTimeNow()
if now < (player:GetAttribute(name .. "ReadyAt") or 0) then
return
end
player:SetAttribute(name .. "ReadyAt", now + Settings.Cooldowns[name])
abilities[name](player, character, root)
end)
-- Mỗi lần hồi sinh, người chơi nhận một thanh kiếm
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function()
local sword = ServerStorage.Sword:Clone()
sword.Parent = player.Backpack
sword.Activated:Connect(function()
swing(player)
end)
end)
end)
-- Hình nộm tập luyện: thanh máu thay đổi theo lượng máu, và khi bị đánh bại,
-- Hình nộm xuất hiện lại sau chốc lát, với bản sao mới ở đúng vị trí cũ
local function setupDummy(dummy)
local humanoid = dummy.Humanoid
humanoid.HealthChanged:Connect(function(health)
dummy.HealthBar.Back.Fill.Size = UDim2.fromScale(health / humanoid.MaxHealth, 1)
end)
humanoid.Died:Connect(function()
local spot = dummy:GetPivot()
task.wait(0.5)
dummy:Destroy()
task.wait(Settings.DummyRespawn)
local fresh = ServerStorage.Dummy:Clone()
fresh:PivotTo(spot)
fresh.Parent = workspace
setupDummy(fresh)
end)
end
setupDummy(workspace.Dummy)
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Trò chơi Roblox: Đấu trường
2Máy khách và máy chủ
Gửi yêu cầu đến máy chủTự luyện tập: Playground Roblox