HeapPlay

كيف تضيف تحكمًا باللمس إلى لعبة متصفح مصممة للوحة المفاتيح فقط؟

ضع فوق اللعبة طبقة لمس مستقلة تمدّها بالمُدخلات التي تفهمها أصلًا. هكذا فعلنا في KittenGalaxy، وهذا ما لم نختبره بعد.

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

ماذا كانت اللعبة تتوقع من قبل؟

KittenGalaxy لعبة تصويب أركيد مكتوبة في ملف JavaScript واحد يرسم على عنصر canvas. كانت كل مُدخلاتها تصل بثلاث طرق: ضغطات المفاتيح للطيران والإطلاق والقوائم؛ والأحرف المكتوبة لاسم الطيار؛ ونقرات الفأرة لقائمة المتجر وللوحة أرقام مرسومة على canvas في تحديات الرياضيات.

على الهاتف لا يبقى للاعب ما يضغطه. لا توجد مفاتيح، ومفاتيح الأرقام المرسومة على canvas، وعرضها 38 وحدة في ساحة لعب عرضها 720 وحدة، تظهر بعرض نحو 20 بكسل CSS على هاتف عرضه 375 بكسل. وهذا أصغر من أن يُصاب بثبات.

هل ينبغي أن يضبط اللمس حالة إدخال مشتركة، أم يرسل أحداث مفاتيح؟

هناك تصميمان شائعان.

الأسلوبكيف يعملمتى يكون مناسبًا
حالة إدخال مشتركةتضبط معالجات لوحة المفاتيح واللمس كلتاهما أعلامًا مثل left أو fire؛ وحلقة اللعبة تقرأ الأعلام فقطحين تملك شيفرة اللعبة وتستطيع تغيير طريقة قراءتها للمُدخلات
أحداث مفاتيح مُصطنعةترسل طبقة اللمس أحداث keydown و keyup؛ فتستقبلها المستمعات الموجودة في اللعبةحين يجب أن تبقى شيفرة اللعبة كما هي

الحالة المشتركة هي التصميم الأنظف، وإن كنت تبدأ لعبة اليوم فابنها هكذا. اخترنا أحداث المفاتيح المُصطنعة لسبب واحد: KittenGalaxy تُطوَّر في مكان آخر، ونحن نُبقي ملفها بايتًا ببايت كما نستلمه، كي لا يعني أخذ إصدار أحدث إعادة تعديلاتنا أبدًا. الأحداث التي تُنشأ بالسكربت تصل فعلًا إلى المستمعات العادية. وهي لا تُطلق الإجراءات الافتراضية للمتصفح، واللعبة لا تحتاج إليها.

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

لمسة الإصبع تذهب إلى طبقة اللمس التي ترسل أحداث مفاتيح إلى اللعبة غير المعدَّلة وتقرأ حالتها
موضع طبقة اللمس.

ما الأزرار التي تحتاجها كل شاشة؟

مجموعة ثابتة واحدة من الأزرار هي المحاولة الأولى المعتادة، وتفشل حالما يكون للعبة قائمة. اكتب كل شاشة وما يجب أن يتمكن اللاعب من فعله فيها.

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

ثلاثة تفاصيل كانت أهم مما توقعنا.

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

الإصبع لا يستطيع التحويم. بالفأرة، الإشارة إلى صف في المتجر تحدده والنقر يشتريه. اللمسة تفعل الأمرين معًا، فيسهل الشراء غير المقصود. تحوّل الطبقة اللمسة الأولى على الصف إلى تحديد وتمرّر الثانية على أنها الشراء.

أخفِ ما لا ينطبق. يظهر زر الصاروخ حين يُركَّب صاروخ، وزر القنبلة حين تُحمل قنبلة. أزرار أقل تعني أزرارًا أكبر.

كيف تبني عصا للإبهام؟

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

const DEAD = 12;
function steer(dx, dy) {
  const far = Math.hypot(dx, dy) > DEAD;
  const want = {
    ArrowLeft:  far && dx < 0 && Math.abs(dx) >= Math.abs(dy) * 0.41,
    ArrowRight: far && dx > 0 && Math.abs(dx) >= Math.abs(dy) * 0.41,
    ArrowUp:    far && dy < 0 && Math.abs(dy) >= Math.abs(dx) * 0.41,
    ArrowDown:  far && dy > 0 && Math.abs(dy) >= Math.abs(dx) * 0.41,
  };
  // press the keys that became true, release the ones that became false
}

