Danh sách thú cưng
Bài học 14 trên 20 trong khóa học Trò chơi Roblox: mô phỏng thú cưng của Coddy.
Người chơi cần thấy thú cưng của mình. HUD có một ScrollingFrame tên Inventory với UIListLayout bên trong. Thành phần này xếp các mục bên trong lần lượt từ trên xuống dưới theo thứ tự LayoutOrder. Mỗi thú cưng có một TextButton ở đó. AutomaticCanvasSize của nó là Y, nên vùng hiển thị tự mở rộng theo danh sách và người chơi có nhiều thú cưng có thể cuộn danh sách.
Máy khách tạo danh sách từ thư mục Pets mà máy chủ lưu trong dữ liệu của người chơi, rồi tạo lại danh sách khi thư mục thay đổi: ChildAdded khi một thú cưng nở, và GetAttributeChangedSignal("Equipped") của từng thú cưng khi thú cưng được trang bị hoặc tháo ra.
pet:GetAttributeChangedSignal("Equipped"):Connect(showPets)Tạo lại danh sách nghĩa là xóa các nút cũ trước, để danh sách không bao giờ hiển thị một thú cưng hai lần.
Thử thách
Trung bìnhHiển thị thú cưng trên màn hình, mỗi thú cưng có một nút.
- Trong
PetClient:local pets = me:WaitForChild("Pets"). - Viết
showPets(): xóa các TextButton tronghud.Inventory, rồi thêm một nút cho mỗi thú cưng, hiển thịCat (out)khi thú cưng có thuộc tính Equipped,Catkhi không có. - Gọi hàm này ngay bây giờ, khi có sự kiện
pets.ChildAddedvà khi mỗi thú cưng có sự kiệnGetAttributeChangedSignal("Equipped"), cho cả thú cưng hiện có lẫn thú cưng mới.
Nhấn Chơi rồi ấp trứng: Cat (out) sẽ hiển thị trong danh sách. Sau đó nhấn Kiểm tra.
Tự làm thử
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local RunService = game:GetService("RunService")
local Settings = require(game.ReplicatedStorage.Settings)
local remotes = game.ReplicatedStorage.Remotes
local piles = workspace.Piles
local petParts = workspace.PetParts
local pileSpot = {} -- Mỗi đống xu -> vị trí đặt đống xu đó
local lastHit = {} -- Mỗi người chơi -> thời điểm họ đánh lần gần nhất
print("A Meadow pile gives " .. Settings.PileValue .. " coins")
-- Settings.Pets theo tên
local petInfo = {}
for _, info in Settings.Pets do
petInfo[info.Name] = info
end
-- Thú cưng: một StringValue trong thư mục Pets của người chơi, lưu tên
-- và có độ hiếm, sức mạnh làm thuộc tính
local function givePet(player, name, equipped)
local info = petInfo[name]
local pet = Instance.new("StringValue")
pet.Name = "Pet"
pet.Value = name
pet:SetAttribute("Rarity", info.Rarity)
pet:SetAttribute("Power", info.Power)
pet:SetAttribute("Equipped", equipped)
pet.Parent = player.Pets
return pet
end
-- Số thú cưng mà người chơi đang cho ra ngoài
local function equippedCount(player)
local count = 0
for _, pet in player.Pets:GetChildren() do
if pet:GetAttribute("Equipped") then
count += 1
end
end
return count
end
-- Sức mạnh thú cưng cộng thêm vào mỗi cú đánh của người chơi
local function petPower(player)
local power = 0
for _, pet in player.Pets:GetChildren() do
if pet:GetAttribute("Equipped") then
power += pet:GetAttribute("Power")
end
end
return power
end
-- Mỗi người chơi đều có Coins 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 coins = Instance.new("IntValue")
coins.Name = "Coins"
coins.Parent = leaderstats
-- Những thú cưng họ sở hữu
local pets = Instance.new("Folder")
pets.Name = "Pets"
pets.Parent = player
end)
-- Một đống xu tại một vị trí: bản sao của ServerStorage.CoinPile, có lượng máu
-- và giá trị làm thuộc tính
local function spawnPile(spot)
local pile = ServerStorage.CoinPile:Clone()
pile.Position = spot.Position
pile:SetAttribute("MaxHealth", Settings.PileHealth)
pile:SetAttribute("Health", Settings.PileHealth)
pile:SetAttribute("Value", Settings.PileValue)
pile.HealthGui.Label.Text = pile:GetAttribute("Health") .. "/" .. pile:GetAttribute("MaxHealth")
pileSpot[pile] = spot
pile.Parent = piles
return pile
end
-- Mỗi cú đánh trừ 1 cộng với sức mạnh thú cưng của người chơi khỏi lượng máu của đống xu;
-- Khi còn 0 máu, đống xu vỡ và trả số xu tương ứng với giá trị của nó
local function hitPile(player, pile)
local health = pile:GetAttribute("Health") - (1 + petPower(player))
if health > 0 then
pile:SetAttribute("Health", health)
pile.HealthGui.Label.Text = health .. "/" .. pile:GetAttribute("MaxHealth")
return
end
player.leaderstats.Coins.Value += pile:GetAttribute("Value")
local spot = pileSpot[pile]
pileSpot[pile] = nil
pile:Destroy()
-- Vài giây sau, một đống xu mới xuất hiện ở cùng vị trí
task.delay(Settings.RespawnTime, spawnPile, spot)
end
-- Mỗi vị trí trong Meadow có một đống xu
for _, spot in workspace.Zones.Meadow.Spawns:GetChildren() do
spawnPile(spot)
end
-- Máy khách yêu cầu đánh một đống xu. Đừng tin máy khách: bất kỳ ai cũng có thể gửi
-- sự kiện từ xa này với dữ liệu bất kỳ, từ bất kỳ đâu, nhanh tùy ý.
remotes.Hit.OnServerEvent:Connect(function(player, pile)
-- đống xu có thật
if typeof(pile) ~= "Instance" or pile.Parent ~= piles then
return
end
-- trong tầm đánh
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if not root or (root.Position - pile.Position).Magnitude > Settings.Reach then
return
end
-- không quá nhanh
local now = time()
if lastHit[player] and now - lastHit[player] < Settings.HitCooldown then
return
end
lastHit[player] = now
hitPile(player, pile)
end)
-- Lượt chọn có trọng số: Chance của mỗi thú cưng (trên 100) quyết định phần của nó trên dải xác suất
local function rollPet()
local roll = math.random() * 100
for _, info in Settings.Pets do
roll -= info.Chance
if roll <= 0 then
return info.Name
end
end
return Settings.Pets[1].Name
end
-- Ấp trứng: dùng lời nhắc ở quả trứng và trả bằng xu
workspace.Egg.ProximityPrompt.Triggered:Connect(function(player)
local coins = player.leaderstats.Coins
if coins.Value < Settings.EggPrice then
return
end
coins.Value -= Settings.EggPrice
local name = rollPet()
-- cho thú cưng ra ngay nếu còn chỗ
local pet = givePet(player, name, equippedCount(player) < Settings.MaxEquipped)
print(player.Name .. " hatched a " .. name)
end)
-- Thú cưng đang được trang bị đi theo chủ: mỗi con có một bộ phận trong thế giới, luôn nằm
-- thành một hàng phía sau người chơi trong mỗi khung hình
local petModels = {} -- mỗi thú cưng -> bộ phận tương ứng trong thế giới trò chơi
RunService.Heartbeat:Connect(function()
for _, player in Players:GetPlayers() do
local root = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
local pets = player:FindFirstChild("Pets")
local slot = 0
for _, pet in pets and pets:GetChildren() or {} do
local model = petModels[pet]
if pet:GetAttribute("Equipped") and root then
slot += 1
if not model then
model = ServerStorage.PetModels[pet.Value]:Clone()
model.Parent = petParts
petModels[pet] = model
end
model.CFrame = root.CFrame * CFrame.new((slot - 2) * 3, -1.5, 4)
end
end
end
end)
Tất cả bài học trong Trò chơi Roblox: mô phỏng thú cưng
3Trứng và thú cưng
Ấp trứngTự luyện tập: Playground Roblox