تنفيذ سلوك البازوكا

*This content is translated using AI (Beta) and may contain errors. To view this page in English, click here.

تنفيذ سلوك البازوكا هي عملية برمجة ميكانيك الانفجار في تجارب مطلق النار من منظور الشخص الأول. بينما يمكن للاعبين أن يقوموا بالانفجار بنقرة واحدة أو ضغطة على زر، فإن إنشاء سلوك انفجار مرضي ودقيق أمر مهم لأنه يعزز استمتاع اللاعبين باللعبة بشكل عام.

باستخدام تجربة الوسم بالليزر النموذجية كمرجع، يُعلمك هذا القسم من الدليل عن السكربتات وراء تنفيذ سلوك البازوكا لنوعين مختلفين من البازوكا، بما في ذلك إرشادات حول:

  • اكتشاف متى يضغط اللاعبون على زر الانفجار.
  • التحقق مما إذا كان اللاعب يمكنه استخدام بازوكته إذا ضغط مؤخرًا على زر الانفجار.
  • إنشاء بيانات الانفجار التي تخبر الخادم بمن بدأ الانفجار، من أين جاء، وما كانت الوجهة النهائية لكل شعاع ليزر.
  • إبلاغ الخادم ببيانات الانفجار حتى يمكنه القيام بالإجراءات المناسبة إذا تصادم الانفجار مع لاعب آخر.
  • إعادة ضبط البازوكا بين كل انفجار لمنح البازوكا وقتًا كافيًا لتبرد قبل أن تتمكن من الانفجار مرة أخرى.

بعد إكمال هذا القسم، ستتعلم عن السكربتات التي تتيح للبازوكا اكتشاف متى تتصادم إنفجاراتها مع لاعبين آخرين، ثم خصم الكمية المناسبة من الصحة وفقًا لكل نوع من البازوكا.

اكتشاف إدخال اللاعب

الخطوة الأولى لتنفيذ سلوك البازوكا هي الاستماع عندما يضغط لاعب على زر الانفجار. يعتمد نوع الإدخال الذي يستخدمه اللاعبون للضغط على زر الانفجار على الجهاز الذي يستخدمونه للوصول إلى التجربة. على سبيل المثال، تدعم تجربة الوسم بالليزر النموذجية الضوابط باستخدام الماوس ولوحة المفاتيح، وأجهزة التحكم، والضوابط اللمسية. يمكنك رؤية كل من هذه الأنواع من الإدخال في ReplicatedStorageUserInputHandler.

يستخدم هذا السكربت العميل ContextActionService لربط MouseButton1 و ButtonR2 للعملية الانفجارية. وهذا يعني أنه في كل مرة يضغط فيها اللاعب على زر الماوس الأيسر أو زر R2 في جهاز التحكم، يتم تشغيل شعاع الليزر للخروج من البازوكا. لاحظ أن HUDGui يحتوي على زر للانفجار على الأجهزة المحمولة، الذي يتصل به لاحقًا في السكربت.

UserInputHandler

ContextActionService:BindAction("_", onBlasterActivated, false,
Enum.UserInputType.MouseButton1,
Enum.KeyCode.ButtonR2
)

ملاحظة أخرى مهمة هي استخدام Enum.UserInputState.Begin في تعريف onBlasterActivated(). لا تحدث العديد من تفاعلات واجهة المستخدم، مثل اختيار بازوكا في هذا المثال، حتى بعد أن يرتفع زر الماوس (Enum.UserInputState.End)، مما يمنح المستخدمين فرصة أخيرة لتجنب التفاعل. ومع ذلك، لا تشعر ميكانيكية الانفجار بالاستجابة ما لم تحدث في اللحظة التي ينخفض فيها الزر.

لتوضيح، يمكنك تغيير Enum.UserInputState.Begin إلى Enum.UserInputState.End، ثم قم بتجربة اللعب لترى كيف يؤثر استجابة الانفجار على تجربة اللعبة. على سبيل المثال، إذا كان بإمكان اللاعبين الضغط على الزر دون تنشيط الانفجار، كيف قد يغير ذلك تجربتهم أثناء الوسم للاعبين آخرين؟

UserInputHandler

local function onBlasterActivated(_actionName: string,
inputState: Enum.UserInputState, _inputObject: InputObject)
if inputState == Enum.UserInputState.End then -- updated line, be sure to change back
attemptBlastClient()
end
end

التحقق مما إذا كان بإمكان اللاعب الانفجار

بعد أن يقوم UserInputHandler بالكشف عن ضغط الزر أو اللمسة على الشاشة، يقوم باستدعاء ReplicatedStorageBlasterattemptBlastClient للتحقق مما إذا كان بإمكان اللاعب الانفجار أم لا. مثل معظم التحققات في تجربة الوسم بالليزر النموذجية، يحدث ذلك مرتين: أولاً على العميل، ثم لاحقًا على الخادم. ثم تستدعي attemptBlastClient ReplicatedStorageBlastercanLocalPlayerBlast لأداء تحقق بسيط من سمة اللاعب blasterStateClient:

