قم بمطاردة Wumpus أو تجربة كتابة لعبة Android الكلاسيكية

صورة

هل سمعت من قبل Vampus؟ بغض النظر عن الجواب - مرحبا بكم في فترة ولايته!

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

محتوى


1. مقدمة
2. اختيار الأموال
3. فكرة المشروع
4. أنا أشم رائحة
5. أساس الأساسيات - هيكل المشروع
6. جيل من متاهة Vampus والعمل معها
7. تخزين رسائل اللعبة وإخراجها للاعب
8. النتيجة الأولى
9. حتى الألعاب الصغيرة تستحق التاريخ.
10. تحول Vampus والنتيجة النهائية
11. الخاتمة

1. مقدمة


محتوى

أولاً ، بضع كلمات عن نفسك. البرمجة ، لسوء الحظ ، ليست نشاطي الرئيسي ، لكنني سعيد بتكريس وقت فراغي له.

لسبب ما ، اخترت طريقة إنشاء ألعاب محمولة. تم إنشاء مشاريعي السابقة للأجهزة المحمولة في بيئة Qt جنبًا إلى جنب مع لغات QML و C ++. كنت سعيدًا جدًا بهذا الثلاثي ، ومع تحليلي لأفكاري ، أدركت أنه في المستقبل سيستغرق الكثير من الوقت والجهد لحل بعض المشكلات بالوسائل المعروفة لي. لذلك ، بالتفكير في المشروع التالي ، قررت أن أجد أدوات تطوير جديدة أكثر ملاءمة واكتسب خبرة معها.

2. اختيار الأموال


محتوى

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

لم أستخدم AS أو Java من قبل ، وقد واجهت جبهة عملاقة من العمل مع العديد من المهام الجديدة ، وكنت مستعدًا للاندفاع إلى المعركة ، لم يتبق سوى الخروج بمشروع.

3. فكرة المشروع


محتوى

من المعروف أن التدريب يتم على مهام حقيقية ، وخاصة تلك التي تهمك. بالنسبة لي ، كان مثل هذا المشروع التدريبي عبارة عن لعبة شكلت لها عددًا من المتطلبات:

  1. اعادتها القيمة.
  2. بساطة ميكانيكا اللعبة.
  3. الحد الأدنى من استخدام الرسومات.
  4. اللعب يجب أن يجبر اللاعب على التفكير.
  5. يجب أن لا تكون حفلة اللعبة طويلة.
  6. التنفيذ السريع للمشروع (2 أشهر).
  7. بساطة وسهولة واجهة المستخدم.

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

4. أنا أشم رائحة


محتوى
صورة

Vampus Hunting هي لعبة نصية كلاسيكية اخترعها غريغوري يوب في عام 1972. وفي نفس العام ، حصل على وصف للعبة ورمز المصدر في مقال بمجلة.

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

بشكل عام ، لقد أحببت الميكانيكا: إنها بسيطة ، ولكن في الوقت نفسه مع عناصر المخاطرة. لم تكن هناك ألعاب مثيرة للاهتمام على Vampus على Google Play (باستثناء لعبة جديدة في ذلك الوقت في عالم Lovecraft ، والتي ، كما اكتشفت لاحقًا ، كانت تستند إلى نفس ميكانيكا Vampus. ولكن هذا المقال يدور حول إنشاء لعبة على Habré) ، وبالتالي تم قبولها قرار اتخاذ Vampus كأساس. لقد حددت الهدف المتمثل في الحفاظ على اللعبة الكلاسيكية ، ولكن تحديثها قليلاً وإضافة ميزات جديدة.

5. أساس الأساسيات - هيكل المشروع


محتوى

بادئ ذي بدء ، لقد تعلمت قواعد اللعبة الكلاسيكية وتعرفت على مختلف تطبيقات Vampus. ثم قمت بعمل رسم بياني لمنطق اللعبة (قابل للنقر):


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

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

1. ميكانيكا اللعبة

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

2. واجهة المستخدم

  • ما هي الأنشطة التي يجب أن تكون في التطبيق؟ كيف ينبغي أن ننظر وما العناصر التي ينبغي أن تكون عليها؟
  • ما المعلمات يمكن تغييرها في الإعدادات؟
  • هل أحتاج إلى صور في اللعبة؟
  • بشكل عام ، ما هو أسلوب التطبيق (الألوان ، الحالة المزاجية ، نمط الرسالة)؟
  • ما الخطوط للاستخدام؟

3. أخرى

  • الاتصال بخدمات Google play
  • العمل مع ملفات XML
  • ما الخطوط للاستخدام؟

4. كتابة النص للعبة

  • رسائل اللعبة
  • القواعد
  • وصف اللعبة لجوجل بلاي

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

