نقاط التحقق
الدرس 16 من 18 في دورة لعبة Roblox: البرج اللانهائي على Coddy.
السقوط حتى الموت في المرحلة 5 والبدء من الأسفل أمر قاسٍ. باستخدام نقاط التفتيش، يبدأ اللاعب الذي يموت مجددًا من آخر مرحلة وصل إليها، وهو ما يعرفه Stage بالفعل.
تُطلق كل شخصية جديدة حدث CharacterAdded للاعب. يضعها Roblox أولًا عند نقطة ظهور، لذا انتظر لحظة، ثم انقلها:
player.CharacterAdded:Connect(function(character)
task.wait()
local checkpoint = towerStages[stage.Value]
if checkpoint then
character:PivotTo(checkpoint.Start.CFrame + Vector3.new(0, 4, 0))
end
end)قبل أن يصل اللاعب إلى أي مرحلة، تكون towerStages[0] بقيمة nil، لذا يظهر في الردهة كالمعتاد. يعود الفائزون إلى الردهة، وينبغي أن يبقوا هناك.
تغيّر الحمم البركانية أمرًا واحدًا. فالمرحلة التي غطتها لا تُعدّ نقطة تفتيش: اللاعب الذي يُعاد إليها يموت مجددًا فورًا، مرارًا وتكرارًا، حتى تتجاوز الحمم المرحلة التالية. قارن موضع Start للمرحلة بأعلى مستوى للحمم، واترك اللاعب الذي تقع نقطة تفتيشه تحتها في الردهة حتى الجولة التالية:
local covered = checkpoint and lava and checkpoint.Start.Position.Y < lava.Position.Y + lava.Size.Y / 2التحدي
صعبفي PlayerAdded، بعد إنشاء إحصاءات لوحة المتصدرين، اربط CharacterAdded الخاص باللاعب. انتظر لحظة باستخدام task.wait()، ثم إذا كان towerStages[stage.Value] موجودًا، ولم تغطِّ الحمم نقطة Start الخاصة به، ولم يُنهِ اللاعب هذه الجولة، فانقل الشخصية إلى ارتفاع 4 studs فوق نقطة Start في تلك المرحلة.
اضغط على Play، وتسلق مرحلة، ثم اقفز منها. بعد ذلك، ابقَ عليها حتى تصل الحمم. ثم اضغط على Check.
جرّب بنفسك
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 lobbySpawn = workspace.Lobby.SpawnLocation
local tower = nil
local towerStages = {}
local lava = nil
local finished = {}
print("Each tower has " .. Settings.StageCount .. " stages")
-- يحصل كل لاعب على Wins وStage في لوحة المتصدرين
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
local stage = Instance.new("IntValue")
stage.Name = "Stage"
stage.Parent = leaderstats
end)
-- اللوحة في الردهة
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
-- أي شيء يحمل الوسم Kill ينهي حياة اللاعب
local function killOnTouch(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
humanoid.Health = 0
end
end
-- تتلاشى الدرجة المختفية بعد وقت قصير من هبوط أحد عليها، ثم تعود للظهور
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
-- ينزلق الليزر إلى موضع الإزاحة Slide ثم يعود، بلا توقف
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
-- تقذف منصة القفز من يهبط عليها إلى أعلى في الهواء
local function bounce(hit)
local root = hit.Parent:FindFirstChild("HumanoidRootPart")
if root then
root.AssemblyLinearVelocity = Vector3.new(0, Settings.BouncePower, 0)
end
end
-- تدور العناصر الدوّارة قليلًا في كل إطار
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)
-- فعّل كل عقبة في المرحلة بحسب وسومها
local function setupStage(stage, index)
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
-- يُحتسب الوصول إلى Start الخاصة بمرحلة ما في لوحة المتصدرين
stage.Start.Touched:Connect(function(hit)
local player = Players:GetPlayerFromCharacter(hit.Parent)
if player and player.leaderstats.Stage.Value < index then
player.leaderstats.Stage.Value = index
end
end)
end
-- مرحلة عشوائية
local function pickStage()
local all = stages:GetChildren()
return all[math.random(1, #all)]
end
-- ضع نسخة من النموذج فوق البرج؛ تُرجع النسخة والارتفاع الجديد لقمة البرج
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
-- قمة البرج: فوز، ثم عودة إلى الردهة
local function reachTop(hit)
local player = Players:GetPlayerFromCharacter(hit.Parent)
if not player or finished[player] then
return
end
finished[player] = true
player.leaderstats.Wins.Value += 1
print(player.Name .. " reached the top")
hit.Parent:PivotTo(lobbySpawn.CFrame + Vector3.new(0, 4, 0))
end
-- أنشئ برجًا عشوائيًا جديدًا من الأسفل إلى الأعلى
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, i)
towerStages[i] = stage
end
local finish = stack(ServerStorage.Finish, top)
finish.FinishPad.Touched:Connect(reachTop)
return top
end
-- ترتفع الحمم من الأرض حتى أسفل قمة البرج مباشرةً
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()
finished = {}
for _, player in Players:GetPlayers() do
player.leaderstats.Stage.Value = 0
end
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
local function endRound()
for _, player in Players:GetPlayers() do
if player.Character and not finished[player] then
player.Character:PivotTo(lobbySpawn.CFrame + Vector3.new(0, 4, 0))
end
player.leaderstats.Stage.Value = 0
end
tower:Destroy()
lava:Destroy()
towerStages = {}
end
-- حلقة الجولات
while true do
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
endRound()
end
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.