canLocalPlayerBlast

local function canLocalPlayerBlast(): boolean
return localPlayer:GetAttribute(PlayerAttribute.blasterStateClient) == BlasterState.Ready
end

إذا قمت بمراجعة ReplicatedStorageBlasterBlasterState، يمكنك أن ترى أن التجربة تحتوي على ثلاث حالات بازوكا: Ready و Blasting و Disabled. لرؤية تأثير كل من هذه الحالات، يمكنك القيام بتجربة للعبة، اختيار لاعبك تحت خدمة Players، ثم مراقبة سمة blasterStateClient في نافذة Properties. لاحظ كيف تعرض Disabled بينما تختار بازوكتك، و Ready معظم الوقت، و Blasting لأقل من ثانية بعد ضغط الزر.

تمنع هذه الواجهة الطفيفة من أن يكون بإمكانك الانفجار بسرعة كما يمكنك الضغط. على سبيل المثال، إذا قمت بتغيير الدالة لتعود دائمًا بـ true، يمكنك انفجار بازوكتك بسرعة دون أي تأخير، وهو أمر غير واقعي لتجربة الوسم بالليزر.

canLocalPlayerBlast

local function canLocalPlayerBlast(): boolean
return true -- updated line, be sure to change back
end

إنشاء بيانات الانفجار

بعد التحقق من أن بازوكا اللاعب في حالة Ready، تستدعي attemptBlastClient ReplicatedStorageattemptBlastClientblastClient. الخطوة الأولى التي تتخذها blastClient هي تعيين سمة اللاعب blasterStateClient إلى Blasting، مما يتجنب حالة النيران السريعة السابقة.

الخطوة التالية هي إنشاء بيانات الانفجار. إذا قمت بمراجعة ReplicatedStorageBlasterBlastData، يمكنك أن ترى أن كل انفجار يتكون من ثلاث قطع من المعلومات:

  • اللاعب الذي يبدأ الانفجار.
  • DataType.CFrame الذي يمثل نقطة الأصل للانفجار.
  • جدول RayResult الذي يحتوي على كل نقطة نهاية لشعاع الليزر واللاعب المتأثر، إذا أصاب لاعبًا آخر.

لإنشاء هذه البيانات، تستدعي blastClient ReplicatedStorageattemptBlastClientblastClientgenerateBlastData، والتي يمكنك مراجعتها أدناه.

generateBlastData

local function generateBlastData(): BlastData.Type
local blasterConfig = getBlasterConfig()
local rayDirections = getDirectionsForBlast(
currentCamera.CFrame, blasterConfig)
local rayResults = castLaserRay(
localPlayer, currentCamera.CFrame.Position, rayDirections)
local blastData: BlastData.Type = {
player = localPlayer,
originCFrame = currentCamera.CFrame,
rayResults = rayResults,
}
return blastData
end

تبدأ هذه الدالة باستخدام getBlasterConfig لاسترجاع نوع بازوكا اللاعب. يوفر النموذج نوعين من البازوكا: واحدة تنتج عدة أشعة مع انتشار واسع، والأخرى تنتج شعاعًا واحدًا. يمكنك العثور على تكويناتها في ReplicatedStorageInstancesLaserBlastersFolder.

ثم تستخدم الدالة currentCamera.CFrame كنقطة الأصل للانفجار، وتمريرها إلى getDirectionsForBlast. في هذه المرحلة، لم يعد الأمر يتعلق بالبازوكا، بل بشعاع الليزر، والذي ستتعلم المزيد عنه في قسم كشف الاصطدامات من الدليل. أخيرًا، بعد إنشاء جدول rayResults، تحتوي generateBlastData على كل المعلومات التي تحتاجها لإرجاع بيانات الانفجار إلى blastClient.

إبلاغ الخادم

بمجرد أن تكون لدى blastClient بيانات كاملة عن الانفجار، تقوم بإطلاق حدثين:

blastClient

local laserBlastedBindableEvent = ReplicatedStorage.Instances.LaserBlastedBindableEvent
local laserBlastedEvent = ReplicatedStorage.Instances.LaserBlastedEvent
laserBlastedBindableEvent:Fire(blastData)
laserBlastedEvent:FireServer(blastData)

يبلغ BindableEvent السكربتات العميلة الأخرى عن الانفجار. على سبيل المثال، تستخدم ReplicatedStorageFirstPersonBlasterVisuals هذا الحدث لمعرفة متى تعرض التأثيرات البصرية، مثل الرسوم المتحركة للاحتراق وشريط التهدئة. بالمثل، يقوم RemoteEvent بإبلاغ سكربتات الخادم عن الانفجار، والذي يبدأ معالجة الانفجار في ServerScriptServiceLaserBlastHandler.

LaserBlastHandler

local function onLaserBlastedEvent(playerBlasted: Player, blastData: BlastData.Type)
local validatedBlastData = getValidatedBlastData(playerBlasted, blastData)
if not validatedBlastData then
return
end
if not canPlayerBlast(playerBlasted) then
return
end
blastServer(playerBlasted)
processTaggedPlayers(playerBlasted, blastData)
for _, replicateToPlayer in Players:GetPlayers() do
if playerBlasted == replicateToPlayer then
continue
end
replicateBlastEvent:FireClient(replicateToPlayer, playerBlasted, blastData)
end
end

