Menu
CoddyTech
flag Ar iconالعربيةdown icon

ابنِ برجًا

الدرس 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؛ ويُنشئ الخادم نسخة منها على المنصة.

challenge icon

التحدي

متوسط

في DefenseClient:

  1. احصل على Players وSettings (باستخدام WaitForChild) وlocal remotes = game.ReplicatedStorage:WaitForChild("Remotes") وlocal me = Players.LocalPlayer وlocal hud = script.Parent.
  2. لكل زر TextButton في hud.Shop، اضبط نصه ليعرض اسم البرج وسعره (Archer $60)، وعند Activated احفظه في selected.
  3. عند 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
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس لعبة Roblox: الدفاع عن الأبراج