الاندفاع عند الضغط على Q
الدرس 6 من 20 في دورة لعبة Roblox: ساحات القتال على Coddy.
تبدأ القدرات على جهاز اللاعب. يُعدّ BattleClient LocalScript في HUD، ويربط ContextActionService الإجراء بالمفاتيح، كما أن الوسيط الثالث true يُظهر له زرًا على شاشة الهاتف أيضًا:
ContextActionService:BindAction("Dash", use, true, Enum.KeyCode.Q)تتلقى الدالة اسم الإجراء وحالة الإدخال، وتكون Begin عند الضغط على المفتاح. يتحكم الخادم بقواعد اللعبة، لذلك لا ينفذ العميل الاندفاع من تلقاء نفسه؛ بل يطلبه من الخادم عبر RemoteEvent Remotes.Ability، باستخدام الاسم. يحتفظ الخادم بجدول للقدرات حسب الاسم، والاندفاع عبارة عن دفعة: فتعيين سرعة الجذر يدفع الشخصية إلى الأمام.
function abilities.Dash(player, character, root)
root.AssemblyLinearVelocity = root.CFrame.LookVector * Settings.DashSpeed + Vector3.new(0, 15, 0)
endالتحدي
متوسطفي BattleClient: احصل على ContextActionService ومجلد Remotes، واكتب use(name, state) الذي يستدعي remotes.Ability مع الاسم عند Begin، واربط "Dash" بالمفتاح Q مع زر للمس.
في BattleServer: أضف local remotes = game.ReplicatedStorage.Remotes، وجدول abilities يتضمن Dash، واربط remotes.Ability.OnServerEvent(player, name) لتشغيل القدرة المحددة مع اللاعب وشخصيته وجذرها.
اضغط تشغيل ثم اضغط Q. بعد ذلك اضغط تحقق.
جرّب بنفسك
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)
local lastSwing = {} -- player -> وقت آخر ضربة نفّذها
-- حركات السيف الخاصة بـ Roblox
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"
print("Swords deal " .. Settings.SwordDamage .. " damage")
-- ضربة بالسيف: تُشغَّل الحركة أولًا، ثم يُصاب كل من في المنطقة أمامك
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()
-- المنطقة أمامك، ولا تشمل جسمك أبدًا
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local box = root.CFrame * CFrame.new(0, 0, -3)
local hit = {} -- كل humanoid مرة واحدة في كل ضربة
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)
end
end
end
-- يحصل كل لاعب على Kills في لوحة الصدارة، وعلى سيف مع كل حياة جديدة
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local kills = Instance.new("IntValue")
kills.Name = "Kills"
kills.Parent = leaderstats
player.CharacterAdded:Connect(function()
local sword = ServerStorage.Sword:Clone()
sword.Parent = player.Backpack
sword.Activated:Connect(function()
swing(player)
end)
end)
end)
-- دمية التدريب: يعكس شريط صحتها مقدار صحتها، وإذا هُزمت
-- تعود الدمية بعد لحظة بنسخة جديدة في المكان نفسه
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)
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.