للمساعدة في منع الغش، يجب على الخادم التحقق من جميع البيانات التي يرسلها كل عميل. تشمل هذه التحققات:

  1. هل BlastData جدول؟ هل يحتوي على Class.CFrame وجدول آخر يسمى rayResults؟
  2. هل اللاعب لديه بازوكا مُركبة؟
  3. هل يمتلك اللاعب شخصية وموقعًا داخل العالم؟
  4. بعد إرسال بيانات الانفجار، هل ابتعد اللاعب عن المكان الذي انفجر منه شعاع الليزر بمسافة كبيرة؟

تتضمن هذه التحقق الأخير قرارًا تقديريًا، ووفقًا لزمن التأخير الخاص بالخادم وسرعة حركة اللاعب، قد تقرر أن القيم المختلفة غير مقبولة لتجربتك الخاصة. لتوضيح كيفية اتخاذ هذا القرار، يمكنك الحصول على فكرة عن حجم التغيير الوظيفي النموذجي عن طريق إضافة بيان طباعة في getValidatedBlastData وتجربة اللعبة.

getValidatedBlastData

local distanceFromCharacterToOrigin = blastData.originCFrame.Position - rootPartCFrame.Position
print(distanceFromCharacterToOrigin.Magnitude) -- updated line, be sure to remove
if distanceFromCharacterToOrigin.Magnitude > ToleranceValues.DISTANCE_SANITY_CHECK_TOLERANCE_STUDS then
warn(`Player {player.Name} failed an origin sanity check while blasting`)
return
end

بينما تتحرك وتنفجر، لاحظ الإخراج. قد يبدو مثل هذا:


1.9019629955291748
3.1549558639526367
2.5742883682250977
4.8044586181640625
2.6434271335601807

إذا زدت من سرعة الحركة للاعبين في ReplicatedStoragePlayerStateHandlertogglePlayerMovement، ثم اختبرت اللعبة مرة أخرى، ستواجه على الأرجح العديد من الفحوصات الفاشلة بسبب الحركة الزائدة بين الانفجارات.

togglePlayerMovement

local ENABLED_WALK_SPEED = 60 -- updated line, be sure to change back

ثم يقوم الخادم بالتالي:

  • التحقق من صحة rayResults.
  • التحقق مما إذا كان بإمكان اللاعب الانفجار.
  • إعادة ضبط حالة البازوكا.
  • تقليل الصحة لأي لاعبين تم وسمهم.
  • تكرار الانفجار لجميع اللاعبين الآخرين حتى يتمكنوا من رؤية التأثيرات البصرية من منظور الشخص الثالث.

لمزيد من المعلومات حول هذه العمليات على الخادم، انظر قسم كشف الاصطدامات من الدليل.

إعادة ضبط البازوكا

في تجربة الوسم بالليزر النموذجية، تستخدم البازوكا ميكانيكية الحرارة. بدلاً من إعادة التحميل بعد عدد معين من الانفجارات، فهي تحتاج إلى وقت "لتبرد" بين كل انفجار. يحدث نفس التأخير في التهدئة على كل من العميل (blastClient) والخادم (blastServer)، مع كون الخادم هو مصدر الحقيقة.

blastServer

local blasterConfig = getBlasterConfig(player)
local secondsBetweenBlasts = blasterConfig:GetAttribute("secondsBetweenBlasts")
task.delay(secondsBetweenBlasts, function()
local currentState = player:GetAttribute(PlayerAttribute.blasterStateServer)
if currentState == BlasterState.Blasting then
player:SetAttribute(PlayerAttribute.blasterStateServer, BlasterState.Ready)
end
end)

سمة secondsBetweenBlasts هي جزء من تكوين البازوكا في ReplicatedStorageInstancesLaserBlastersFolder. بعد مرور تأخير secondsBetweenBlasts، يمكن للاعب الانفجار مرة أخرى، وتكرر العملية بأكملها. لمساعدة اللاعب على فهم متى يمكنه الانفجار مرة أخرى، تتضمن التجربة شريط تهدئة.

في هذه المرحلة، يمكن للاعبين الظهور وإعادة الظهور، والتصويب والانفجار، ولكن لا تزال التجربة بحاجة إلى تحديد نتائج كل انفجار. في القسم التالي من الدليل، ستتعلم كيفية برمجة قدرة البازوكا لاكتشاف متى يصطدم الانفجار بلاعب آخر، ثم تقليل الكمية المناسبة من صحة اللاعب وفقًا لإعدادات البازوكا.

©2026 شركة Roblox Corporation. تُعد منصّة Roblox، وشعار Roblox وشعار "توسيع حدود المخيلة"، من ضمن علاماتنا التجارية المسجّلة وغير المسجّلة في الولايات المتحدة وبلدان أخرى.