GlamUp Girls: لعبة تلبيس للهاتف (Flutter)
Kendi ürünüm — bağımsız yayın
(73 تقييم) 9014 مشاهدة
لعبة تلبيس منشورة على Google Play وApp Store تضم 14 شخصية وأكثر من 1,000 خيار من الملابس والإكسسوارات وتسريحات الشعر والمكياج، وأربع حزم حيوانات أليفة. العميل مكتوب بـ Flutter، والتحقق من المشتريات يجري على الخادم عبر Firebase Cloud Functions، أما عيوب التخطيط فأُغلقت بالقياس لا بالتخمين. بدأ العمل في نيسان/أبريل 2026، واللعبة منشورة على Play ضمن تصنيف PEGI 3 وقواعد فئة الأطفال.
GlamUp Girls: لعبة تلبيس للهاتف
متاحة على Google Play وApp Store · بالإنجليزية والتركية والعربية · طُوّرت ونُشرت بشكل مستقل
GlamUp Girls لعبة تلبيس: تختار شخصيتك، وتضع المكياج، تختار الشعر والملابس، ثم تخرج بها إلى منصة العرض. فيها 14 شخصية وأكثر من 1,000 خيار من الملابس والإكسسوارات وتسريحات الشعر والمكياج، وأربع حزم حيوانات أليفة ومسابقات أسبوعية وشهرية. وفي الجولة التعليمية شرح صوتي قصير مولَّد بتحويل النص إلى كلام (TTS). أول commit كان في 7 نيسان/أبريل 2026، وهي منشورة على Google Play. ومتوفرة على App Store(iPhone وiPad) منذ 12 أيلول/سبتمبر 2026. تصنيفها PEGI 3، ضمن فئة الألعاب العادية، وتخضع لسياسة العائلة في Play.
أفضّل هنا أن أشرح كيف بُنيت اللعبة لا ماذا تفعل. الجزء الظاهر في لعبة عادية، أي الرسوم والحركة، هو الجزء الصغير. الوقت الحقيقي يذهب إلى خط إنتاج المحتوى، وإلى حسابات النقاط، وإلى التحقق من المشتريات على الخادم، وإلى قواعد فئة الأطفال. كل رقم في هذه الصفحة قِيس من المستودع مباشرة في 9 أيلول/سبتمبر 2026، ولم يُقدَّر تقديراً.
ماذا في اللعبة
- 👗 14 شخصية و1,095 خياراً مختلفاً: 817 قطعة ملابس وإكسسوار، و78 تسريحة شعر، و200 نمط مكياج (الرسم المشترك بين شخصيتين يُحتسب مرة واحدة؛ تشارك أنيقة جزءاً من قطع غلام؛ لا تُحتسب رسوم الجسم الأساسية)
- 🐾 4 حزم حيوانات أليفة (قطة وكلب ومهرة ووحيد قرن)، 193 قطعة
- 🌟 نقاط المنصة: 4 فئات في الوضع الحر و5 فئات في المسابقة، على مقياس من 0 إلى 100
- 🏆 مسابقات أسبوعية وشهرية ومجموعة قطع نادرة
- 🌍 واجهة بالتركية والإنجليزية والعربية وشرح صوتي (TTS) في الجولة التعليمية، وستُضاف لغات أخرى تدريجيًا
- 🛡️ بوابة والدية على مداخل الشراء، ومعاملة الإعلانات كإعلانات موجهة للأطفال بتصنيف محتوى G
من داخل اللعبة
خمس شاشات يقضي فيها اللاعب معظم وقته.





ثلاث شخصيات جديدة



