كيفية تطبيق واستخدام قائمة انتظار الرسائل في اللعبة
() translation by (you can also view the original English article)
لعبة عادة ما تتكون من عدة كيانات مختلفة التي تتفاعل مع بعضها البعض. هذه التفاعلات تميل إلى أن تكون حيوية جداً وعميق متصل باللعب. ويغطي هذا البرنامج التعليمي مفهوم وتنفيذ نظام قائمة انتظار الرسائل التي يمكن توحيد التفاعلات بين الكيانات، مما يجعل التعليمات البرمجية الخاصة بك سهلة الصيانة كما أنه ينمو في التعقيد ويمكن التحكم فيها.
مقدمة
قنبلة يمكن أن تتفاعل مع حرف قبل انفجارها والتسبب في الضرر، يمكن أن تلتئم مجموعة مسعف كيان، مفتاح يمكن أن يفتح باب، وهلم جرا. التفاعلات في لعبة لا نهاية لها، ولكن كيف يمكننا أن نبقى رمز اللعبة يمكن التحكم فيها في حين لا تزال قادرة على التعامل مع جميع هذه التفاعلات؟ وكيف نكفل يمكن تغيير التعليمات البرمجية ومواصلة العمل عندما تنشأ تفاعلات جديدة وغير متوقعة؟



كما تتم إضافة التفاعلات (وخصوصا منها غير متوقع)، التعليمات البرمجية الخاصة بك ستبدو تشوش أكثر وأكثر. بسرعة سيؤدي تنفيذ السذاجة أن تسأل أسئلة مثل:
"هذا هو الكيان، لذلك ينبغي أن أدعو ()damage
الأسلوب، الحق؟ أو هل هو ()damageByItem
؟ ربما هذا الأسلوب ()damageByWeapon
هو حق واحد؟ "
تخيل أن الفوضى التبعثر يمتد إلى جميع الكيانات اللعبة الخاصة بك، نظراً لأنهم جميعا تتفاعل مع بعضها البعض بطرق مختلفة وغريبة. لحسن الحظ، هناك طريقة أفضل وأسهل، وأكثر قابلية للإدارة للقيام بذلك.
قائمة انتظار الرسائل
أدخل قائمة انتظار الرسائل. والفكرة الأساسية وراء هذا المفهوم هو تنفيذ جميع التفاعلات لعبة كنظام اتصالات (ولا يزال قيد الاستخدام اليوم): تبادل الرسائل. وقد أبلغت الشعب عبر رسائل (رسائل) لعدة قرون لأنه نظام فعال وبسيط.
في عالمنا الحقيقي وظيفة الخدمات، يمكن أن تختلف محتويات كل رسالة، ولكن الطريقة التي فعلياً إرسال وتلقى لا يزال هو نفسه. مرسل يضع المعلومات في مغلف، ويعالج ذلك بوجهة. يمكن الرد الوجهة (أو لا) باتباع الآلية نفسها، مجرد تغيير في "من وإلى" حقول على المغلف.



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