6. جيل من متاهة Vampus والعمل معها


محتوى

Vampus Labyrinth هو dodecahedron ، والذي يمكن تمثيله باعتباره مصفوفة G ذات البعد 20x20. نقوم بترقيم القمم من 0 إلى 19. إذا كان عنصر المصفوفة هو 1 ، فهناك مرور بين القمم (الغرف) ، وإلا ، لا.

نقدم أيضًا مصفوفة 20 × 3 N تخزّن مؤشرات الجيران لكل غرفة. ستعمل هذه المصفوفة على تسريع العمل مع G.


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

//  ""    for (byte i = 0; i < 20; i++) { V[i] = i; } //    ""  for (int i = 0; i < 20; i++) { int tmpRand = random.nextInt(20); byte tmpVar = V[i]; V[i] = V[tmpRand]; V[tmpRand] = tmpVar; } 

وبالتالي ، يتم الحصول على الصورة التالية:


يتم تشكيل Vector V في كل لعبة جديدة ، والتي تمنح اللاعب زنزانة "جديدة".

لتأسيس المراسلات بين فهرس غرفة "true" و "game" ، يتم استخدام طريقة تحويل indByNmb :

 public byte indByNmb(int room) { byte ind = -1; for (byte i = 0; i < V.length; i++) { if (V[i] == room) { ind = i; break; } } return ind; } 

عند الإدخال ، تحصل طريقة indByNmb على مؤشر "لعبة" في غرفة الغرفة ، وفي الإخراج ، تعطي ind "حقيقية".

بعد إنشاء هيكل الأبراج المحصنة ، نضع: قطعان من الخفافيش ، فتحتان ، و Vampus ولاعب:

 byte[] randomRooms = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; for (int i = 0; i < 20; i++) { int tmpRand = random.nextInt(20); byte tmpVar = randomRooms[i]; randomRooms[i] = randomRooms[tmpRand]; randomRooms[tmpRand] = tmpVar; } P = randomRooms[0]; W = randomRooms[1]; Pits[0] = randomRooms[2]; Pits[1] = randomRooms[3]; Bats[0] = randomRooms[4]; Bats[1] = randomRooms[5]; 

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

الجيل الكامل المحصنة على النحو التالي:

قانون
 byte[] V = new byte[20]; // ""  int P; //  , byte W; //   byte[] Bats = new byte[2]; //    , byte[] Pits = new byte[2]; //    public void generateDungeons() { resetVars(); //      for (int i = 0; i < 20; i++) { int tmpRand = random.nextInt(20); byte tmpVar = V[i]; V[i] = V[tmpRand]; V[tmpRand] = tmpVar; } byte[] randomRooms = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; for (int i = 0; i < 20; i++) { int tmpRand = random.nextInt(20); byte tmpVar = randomRooms[i]; randomRooms[i] = randomRooms[tmpRand]; randomRooms[tmpRand] = tmpVar; } P = randomRooms[0]; W = randomRooms[1]; Pits[0] = randomRooms[2]; Pits[1] = randomRooms[3]; Bats[0] = randomRooms[4]; Bats[1] = randomRooms[5]; } 


الآن يمكنك تنفيذ جميع خوارزميات ميكانيكا اللعبة. لذلك ، على سبيل المثال ، يحدث إخراج الغرف المجاورة عندما يدخل اللاعب الغرفة باستخدام فهرس CurrentRoom :

 public void printNearRooms(byte currentRoom) { byte ind = indByNmb(currentRoom); appendText(V[N[ind][0]], V[N[ind][1]], V[N[ind][2]]); } 

عند الإدخال ، تحصل طريقة printNearRooms على فهرس "اللعبة" الحالي لغرفة currentRoom .

النظر في ميكانيكا مثال. دع اللاعب ينتقل إلى غرفة جديدة وتظهر رسالة: "الآن أنا في الغرفة 8". الرقم 8 هو مؤشر الألعاب. مؤشر الغرفة "الحقيقي" هو 6 (انظر الصور أعلاه). تعمل الشفرة على وجه التحديد مع الفهرس "الحقيقي" ، أي 6. بالنسبة لـ 6 ، يتم تحديد مؤشرات الجيران "الحقيقيين": 2 ، 5 ، 7. ستكون "اللعبة" ، على التوالي ، هي: 10 ، 0 ، 7. نعرض اللاعب في السجل: "يمكنني الذهاب إلى الغرف 10 ، 0 ، 7".

وبالتالي ، عند تشكيل كل لعبة جديدة ، المتجه الخامس والعمل مع الفهارس "الحقيقية" و "اللعبة" في الرسم البياني للمتاهة ، يتم إنشاء مظهر حقيقة أن كل لعبة فريدة من نوعها.