أنيقة تستخدم خزانة محتشمة منتقاة عبر تبويب الحجاب في استوديو الأطقم: 109 قطع مختارة من حزمة غلام، منها 85 قطعة مشتركة مع قائمة غلام نفسها. أيقونة امرأة بمقاس كبير، وكاجوال رجل بمقاس كبير. الثلاث مفتوحة منذ التثبيت الأول، ولا تقبع خلف حزمة تُنزَّل لاحقاً.
العمل المنجز
كتبتُ العميل بـ Flutter: 451 ملف Dart و180,738 سطراً تحت lib/ (حتى 21 أيلول/سبتمبر 2026). منطق العمل موزع على 104 ملفات خدمات مباشرة في جذر lib/services، وحالة الشاشات في 10 أصناف تحت lib/store. الحفظ محلي أولاً على SharedPreferences مقيدة بمعرّف المستخدم، أما المزامنة السحابية فطبقة منفصلة، حتى لا يتعطل اللعب دون اتصال. الخادم على Firebase Cloud Functions: 19 دالة قابلة للاستدعاء، وملف index.js من 3,313 سطراً، ووحدة مستقلة من 945 سطراً للتحقق من المشتريات.
أبرز النتائج
✅ 18,622 صورة webp منظَّمة في 25 حزمة أصول؛ أعداد تنويعات الألوان تدخل الشيفرة من جدول يضم 1,418 مدخلاً يولّده مسح الأصول، لا من الكتابة اليدوية
✅ لا ثقة في العميل عند الشراء: توقيع JWS من StoreKit 2 على iOS، وواجهة Play Developer API على Android، والتحقق يجري على الخادم؛ الإيصال الواحد لا يُقبل مرتين
✅ الشاشات الـ44 كلها تجتاز اختبار الفيض على 13 عرض جهاز بين 320 و1024 dp
✅ 5,433 تعريف اختبار في 607 ملفات (عدٌّ من المصدر، 21 أيلول/سبتمبر 2026)، إضافة إلى 47 ملف اختبار على المحاكي لجانب Firestore وFunctions
✅ انزياح علامات الترقيم في الشاشة العربية أُغلق بالقياس (36.1 بكسل)، واختبار حارس من 261 سطراً يمنع عودته
خط إنتاج المحتوى
الفهرس مصمَّم على شكل قوائم منفصلة لكل شخصية من الشخصيات الـ14. وراء تعريفات الخيارات الـ1,095 توجد 25 حزمة أصول و18,622 صورة webp منظَّمة. أكثر ما استهلك وقتي كان تنويعات الألوان. في البداية كنت أكتب الأعداد بيدي. كلما أُضيفت قطعة إلى حزمة، يتقادم الجدول وتعرض اللعبة عدداً خاطئاً. الآن يولّد مسحُ الأصول 1,418 مدخلاً (حزمة، بادئة) ويضعها في الشيفرة مباشرة. لم يعد الجدول يتقادم، لأنه لم يعد هناك جدول يدوي أصلاً.
تقييم الإطلالة
التقييم وحدة مستقلة من 15 ملفاً و1,608 سطراً، ستة منها محللات. الإطلالة الحرة تكسب حتى 25 نقطة في كل فئة من أربع؛ وفي المسابقة تُضاف فئة "ملاءمة الموضوع"، فتصبح خمس فئات بعشرين نقطة لكل منها، على مقياس من 0 إلى 100. فوق ذلك مضاعِف ندرة من خمس درجات، من Common ×1.00 إلى Legendary ×1.25. هذه ثوابت في الشيفرة لا ملاحظات في تعليق، فأي تغيير في التصميم يمس موضعاً واحداً.
التوطين
نص الواجهة موزع على 51 ملف ARB في 17 نطاق أسماء: 7,568 سطر مفتاح بالإنجليزية، و7,569 بالتركية، و7,596 بالعربية. ثمانية وعشرون اختبار i18n منفصلاً تراقب التطابق بين الملفات وتلتقط أي إنجليزية تتسرب إلى الشاشات العربية.
الدرس الحقيقي جاء من الجانب العربي. حين يقع نص لاتيني، كاسم مستخدم مثلاً، داخل جملة عربية، تنزلق علامة التعجب والنقطة إلى الجهة الخطأ. قستُ ذلك بـ TextPainter بدل الاعتماد على العين: علامة التعجب من دون عزل ظهرت عند x=0.0، ومع عزل FSI/PDI من يونيكود ظهرت عند x=36.1. حين صار الفرق رقماً، صار الإصلاح صغيراً. ولكي لا يعود الخلل، يعدّ اختبارُ حراسة من 261 سطراً استخدامات EdgeInsets.only وfromLTRB وPositioned وTextAlign التي ترسم بصمت في الجهة الخطأ، ويستثني المتناظر منها.
الشرح الصوتي 32 جملة قصيرة لكل لغة: 24 للجولة الإرشادية و8 ردود فعل، وكلها مولَّدة بتحويل النص إلى كلام (TTS). التركية والإنجليزية من edge-tts (tr-TR-EmelNeural وen-US-AvaNeural)، والعربية من Azure Speech (ar-EG-SalmaNeural). كل لغة مثبَّتة على صوت واحد، فلا يتبدل صوت الشخصية من شاشة إلى أخرى.
الخادم والمشتريات
التحقق من الشراء يجري على الخادم لا في العميل. على iOS أعتمد توقيع JWS من StoreKit 2، وعلى Android واجهة Play Developer API. العملية الموثَّقة تُكتب تحت verified_purchases/{transactionId} بإنشاء ذرّي، فالإيصال نفسه لا يصلح مرتين ولا في حساب آخر. الأخطاء ثلاثة أصناف: الإيصال غير الصالح فعلاً وخطأ الإعداد يُرفضان، أما خطأ الشبكة العابر أو استجابة 5xx فتمرّ بتساهل. هذا الخيار الأخير قابل للنقاش. فضّلتُ نافذة تساهل قصيرة على حرمان طفلة دفعت بالفعل بسبب تعثر مؤقت في الخادم.
فئة الأطفال والامتثال
مداخل الشراء داخل التطبيق تقف خلف حوار تحقق والدي لا يُغلق بالنقر خارجه: سؤال جمع يُختار حدّاه عشوائياً بين 12 و19 (الجواب بين 24 و38)، وسؤال جديد بعد 600 ميلي ثانية من كل إجابة خاطئة، والتحقق الناجح يبقى في الذاكرة 15 دقيقة.
على جانب الإعلانات لا توجد بوابة كهذه، وأقولها صراحة لأن مسودتي الأولى زعمت العكس، وكذّبتها الشيفرة. الإعلانات مقيدة بالمعاملة الموجهة للأطفال وبتصنيف محتوى G، وقبل تهيئة الحزمة البرمجية يعمل مسار موافقة Google UMP بمهلة 8 ثوانٍ.
سطح الاختبار
حتى 21 أيلول/سبتمبر 2026: 5,433 تعريف اختبار في 607 ملفات، مع 47 ملف اختبار على المحاكي لجانب Firestore وCloud Functions. يُضاف إليها 24 حارس انحدار باسم *_guard_test.dart: بعضها يمسح المصدر على القرص ويقفل نمطاً برمجياً في CI، وبعضها يتحقق من السلوك. مصفوفة الفيض تشغّل 44 شاشة على 13 عرضاً، واختبار تغطية منفصل يقارن سجل الشاشات بملفات *_screen.dart على القرص، فأي شاشة جديدة غابت عن السجل تحوّل CI إلى الأحمر.
الصعوبات التقنية
- تقادم أعداد تنويعات الألوان في جدول يدوي؛ حُلّت بتوليد الجدول من مسح الأصول
- انزياح الترقيم عند وقوع نص لاتيني داخل جملة عربية؛ قياس ثم عزل FSI/PDI
- إعادة استخدام إيصال الشراء أو نقله إلى حساب آخر؛ أُغلق بالإنشاء الذرّي
- الإبقاء على بوابة الشراء وموافقة الإعلانات آليتين منفصلتين في فئة الأطفال
- نسيان إضافة شاشة جديدة إلى مصفوفة الفيض؛ اختبار التغطية يلتقطه في CI
لماذا كان مهماً
لعبة تلبيس عادية تبدو من الخارج عملاً صغيراً. من الداخل هي خمس مشكلات تُدار معاً: إنتاج المحتوى، وحساب النقاط، وأمان الدفع، والتوطين، وامتثال الأطفال. في هذا المشروع أغلقتُ الخمس بالقياس وبقفل كل واحدة باختبار، والنتيجة ظاهرة في المتجر، وفي مسار الشراء، وعلى الشاشة العربية.
بالأرقام
| المجال | القيمة |
|---|---|
| قاعدة الشيفرة | 451 ملف Dart، 180,738 سطراً، 104 ملفات خدمات (جذر lib/services) |
| خزانة الملابس | 14 شخصية، 1,095 خياراً + 193 قطعة للحيوانات الأليفة |
| مخزن الصور | 25 حزمة، 18,622 صورة webp، 1,418 مدخل تنويع |
| التعريب والترجمة | 51 ملف ARB، 17 نطاق أسماء، 3 لغات، 32 جملة صوتية (TTS) لكل لغة |
| الاختبارات | 607 ملفات، 5,433 تعريف اختبار (عدٌّ من المصدر، 21 أيلول/سبتمبر 2026)، 47 ملف اختبار محاكي، 24 حارساً |
| الخادم | 19 دالة قابلة للاستدعاء، تحقق من الشراء على الخادم |
خلاصة
الإصدار المنشور على Play يحمل كل سطر في هذه الصفحة. الملاحظة التي بقيت معي: أغلى خطأ في لعبة تلبيس ليس في الرسم، بل في جدول يُحفظ باليد.