الحقول الأول والثاني (المرسل
والوجهة
) هي إشارات إلى الكيان الذي تم إنشاؤها والجهة التي ستقوم بتلقي هذه الرسالة، على التوالي. استخدام هذه الحقول، كل من المرسل والمتلقي معرفة أين ستكون الرسالة ومن أين جاء.
الحقلين الآخرين (نوع
والبيانات
) العمل معا لضمان معالجة الرسالة بشكل صحيح. حقل نوع
توضح ما هذه الرسالة حول؛ على سبيل المثال، إذا كان النوع "الضرر"
، المتلقي سوف تتعامل مع هذه الرسالة كأمر إنقاص نقاطها الصحية؛ إذا كان النوع "متابعة"
، اعتبر المتلقي كتعليمات لمتابعة شيء – وهلم جرا.
حقل البيانات
متصل مباشرة إلى حقل النوع
. استخدام الأمثلة السابقة، إذا كان نوع الرسالة "الضرر"
، فسيحتوي حقل البيانات
عدد – أقول، 10
– الذي يصف مقدار الضرر المتلقي ينبغي أن تنطبق على مراكز الصحة له. إذا كان نوع الرسالة "متابعة"
، سوف تحتوي على بيانات
كائن تصف الهدف الذي يجب تحقيقه.
يمكن أن يحتوي حقل البيانات
على أي معلومات، مما يجعل المغلف وسيلة مرنة للاتصال. يمكن وضع أي شيء في هذا المجال: الإعداد الصحيحة والعوامات والسلاسل وكائنات أخرى حتى. وبحكم التجربة أن المتلقي يجب أن تعرف ما هو في حقل البيانات
على أساس ما هو في حقل النوع
.
يمكن ترجمة جميع تلك النظرية إلى فئة بسيطة جداً باسم الرسالة
. يحتوي على الخصائص الأربعة، واحد لكل حقل:
1 |
Message = function (to, from, type, data) { |
2 |
// Properties
|
3 |
this.to = to; // a reference to the entity that will receive this message |
4 |
this.from = from; // a reference to the entity that sent this message |
5 |
this.type = type; // the type of this message |
6 |
this.data = data; // the content/data of this message |
7 |
};
|
كمثال لذلك في استخدام، إذا كان كيان A
ما للتي تريد إرسال رسالة "ضرر"
للكيان B
، كل ذلك القيام به هو إنشاء مثيل كائن فئة الرسالة
، قم بتعيين الخاصية to
إلى B
، تعيين الخاصية من
نفسه (الكيان A
) ، تعيين نوع
"الضرر"
، وأخيراً، تعيين البيانات
إلى بعض رقم (10
، على سبيل المثال):
1 |
// Instantiate the two entities
|
2 |
var entityA = new Entity(); |
3 |
var entityB = new Entity(); |
4 |
|
5 |
// Create a message to entityB, from entityA,
|
6 |
// with type "damage" and data/value 10.
|
7 |
var msg = new Message(); |
8 |
|
9 |
msg.to = entityB; |
10 |
msg.from = entityA; |
11 |
msg.type = "damage"; |
12 |
msg.data = 10; |
13 |
|
14 |
// You can also instantiate the message directly
|
15 |
// passing the information it requires, like this:
|
16 |
var msg = new Message(entityB, entityA, "damage", 10); |
الآن أن لدينا طريقة لإنشاء رسائل، حان الوقت للتفكير في الفئة التي سيتم تخزينها وتسليمها.
تنفيذ قائمة انتظار
سيتم استدعاء الفئة المسؤولة عن تخزين وتسليم الرسائل MessageQueue
. فإنه سيعمل كمكتب للبريد: يتم تسليم كافة الرسائل لهذه الفئة، مما يضمن أنها ستوفد إلى وجهتهم.
الآن، سيكون الفئة MessageQueue
هيكل بسيط جداً:
1 |
/**
|
2 |
* This class is responsible for receiving messages and
|
3 |
* dispatching them to the destination.
|
4 |
*/
|
5 |
MessageQueue = function () { |
6 |
this.messages = []; // list of messages to be dispatched |
7 |
};
|
8 |
|
9 |
// Add a new message to the queue. The message must be an
|
10 |
// instance of the class Message.
|
11 |
MessageQueue.prototype.add = function(message) { |
12 |
this.messages.push(message); |
13 |
};
|
رسائل
الملكية هي صفيف. سيقوم بتخزين كافة الرسائل الموجودة على وشك تسليمها بواسطة MessageQueue
. يتلقى الأسلوب add ()
كائنًا من الفئة الرسالة
كمعلمة ، ويضيف ذلك الكائن إلى قائمة الرسائل.
هنا كيف مثالنا السابق كيان A
كيان مراسلة B
حول الأضرار التي سيعمل استخدام فئة MessageQueue
:
1 |
// Instantiate the two entities and the message queue
|
2 |
var entityA = new Entity(); |
3 |
var entityB = new Entity(); |
4 |
var messageQueue = new MessageQueue(); |
5 |
|
6 |
// Create a message to entityB, from entityA,
|
7 |
// with type "damage" and data/value 10.
|
8 |
var msg = new Message(entityB, entityA, "damage", 10); |
9 |
|
10 |
// Add the message to the queue
|
11 |
messageQueue.add(msg); |
ولدينا الآن وسيلة لإنشاء وتخزين الرسائل في قائمة انتظار. لقد حان الوقت لجعلها تصل إلى وجهتها.
تسليم الرسائل
من أجل جعل الفئة MessageQueue
فعلا إرسال الرسائل التي تم نشرها، أولاً نحن بحاجة إلى تحديد كيف سيتم التعامل مع الكيانات وتلقى الرسائل. أن أسهل طريقة عن طريق إضافة أسلوب المسمى ()onMessage
لكل كيان قادراً على تلقي الرسائل:
1 |
/**
|
2 |
* This class describes a generic entity.
|
3 |
*/
|
4 |
Entity = function () { |
5 |
// Initialize anything here, e.g. Phaser stuff
|
6 |
};
|
7 |
|
8 |
// This method is invoked by the MessageQueue
|
9 |
// when there is a message to this entity.
|
10 |
Entity.prototype.onMessage = function(message) { |
11 |
// Handle new message here
|
12 |
};
|
وسوف الفئة MessageQueue
استدعاء الأسلوب ()onMessage
لكل كيان من الكيانات التي يجب أن تتلقى رسالة. تمرير المعلمة إلى أن الأسلوب هو الرسالة التي يجري بها نظام قائمة الانتظار (والتي يتلقاها الوجهة).
الفئة MessageQueue
سترسل الرسائل الموجودة في قائمة الانتظار في كل مرة، في أسلوب ()dispatch
:
1 |
/**
|
2 |
* This class is responsible for receiving messages and
|
3 |
* dispatching them to the destination.
|
4 |
*/
|
5 |
MessageQueue = function () { |
6 |
this.messages = []; // list of messages to be dispatched |
7 |
};
|
8 |
|
9 |
MessageQueue.prototype.add = function(message) { |
10 |
this.messages.push(message); |
11 |
};
|
12 |
|
13 |
// Dispatch all messages in the queue to their destination.
|
14 |
MessageQueue.prototype.dispatch = function() { |
15 |
var i, entity, msg; |
16 |
|
17 |
// Iterave over the list of messages
|
18 |
for(i = 0; this.messages.length; i++) { |
19 |
// Get the message of the current iteration
|
20 |
msg = this.messages[i]; |
21 |
|
22 |
// Is it valid?
|
23 |
if(msg) { |
24 |
// Fetch the entity that should receive this message
|
25 |
// (the one in the 'to' field)
|
26 |
entity = msg.to; |
27 |
|
28 |
// If that entity exists, deliver the message.
|
29 |
if(entity) { |
30 |
entity.onMessage(msg); |
31 |
}
|
32 |
|
33 |
// Delete the message from the queue
|
34 |
this.messages.splice(i, 1); |
35 |
i--; |
36 |
}
|
37 |
}
|
38 |
};
|
هذا الأسلوب بالتكرار عبر كافة الرسائل في قائمة الانتظار، وعن كل رسالة، لحقل to
يستخدم لجلب إشارة إلى المتلقي. ثم يتم استدعاء الأسلوب ()onMessage
للمتلقي، مع الرسالة الحالية كمعلمة، والرسالة التي تم تسليمها ثم إزالة من قائمة MessageQueue
. وتتكرر هذه العملية حتى يتم إرسال كافة الرسائل.
باستخدام قائمة انتظار الرسائل
لقد حان الوقت لمشاهدة كافة تفاصيل تنفيذ هذا العمل معا. دعونا استخدام نظامنا قائمة انتظار الرسائل في عرض بسيط جداً يتألف من نقل بعض الكيانات التي تتفاعل مع بعضها البعض. توخياً للبساطة، سوف نعمل مع ثلاثة كيانات: الشافي
وعداء
والصياد
.
ويضم حانة صحة العداء
والتحركات عشوائياً. المعالج سوف تلتئم الشافي
أي عداء
يمر قريبة؛ من ناحية أخرى، سوف الصياد
ضررا بأي عداء
القريبة. سيتم التعامل مع جميع التفاعلات باستخدام نظام قائمة انتظار الرسائل.
إضافة قائمة انتظار الرسائل
دعونا نبدأ من خلال إنشاء playState
الذي يحتوي على قائمة بالكيانات (المعالجين والعدائين والصيادين) ومثيل لفئة MessageQueue
:
1 |
var PlayState = function() { |
2 |
var entities; // list of entities in the game |
3 |
var messageQueue; // the message queue (dispatcher) |
4 |
|
5 |
this.create = function() { |
6 |
// Initialize the message queue
|
7 |
messageQueue = new MessageQueue(); |
8 |
|
9 |
// Create a group of entities.
|
10 |
entities = this.game.add.group(); |
11 |
};
|
12 |
|
13 |
this.update = function() { |
14 |
// Make all messages in the message queue
|
15 |
// reach their destination.
|
16 |
messageQueue.dispatch(); |
17 |
};
|
18 |
};
|
في لعبة التكرار الحلقي، ممثلة بواسطة الأسلوب ()update
، يتم استدعاء الأسلوب ()dispatch
لقائمة انتظار الرسائل، حيث يتم تسليم كافة الرسائل في نهاية كل إطار اللعبة.
مشيراً إلى العدائين
الفئة عداء
له البنية التالية:
1 |
/**
|
2 |
* This class describes an entity that just
|
3 |
* wanders around.
|
4 |
*/
|
5 |
Runner = function () { |
6 |
// initialize Phaser stuff here...
|
7 |
};
|
8 |
|
9 |
// Invoked by the game on each frame
|
10 |
Runner.prototype.update = function() { |
11 |
// Make things move here...
|
12 |
}
|
13 |
|
14 |
// This method is invoked by the message queue
|
15 |
// to make the runner deal with incoming messages.
|
16 |
Runner.prototype.onMessage = function(message) { |
17 |
var amount; |
18 |
|
19 |
// Check the message type so it's possible to
|
20 |
// decide if this message should be ignored or not.
|
21 |
if(message.type == "damage") { |
22 |
// The message is about damage.
|
23 |
// We must decrease our health points. The amount of
|
24 |
// this decrease was informed by the message sender
|
25 |
// in the 'data' field.
|
26 |
amount = message.data; |
27 |
this.addHealth(-amount); |
28 |
|
29 |
} else if (message.type == "heal") { |
30 |
// The message is about healing.
|
31 |
// We must increase our health points. Again the amount of
|
32 |
// health points to increase was informed by the message sender
|
33 |
// in the 'data' field.
|
34 |
amount = message.data; |
35 |
this.addHealth(amount); |
36 |
|
37 |
} else { |
38 |
// Here we deal with messages we are not able to process.
|
39 |
// Probably just ignore them :)
|
40 |
}
|
41 |
};
|
الجزء الأهم هو الأسلوب ()onMessage
، يتم استدعاؤه بواسطة قائمة انتظار الرسائل في كل مرة هناك رسالة جديدة لهذا المثيل. كما هو موضح سابقا، يتم استخدام نوع
الحقل في الرسالة أن تقرر ما كل شيء عن هذه الاتصالات.
استناداً إلى النوع الرسالة، يتم تنفيذ الإجراء الصحيح: إذا كان نوع الرسالة "الضرر "
، انخفضت نقاط صحية؛ إذا كان نوع الرسالة "الشفاء"
، يتم زيادة نقاط صحية. ويعرف عدد النقاط الصحية لزيادة أو إنقاص بالمرسل في حقل البيانات
من الرسالة.
في playState
، نضيف بعض العدائين إلى قائمة الكيانات:
1 |
var PlayState = function() { |
2 |
// (...)
|
3 |
|
4 |
this.create = function() { |
5 |
// (...)
|
6 |
|
7 |
// Add runners
|
8 |
for(i = 0; i < 4; i++) { |
9 |
entities.add(new Runner(this.game, this.game.world.width * Math.random(), this.game.world.height * Math.random())); |
10 |
}
|
11 |
};
|
12 |
|
13 |
// (...)
|
14 |
};
|
والنتيجة أربع عداءات يتحرك عشوائياً:
إضافة الصياد
يحتوي صنف الصياد
على البنية التالية:
1 |
/**
|
2 |
* This class describes an entity that just
|
3 |
* wanders around hurting the runners that pass by.
|
4 |
*/
|
5 |
Hunter = function (game, x, y) { |
6 |
// initialize Phaser stuff here
|
7 |
};
|
8 |
|
9 |
// Check if the entity is valid, is a runner, and is within the attack range.
|
10 |
Hunter.prototype.canEntityBeAttacked = function(entity) { |
11 |
return entity && entity != this && |
12 |
(entity instanceof Runner) && |
13 |
!(entity instanceof Hunter) && |
14 |
entity.position.distance(this.position) <= 150; |
15 |
};
|
16 |
|
17 |
// Invoked by the game during the game loop.
|
18 |
Hunter.prototype.update = function() { |
19 |
var entities, i, size, entity, msg; |
20 |
|
21 |
// Get a list of entities
|
22 |
entities = this.getPlayState().getEntities(); |
23 |
|
24 |
for(i = 0, size = entities.length; i < size; i++) { |
25 |
entity = entities.getChildAt(i); |
26 |
|
27 |
// Is this entity a runner and is it close?
|
28 |
if(this.canEntityBeAttacked(entity)) { |
29 |
// Yeah, so it's time to cause some damage!
|
30 |
msg = new Message(entity, this, "damage", 2); |
31 |
|
32 |
// Send the message away!
|
33 |
this.getMessageQueue().add(msg); // or just entity.onMessage(msg); if you want to bypass the message queue for some reasong. |
34 |
}
|
35 |
}
|
36 |
};
|
37 |
|
38 |
// Get a reference to the game's PlayState
|
39 |
Hunter.prototype.getPlayState = function() { |
40 |
return this.game.state.states[this.game.state.current]; |
41 |
};
|
42 |
|
43 |
// Get a reference to the game's message queue.
|
44 |
Hunter.prototype.getMessageQueue = function() { |
45 |
return this.getPlayState().getMessageQueue(); |
46 |
};
|
الصيادين أيضا التحرك، بل أنها سوف تسبب ضررا لجميع المتسابقين التي قريبة. وينفذ هذا السلوك في الأسلوب ()update
، حيث يتم تفتيش جميع الكيانات اللعبة والعدائين هي بعث برسالة حول الأضرار.
يتم إنشاء الرسالة الأضرار على النحو التالي:
1 |
msg = new Message(entity, this, "damage", 2); |
تحتوي الرسالة على معلومات حول الوجهة (الكيان
، في هذه الحالة، وهو الكيان الذي يجري تحليله في التكرار الحالي)، المرسل (هذا
، الذي يمثل الصياد الذي يتم تنفيذ الهجوم)، ونوع الرسالة ("الضرر"
) مقدار الضرر (2
، وفي هذه الحالة، تم تعيينها لحقل البيانات
من الرسالة).
ثم يتم نشر الرسالة إلى الوجهة عن طريق (this.getMessageQueue().add(msg
الأوامر، التي تضيف الرسالة التي تم إنشاؤها حديثا إلى قائمة انتظار الرسائل.
وأخيراً، نضيف الصياد
إلى قائمة الكيانات playState
:
1 |
var PlayState = function() { |
2 |
// (...)
|
3 |
|
4 |
this.create = function() { |
5 |
// (...)
|
6 |
|
7 |
// Add hunter at position (20, 30)
|
8 |
entities.add(new Hunter(this.game, 20, 30)); |
9 |
};
|
10 |
|
11 |
// (...)
|
12 |
};
|
والنتيجة هي بعض العدائين يتحرك، وتلقى رسائل من الصياد كما أنها تحصل على مقربة من بعضها البعض:
وأضفت المغلفات تحلق كمساعدات البصرية للمساعدة في إظهار ما يحدث.
إضافة المعالج
فئة الشفاء
بالبنية التالية:
1 |
/**
|
2 |
* This class describes an entity that is
|
3 |
* able to heal any runner that passes nearby.
|
4 |
*/
|
5 |
Healer = function (game, x, y) { |
6 |
// Initializer Phaser stuff here
|
7 |
};
|
8 |
|
9 |
Healer.prototype.update = function() { |
10 |
var entities, i, size, entity, msg; |
11 |
|
12 |
// The the list of entities in the game
|
13 |
entities = this.getPlayState().getEntities(); |
14 |
|
15 |
for(i = 0, size = entities.length; i < size; i++) { |
16 |
entity = entities.getChildAt(i); |
17 |
|
18 |
// Is it a valid entity?
|
19 |
if(entity) { |
20 |
// Check if the entity is within the healing radius
|
21 |
if(this.isEntityWithinReach(entity)) { |
22 |
// The entity can be healed!
|
23 |
// First of all, create a new message regaring the healing
|
24 |
msg = new Message(entity, this, "heal", 2); |
25 |
|
26 |
// Send the message away!
|
27 |
this.getMessageQueue().add(msg); // or just entity.onMessage(msg); if you want to bypass the message queue for some reasong. |
28 |
}
|
29 |
}
|
30 |
}
|
31 |
};
|
32 |
|
33 |
// Check if the entity is neither a healer nor a hunter and is within the healing radius.
|
34 |
Healer.prototype.isEntityWithinReach = function(entity) { |
35 |
return !(entity instanceof Healer) && !(entity instanceof Hunter) && entity.position.distance(this.position) <= 200; |
36 |
};
|
37 |
|
38 |
// Get a reference to the game's PlayState
|
39 |
Healer.prototype.getPlayState = function() { |
40 |
return this.game.state.states[this.game.state.current]; |
41 |
};
|
42 |
|
43 |
// Get a reference to the game's message queue.
|
44 |
Healer.prototype.getMessageQueue = function() { |
45 |
return this.getPlayState().getMessageQueue(); |
46 |
};
|
التعليمات البرمجية وهيكل مشابهة جداً للفئة هنتر، باستثناء عدد قليل من الاختلافات. وبالمثل للتنفيذ للصياد
، تتكرر الأسلوب ()update
للمعالج على قائمة الكيانات في اللعبة، والمراسلة أي كيان داخل نطاقه الشفاء:
1 |
msg = new Message(entity, this, "heal", 2); |
كما تحتوي الرسالة على وجهة (كيان
)، مرسل (هذا
، وهو المعالج يقوم بتنفيذ الإجراء)، اكتب رسالة ("شفاء"
) وعدد النقاط الشفاء (2
، تم تعيينها في حقل البيانات
من الرسالة).
نقوم بإضافة الشفاء
إلى قائمة الكيانات playState
بنفس الطريقة فعلنا مع الصياد
، والنتيجة مشهد مع المتسابقين وصياد من معالج:
وهذا كل شيء! ولدينا ثلاثة كيانات مختلفة تتفاعل مع بعضها البعض عن طريق تبادل الرسائل.
مناقشة حول المرونة
نظام قائمة الانتظار هذه الرسائل طريقة مرنة لإدارة التفاعلات في لعبة. التفاعلات تتم عبر قناة اتصال موحد وله واجهة واحدة سهلة الاستخدام وتنفيذ.
مع ازدياد في تعقيد اللعبة الخاصة بك، قد تكون هناك حاجة تفاعلات جديدة. قد يكون بعضها غير متوقع تماما، حيث أنك يجب أن تكيف التعليمات البرمجية الخاصة بك للتعامل معها. إذا كنت تستخدم نظام قائمة انتظار الرسائل، وهذا مدعاة لإضافة رسالة جديدة في مكان ما، والتعامل مع الأمر في مكان آخر.
على سبيل المثال، تخيل تريد جعل الصياد
تتفاعل مع الشفاء
؛ لديك فقط لجعل الصياد
إرسال رسالة مع التفاعل الجديد — على سبيل المثال، "الفرار"
– والتأكد من أن الشفاء
يمكن التعامل معها في onMessage
:
1 |
// In the Hunter class:
|
2 |
Hunter.prototype.someMethod = function() { |
3 |
// Get a reference to a nearby healer
|
4 |
var healer = this.getNearbyHealer(); |
5 |
|
6 |
// Create message about fleeing a place
|
7 |
var place = {x: 30, y: 40}; |
8 |
var msg = new Message(entity, this, "flee", place); |
9 |
|
10 |
// Send the message away!
|
11 |
this.getMessageQueue().add(msg); |
12 |
};
|
13 |
|
14 |
// In the Healer class:
|
15 |
Healer.prototype.onMessage = function(message) { |
16 |
if(message.type == "flee") { |
17 |
// Get the place to flee from the data field in the message
|
18 |
var place = message.data; |
19 |
|
20 |
// Use the place information
|
21 |
flee(place.x, place.y); |
22 |
}
|
23 |
};
|
لماذا لا مجرد إرسال رسائل مباشرة؟
على الرغم من أن تبادل الرسائل بين الكيانات يمكن أن تكون مفيدة، كنت قد يكون التفكير لماذا هناك حاجة MessageQueue
بعد كل. لا يمكنك فقط استدعاء الأسلوب ()onMessage
للمتلقي نفسك بدلاً من الاعتماد على MessageQueue
، كما في التعليمات البرمجية أدناه؟
1 |
Hunter.prototype.someMethod = function() { |
2 |
// Get a reference to a nearby healer
|
3 |
var healer = this.getNearbyHealer(); |
4 |
|
5 |
// Create message about fleeing a place
|
6 |
var place = {x: 30, y: 40}; |
7 |
var msg = new Message(entity, this, "flee", place); |
8 |
|
9 |
// Bypass the MessageQueue and directly deliver
|
10 |
// the message to the healer.
|
11 |
healer.onMessage(msg); |
12 |
};
|
يمكن بالتأكيد تنفيذ نظام لرسالة مثل هذه، ولكن استخدام MessageQueue
بعض المزايا.
على سبيل المثال، بإضفاء الطابع المركزي ديسباتشمينت الرسائل، يمكنك تنفيذ بعض الميزات الرائعة مثل تأخر الرسائل، القدرة على رسالة مجموعة من الكيانات، ومعلومات التصحيح البصرية (مثل المغلفات الطيران المستخدمة في هذا البرنامج التعليمي).
هناك مجالاً للإبداع في الفئة MessageQueue
، والأمر متروك لكم ومتطلبات اللعبة الخاصة بك.
الاستنتاج
معالجة التفاعلات بين الكيانات اللعبة باستخدام نظام قائمة انتظار رسالة وسيلة للحفاظ على التعليمات البرمجية الخاصة بك المنظمة والاستعداد للمستقبل. تفاعلات جديدة يمكن بسهولة وبسرعة إضافة، حتى الأفكار الأكثر تعقيداً، طالما أنها هي مغلفة كرسائل.
كما تمت مناقشته في البرنامج التعليمي، يمكنك تجاهل استخدام قائمة انتظار الرسالة المحورية ومجرد إرسال رسائل مباشرة إلى الكيانات. يمكن أيضا مركزة الاتصال باستخدام برقية (الفئة MessageQueue
في حالتنا) لإفساح المجال للميزات الجديدة في المستقبل، مثل تأخر الرسائل.
أرجو أن يجد هذا النهج مفيداً وإضافته إلى حزام أداة مطور اللعبة الخاصة بك. الأسلوب الذي قد يبدو وكأنه مبالغة للمشاريع الصغيرة، ولكن من المؤكد سيوفر لك بعض الصداع في الأجل الطويل للألعاب أكبر.