בנה מגדל
שיעור 6 מתוך 18 בקורס משחק Roblox: הגנת מגדלים של Coddy.
עכשיו הצד של השחקן. DefenseClient הוא LocalScript בתוך ה־HUD, מסוג ScreenGui ש־Roblox מעתיקה למסך של כל שחקן. מסגרת Shop של ה־HUD מכילה TextButton לכל מגדל, ששמו כשם המגדל. אירוע Activated של כפתור מופעל כשלוחצים עליו או מקישים עליו:
button.Activated:Connect(function()
selected = button.Name
end)לאחר מכן, לחיצה על אחד המשטחים האפורים בונה עליו את המגדל שנבחר. הלקוח קורא את הלחיצה מהעכבר (me:GetMouse(), האירוע Button1Down שלו וה־Target שלו, החלק שמתחת לסמן), אבל הוא לא יכול לבנות דבר בעצמו: המגדלים נמצאים בשרת. הוא מבקש זאת באמצעות RemoteEvent Remotes.Place:
-- לקוח
remotes.Place:FireServer(pad, "Archer")
-- שרת: Roblox מוסיף קודם את השחקן
remotes.Place.OnServerEvent:Connect(function(player, pad, kind)
end)דגמי המגדלים ממתינים בתוך ServerStorage.Towers; השרת משכפל אחד מהם אל המשטח.
אתגר
בינוניב־DefenseClient:
- קבל את
Players, אתSettings(עםWaitForChild), אתlocal remotes = game.ReplicatedStorage:WaitForChild("Remotes"), אתlocal me = Players.LocalPlayerואתlocal hud = script.Parent. - עבור כל TextButton ב־
hud.Shop, הגדר את הטקסט שלו לשם המגדל ולמחיר שלו (Archer $60), וב־Activatedשמור אותו ב־selected. - בעת
Button1Downשל העכבר, אם המטרה נמצאת ב־workspace.Padsונבחר מגדל, הפעל אתremotes.Placeעם המשטח ועם שם המגדל.
ב־DefenseServer: הוסף את local remotes ואת local towers = workspace.Towers, כתוב את placeTower(pad, kind) (שכפל, העבר באמצעות PivotTo אל ה־CFrame של המשטח כשהוא מוגבה במחצית גובה המשטח ועוד 1, והגדר את ההורה ל־towers), וחבר אליו את remotes.Place.OnServerEvent.
לחץ על Play, בחר מגדל ולחץ על משטח. לאחר מכן לחץ על Check.
נסו בעצמכם
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)
local enemies = workspace.Enemies
print("The base can take " .. Settings.BaseHealth .. " hits")
-- נקודות הציון, לפי הסדר (שמותיהן 1, 2, 3...)
local waypoints = workspace.Path.Waypoints:GetChildren()
table.sort(waypoints, function(a, b)
return tonumber(a.Name) < tonumber(b.Name)
end)
-- הבריאות של הבסיס, כתכונה של workspace: כל לקוח יכול לקרוא אותה
workspace:SetAttribute("BaseHealth", Settings.BaseHealth)
-- כל שחקן מקבל Money בלוח המובילים
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local money = Instance.new("IntValue")
money.Name = "Money"
money.Value = Settings.StartMoney
money.Parent = leaderstats
end)
-- אויב הגיע לבסיס
local function damageBase(amount)
local health = math.max(0, workspace:GetAttribute("BaseHealth") - amount)
workspace:SetAttribute("BaseHealth", health)
end
-- הולך עם אויב לאורך המסלול. MoveTo מוותר אחרי 8 שניות ומדווח על כך
-- (MoveToFinished עם false), ולכן שולחים אויב איטי שוב עד שהוא מגיע.
local function walkPath(enemy)
local humanoid = enemy.Humanoid
for i = 2, #waypoints do
repeat
humanoid:MoveTo(waypoints[i].Position)
until humanoid.MoveToFinished:Wait() or not enemy.Parent
if not enemy.Parent then
return
end
end
-- הוא הגיע לבסיס
damageBase(Settings.Enemies[enemy.Name].Damage)
enemy:Destroy()
end
-- אויב חדש בשער, מתקדם לאורך המסלול
local function spawnEnemy(kind)
local enemy = ServerStorage.Enemies[kind]:Clone()
-- מוצב ממש מעל נקודת הציון הראשונה
enemy:PivotTo(waypoints[1].CFrame + Vector3.new(0, 5, 0))
local info = Settings.Enemies[kind]
enemy.Humanoid.MaxHealth = info.Health
enemy.Humanoid.Health = info.Health
enemy.Humanoid.WalkSpeed = info.Speed
enemy.Parent = enemies
task.spawn(walkPath, enemy)
return enemy
end
-- גל אחד: האויבים שלו בזה אחר זה, ואז מחכים עד שכולם ייעלמו
local function runWave(list)
for _, kind in list do
spawnEnemy(kind)
task.wait(Settings.SpawnGap)
end
while #enemies:GetChildren() > 0 do
task.wait(0.2)
end
end
-- הגלים, כל אחד אחרי הפסקה
for i, list in Settings.Waves do
task.wait(Settings.WaveBreak)
runWave(list)
end
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.