الرقم 0.41 هو ظلّ الزاوية 22.5 درجة، وهو يقسم الدائرة إلى ثمانية قطاعات متساوية. حين يتجاوز الإبهام الحافة يتبعه مركز العصا، فيكفي لعكس الاتجاه تحريك صغير بدل تحريك طويل.

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

ما الذي يمنع المتصفح من مصارعة اللعبة؟

يعامل المتصفح اللمسات على أنها تمرير وتكبير وتحديد نص ما لم يُقل له غير ذلك.

  • اضبط [touch-action: none](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/touch-action) على اللعبة وأزرارها، لتكون حركات السحب لك.
  • عطّل تحديد النص وقائمة الضغط المطوّل فوق اللعبة.
  • أفلت كل مفتاح مضغوط حين تفقد النافذة التركيز. وإلا تواصل المركبة الطيران يسارًا بعد أن يستولي إشعار على الشاشة.
  • ابدأ الصوت من لمسة حقيقية. المتصفحات لا تسمح بالصوت إلا بعد أن يتفاعل اللاعب مع الصفحة، فاللمسة الأولى توقظ صوت اللعبة أيضًا.
  • حدّث الأزرار بمؤقّت، لا من حلقة الرسم وحدها، لتكون الأزرار الصحيحة حاضرة قبل رسم الإطار الأول.
  • استخدم الأشرطة التي تتركها اللعبة فارغة. في الوضع الرأسي تقع ساحة لعبنا المربعة في الوسط، فتذهب الأزرار إلى الشريطين الأسودين أعلاها وأسفلها. وفي الوضع الأفقي تذهب إلى الزوايا وتبقى باهتة.

ما الذي اختبرناه وما الذي لم نختبره؟

في يوم الإصدار، 8 أكتوبر 2026، فحصنا طبقة اللمس في متصفح حاسوب مضبوط على حجم الهاتف، في الوضع الرأسي (375 × 812) والأفقي (812 × 375)، وشغّلناها بلمسات مبرمجة: إنشاء طيار عبر حقل النص، وبدء جولة، واتجاهات العصا الثمانية كلها، والمتجر، والإجابة عن سؤال رياضيات على لوحة الأرقام.

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

أسئلة شائعة

هل أحتاج إلى محرك ألعاب من أجل التحكم باللمس؟ لا. الأزرار عناصر HTML عادية موضوعة فوق canvas، والمتصفح يحدد أيها لُمس.

هل تُرسم الأزرار على canvas أم تُصنع بـ HTML؟ بـ HTML في معظم الحالات. تحصل على كشف اللمس وتعدد اللمسات وتسميات إمكانية الوصول دون كتابتها، وتستطيع تغيير المظهر بـ CSS.

كم ينبغي أن يكون حجم زر اللمس؟ الأزرار التي تُضغط أثناء اللعب لا يقل ضلعها عن 46 بكسل CSS في الوضع الرأسي، والرئيسية أكبر؛ وبضعة أزرار مساعدة في الزوايا أصغر عن قصد. مفاتيح canvas التي استبدلناها كانت نحو 20.

هل سيكتشف اللاعبون إيماءة مخفية؟ افترض أنهم لن يكتشفوها. لكل إجراء في طبقتنا زر ظاهر وله تسمية.

هل أستطيع إدراج لعبة في HeapPlay قبل اكتمال التحكم على الهاتف؟ نعم. كل طريقة لعب تُدرج وتُفحص على حدة، فيمكنك إرسال لعبتك الآن بطريقة لعب للحاسوب وإضافة طريقة للهاتف لاحقًا. وبعدها يستطيع المطورون الموثّقون تسجيل كل إصدار بأنفسهم؛ انظر ما يحصل عليه المطورون.

touch-controls mobile browser-games

هل تبني لعبة؟ أرسلها إلى HeapPlay وتعرّف على ما يحصل عليه المطورون.