الارتداد
الدرس 11 من 25 في دورة لعبة Roblox: ساحة القتال على Coddy.
ينبغي للضربة القوية أن تقذف ما تصيبه. تطبيق ApplyImpulse على جذر يمنح الجسم كله دفعة. الدفع هو التغير في السرعة مضروبًا في الكتلة، لذا فإن الضرب في AssemblyMass يقذف الهياكل الخفيفة والثقيلة بالطريقة نفسها:
theirRoot:ApplyImpulse((away * 30 + Vector3.new(0, 20, 0)) * theirRoot.AssemblyMass)يشير away من موقعك إلى موقعهم، بمحاذاة سطح الأرض: موقعهم مطروحًا منه موقعك، مع جعل Y صفرًا، ثم .Unit ليكون طوله 1.
التحدي
متوسطاجعل الضربة المقذوفة ترمي كل من تصيبه.
- في
abilities.Slam، بعدhurt:local away = (theirRoot.Position - root.Position) * Vector3.new(1, 0, 1)، ثمaway = away.Unitإذا كان مقدارها أكبر من 0. - ثم
theirRoot:ApplyImpulse((away * Settings.SlamKnockback + Vector3.new(0, 40, 0)) * theirRoot.AssemblyMass).
اضغط «العب»، وامشِ بين المجسمين الأحمرين واضغط E: سيندفعان مبتعدين. ثم اضغط «تحقق».
جرّب بنفسك
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)
local remotes = game.ReplicatedStorage.Remotes
local lastSwing = {} -- player -> وقت آخر ضربة سيف نفّذها
-- حركات السيف الخاصة بـ Roblox
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"
print("Swords deal " .. Settings.SwordDamage .. " damage")
-- كل ضربة في اللعبة تمر من هنا
local function hurt(humanoid, amount)
if humanoid.Health <= 0 then
return
end
local character = humanoid.Parent
humanoid:TakeDamage(amount)
end
-- ضربة سيف: تبدأ الحركة، ثم يُصاب كل من في الصندوق أمامك
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
hurt(humanoid, Settings.SwordDamage)
end
end
end
-- القدرات بحسب أسمائها: ما تفعله كل منها
local abilities = {}
-- جهاز اللاعب هو الذي يحرّك شخصيته، لذا تحدث الاندفاعة هناك
function abilities.Dash(player)
remotes.Ability:FireClient(player, "Dash")
end
-- يُصاب كل من حولك
function abilities.Slam(player, character, root)
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local hit = {}
for _, part in workspace:GetPartBoundsInRadius(root.Position, Settings.SlamRadius, params) do
local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
local theirRoot = part.Parent:FindFirstChild("HumanoidRootPart")
if humanoid and theirRoot and not hit[humanoid] then
hit[humanoid] = true
hurt(humanoid, Settings.SlamDamage)
-- الدرس 11: يُضاف تأثير الدفع إلى الخلف هنا
end
end
end
-- يطلب العميل قدرةً باسمها. يتحقق الخادم من أنها قدرة حقيقية،
-- وأن اللاعب على قيد الحياة، وأن فترة انتظارها قد انتهت. ووقت جاهزيتها مجددًا
-- يُخزَّن كسمة للاعب، حتى تتمكن شاشته من عرضها.
remotes.Ability.OnServerEvent:Connect(function(player, name)
if typeof(name) ~= "string" or not abilities[name] then
return
end
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if not root or character.Humanoid.Health <= 0 then
return
end
local now = workspace:GetServerTimeNow()
if now < (player:GetAttribute(name .. "ReadyAt") or 0) then
return
end
player:SetAttribute(name .. "ReadyAt", now + Settings.Cooldowns[name])
abilities[name](player, character, root)
end)
-- يحصل كل لاعب على سيف في كل مرة يعود فيها إلى الحياة
Players.PlayerAdded:Connect(function(player)
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)
جميع دروس لعبة Roblox: ساحة القتال
تدرّب بنفسك: Playground لـ Roblox