بفضل وظيفة appendText ، يتم عرض الرسائل في فاصل زمني محدد. سنلتقي بها لاحقا.

هنا مثال على التحقق من الغرفة لقرب الفئران:

 public boolean isBatsNear() { boolean answer = false; byte indP = indByNmb(P); for (int i = 0; i < 3; i++) { if ((V[N[indP][i]] == Bats[0]) || (V[N[indP][i]] == Bats[1])) { answer = true; break; } } return answer; } 


7. تخزين رسائل اللعبة وإخراجها للاعب


محتوى

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

  • الرسالة الأولى من اللعبة الجديدة.
  • رسالة عندما يتحرك اللاعب.
  • رسالة في محيط الحفر.
  • رسالة عند نقل Vampus.
  • رسالة عند الوقوع في حفرة.

يتم تخزين النص في ملف XML. كل كتلة لديها العديد من خيارات الرسائل من أجل مجموعة متنوعة من اللعب.

مثال على كتلة رسالة يتم عرضها في حالة وجود فتحة في إحدى الغرف المجاورة:

 <string name="g_pitsNear_1">—  \n</string> <string name="g_pitsNear_2">—    \n</string> <string name="g_pitsNear_3">—     \n</string> <string name="g_pitsNear_4">—  , \n</string> <string name="g_pitsNear_5">—   \n</string> <string-array name="g_pitsNear"> <item>@string/g_pitsNear_1</item> <item>@string/g_pitsNear_2</item> <item>@string/g_pitsNear_3</item> <item>@string/g_pitsNear_4</item> <item>@string/g_pitsNear_5</item> </string-array> 

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

إذا ، على سبيل المثال ، عند التحقق من الغرفة ، فإن طريقة isBatsNear الموضحة مسبقًا تُرجع إلى حقيقة ، ثم نحصل على كتلة الرسالة المطلوبة من XML ، ثم نأخذها بشكل عشوائي كوسيطة لـ appendText :

 if (isBatsNear()) { String[] g_batsNear = getResources().getStringArray(R.array.g_batsNear); appendText(g_batsNear[random.nextInt(g_batsNear.length)]); } 

يتم إخراج رسائل اللعبة إلى وحدة التحكم ، والتي هي كائن TextView . لنلقِ نظرة على طريقة appendText .

 public void appendText(final String str) { msgBuffer.add(str); if (!isTimerGameMsgWork) { mTimerGameMsg.run(); isTimerGameMsgWork = true; } } 

عندما يصبح من الضروري عرض رسالة لعبة ، يتم استدعاء طريقة appendText ، والتي تأخذها كوسيطة. في الطريقة نفسها ، تتم إضافة خط أولاً إلى المخزن المؤقت msgBuffer . يتبع ذلك عن طريق التحقق من المتغير المنطقي isTimerGameMsgWork . يقبل ذلك في الحالات التي يتم فيها تشغيل جهاز ضبط الوقت mTimerGameMsg . عندما يعمل هذا المؤقت ، ثم من المخزن المؤقت msgBuffer ، وفقًا لمبدأ FIFO (First In First Out) ، يتم تلقي الرسائل عند الفاصل الزمني المحدد mIntervalGameMsg وإضافتها إلى سجل اللعبة - txtViewGameLog .

رمز إخراج الرسالة الكامل:

قانون
 ArrayList<String> msgBuffer = new ArrayList<>(); Handler mHandlerGameMsg; private int mIntervalGameMsg = 1000; boolean isTimerGameMsgWork = false; public void appendText(final String str) { msgBuffer.add(str); if (!isTimerGameMsgWork) { mTimerGameMsg.run(); isTimerGameMsgWork = true; } } final Runnable mTimerGameMsg = new Runnable() { @Override public void run() { if (msgBuffer.size() == 0) { mHandlerGameMsg.removeCallbacks(mTimerGameMsg); isTimerGameMsgWork = false; } else { txtViewGameLog.append(msgBuffer.get(0)); msgBuffer.remove(0); mHandlerGameMsg.postDelayed(mTimerGameMsg, mIntervalGameMsg); } } }; 



8. النتيجة الأولى


محتوى

بعد شهر من التطوير ، تم استلام أول إصدار قابل للتشغيل من اللعبة مع وظائف مطبقة بالكامل. أرفق لقطات:

لقطات من الإصدار الأول من اللعبة





في لقطات الشاشة المقدمة ، يمكنك رؤية: القائمة الرئيسية ، نافذة القواعد ، نافذة الإعدادات ، نافذة اللعبة.

بالطبع ، فهمت أن النتيجة كانت غير تامة. الشيء الرئيسي هو أنني حصلت على خبرة عملية في AS و Java ، والتي كانت المهمة الأولى.

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

بعد ذلك ، خططت لاستبدال الصور الموجودة (التي التقطتها بلا ضمير من الإنترنت) بالصور التي يرسمها الفنان. ثم أطلق اللعبة في سوق Play وأنسى ذلك بأمان ، بتطبيق الخبرة المكتسبة على مشاريع جديدة. ثم لم أستطع أن أتخيل مقدار Vampus الذي يمكن أن يتغير ...

9. حتى الألعاب الصغيرة تستحق التاريخ.


محتوى

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

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


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

الإصدار الأول من القائمة الرئيسية ، المحرز في شكل منتدى

أما بالنسبة للجوانب الأخرى ، فقد بقيت على حالها تقريبًا: تعمل الفئران بالطريقة نفسها ، وبدأ الدخول في الحفرة يؤدي إلى حدوث تعطل ، وانهيار الكاميرا ونهاية اللعبة (وليس وفاة اللاعب).


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

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




10. تحول Vampus والنتيجة النهائية


محتوى

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

الغرف ، على سبيل المثال ، تم إنشاؤها على النحو التالي:

صورة
هناك 20 غرفة ، جميعها فريدة من نوعها ، ويتلقى اللاعب متاهة "جديدة" في كل لعبة. كيفية جعل كل بلدان جزر المحيط الهادئ لعبة جديدة تعلق على غرف جديدة؟ أبسطها هو استخدام نهج الفهارس "الحقيقي" و "اللعبة":

 public void changeImgOfRoom() { ImageView img = findViewById(R.id.imgRoom); int ind = indByNmb(P); String imgName = "room_" + ind; int id = getResources().getIdentifier(imgName, "drawable", this.getPackageName()); Glide.with(this) .load(id) .transition(DrawableTransitionOptions.withCrossFade()) .into(img); } 

يتم تخزين صور بتنسيق مربع (للحد من التشويه عند العرض على شاشات مختلفة) في الموارد التي تحمل أسماء [room_0؛ room_1. ... ، room_19]. وهم في الواقع مرتبطون بمؤشرات dodecahedron "الحقيقية" ، ولكن بالنسبة للاعب ، فإن كل لعبة جديدة للغرفة نفسها سيكون لها صور مختلفة. لماذا هذا مطلوب؟ من أجل تمكين طرف معين في اللعبة من ربط المعلومات النصية مع صورة غرفة معينة ("نعم ، أتذكر أنه في الغرفة X ، التي كانت غرفة المعيشة ، كان هناك مسودة") وأنه لم ينجح في ذلك "لماذا توجد دائمًا في غرفتي" X هي نفس الصورة؟ " كل شيء من أجل التنوع ومساعدة اللاعب (ومع ذلك ، كما أظهرت التجربة ، لا يوجد أي مساعدة من التحفيظ المرئي ، بل إنه أكثر كفاءة في العمل مع النص).

في النهاية ، حصلنا على نسخة جديدة من اللعبة. وانت تعرف ماذا؟ أصبحت vampus جذابة لعنة ، والأهم من ذلك ، أنها لا تزال نفس Vampus الكلاسيكية ، ولكن في منزل مريح جديد!

لقطات من الإصدار الثاني من اللعبة





في لقطات الشاشة: القائمة الرئيسية ، نافذة القواعد ، نافذة الإعدادات ، نافذة اللعبة.

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


في الفيديو أدناه ، يمكنك رؤية النتيجة النهائية:



11. الخاتمة


محتوى

لقد استلمت الإصدار الأول من اللعبة خلال شهر من التطوير ، حيث تم تخصيص 1-2 ساعات بعد العمل. في الوقت نفسه ، لم يكن AS ولا Java مألوفين لي سابقًا. استغرق الإصدار الثاني من اللعبة 2 أشهر أخرى. وهكذا ، 3 أشهر فقط من العمل على مهل.

بالطبع ، في هذا الشكل ، اللعبة ليست لمجموعة واسعة ، لأن قد يبدو الأمر معقدًا وغير مثير بالنسبة للاعب الحديث ، ولكن الأهم من ذلك ، على الأرجح ، الحفاظ على روح الألعاب الكلاسيكية ، ألا تجدها؟

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

هل هذه اللعبة مثيرة للاهتمام؟ حسنًا ، الأمر ليس متروكًا لي لاتخاذ القرار. لكن دع Vampus مرتاحًا في المنزل الذي بنيناه من أجله باهتمام واهتمام كبيرين.

اتمنى لك التوفيق

شكرا لك واحترس من Vampus!

سكرتير خاص باستمرار المهام الناشئة وفرحة حلها هو بالضبط ما أحب البرمجة ل. آمل أن تحصل على ما لا يقل متعة.

Source: https://habr.com/ru/post/ar462943/


All Articles