11 KiB
بناء لعبة فضاء الجزء السادس: النهاية وإعادة البدء
اختبار ما قبل المحاضرة
هناك طرق مختلفة للتعبير عن شرط النهاية في اللعبة. الأمر متروك لك كمُصمم اللعبة لتحديد سبب انتهاء اللعبة. إليك بعض الأسباب، إذا افترضنا أننا نتحدث عن لعبة الفضاء التي كنت تبنيها حتى الآن:
- تم تدمير
Nمن سفن العدو: من الشائع جدًا إذا قمت بتقسيم اللعبة إلى مستويات مختلفة أن تحتاج إلى تدميرNمن سفن العدو لإكمال المستوى. - تم تدمير سفينتك: هناك بالتأكيد ألعاب تخسر فيها اللعبة إذا تم تدمير سفينتك. نهج شائع آخر هو وجود مفهوم "الحياة". في كل مرة يتم فيها تدمير سفينتك، يتم خصم حياة. بمجرد فقدان جميع الأرواح، تخسر اللعبة.
- لقد جمعت
Nنقطة: شرط نهاية شائع آخر هو جمع النقاط. كيفية الحصول على النقاط متروك لك، ولكن من الشائع جدًا تخصيص نقاط لأنشطة مختلفة مثل تدمير سفينة العدو أو ربما جمع العناصر التي تسقطها السفن عند تدميرها. - إكمال مستوى: قد يتضمن ذلك عدة شروط مثل تدمير
Xسفن العدو، جمعYنقاط، أو ربما جمع عنصر معين.
إعادة البدء
إذا استمتع الناس بلعبتك، فمن المحتمل أن يرغبوا في إعادة لعبها. بمجرد انتهاء اللعبة لأي سبب كان، يجب أن تقدم خيارًا لإعادة البدء.
✅ فكر قليلاً في الظروف التي تجد فيها اللعبة تنتهي، ثم كيف يتم تحفيزك لإعادة البدء.
ما الذي ستبنيه
ستقوم بإضافة هذه القواعد إلى لعبتك:
- الفوز باللعبة. بمجرد تدمير جميع سفن العدو، تفوز باللعبة. بالإضافة إلى ذلك، قم بعرض رسالة انتصار.
- إعادة البدء. بمجرد فقدان جميع الأرواح أو الفوز باللعبة، يجب أن تقدم طريقة لإعادة بدء اللعبة. تذكر! ستحتاج إلى إعادة تهيئة اللعبة ومسح حالة اللعبة السابقة.
الخطوات الموصى بها
حدد الملفات التي تم إنشاؤها لك في مجلد your-work. يجب أن يحتوي على ما يلي:
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| life.png
-| index.html
-| app.js
-| package.json
ابدأ مشروعك في مجلد your_work عن طريق كتابة:
cd your-work
npm start
سيقوم الأمر أعلاه بتشغيل خادم HTTP على العنوان http://localhost:5000. افتح متصفحًا وأدخل هذا العنوان. يجب أن تكون لعبتك في حالة قابلة للعب.
نصيحة: لتجنب التحذيرات في Visual Studio Code، قم بتحرير وظيفة
window.onloadلتستدعيgameLoopIdكما هي (بدونlet)، وقم بتعريفgameLoopIdفي أعلى الملف بشكل مستقل:let gameLoopId;
إضافة الكود
-
تتبع شرط النهاية. أضف كودًا يتتبع عدد الأعداء، أو إذا تم تدمير سفينة البطل عن طريق إضافة هاتين الوظيفتين:
function isHeroDead() { return hero.life <= 0; } function isEnemiesDead() { const enemies = gameObjects.filter((go) => go.type === "Enemy" && !go.dead); return enemies.length === 0; } -
إضافة منطق إلى معالجات الرسائل. قم بتحرير
eventEmitterلمعالجة هذه الشروط:eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => { first.dead = true; second.dead = true; hero.incrementPoints(); if (isEnemiesDead()) { eventEmitter.emit(Messages.GAME_END_WIN); } }); eventEmitter.on(Messages.COLLISION_ENEMY_HERO, (_, { enemy }) => { enemy.dead = true; hero.decrementLife(); if (isHeroDead()) { eventEmitter.emit(Messages.GAME_END_LOSS); return; // loss before victory } if (isEnemiesDead()) { eventEmitter.emit(Messages.GAME_END_WIN); } }); eventEmitter.on(Messages.GAME_END_WIN, () => { endGame(true); }); eventEmitter.on(Messages.GAME_END_LOSS, () => { endGame(false); }); -
إضافة أنواع رسائل جديدة. أضف هذه الرسائل إلى كائن constants:
GAME_END_LOSS: "GAME_END_LOSS", GAME_END_WIN: "GAME_END_WIN", -
إضافة كود إعادة البدء الذي يعيد تشغيل اللعبة عند الضغط على زر محدد.
- الاستماع إلى ضغط مفتاح
Enter. قم بتحرير مستمع الأحداث الخاص بنافذتك للاستماع إلى هذا الضغط:
else if(evt.key === "Enter") { eventEmitter.emit(Messages.KEY_EVENT_ENTER); }-
إضافة رسالة إعادة البدء. أضف هذه الرسالة إلى ثابت Messages:
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
- الاستماع إلى ضغط مفتاح
-
تنفيذ قواعد اللعبة. قم بتنفيذ قواعد اللعبة التالية:
-
شرط فوز اللاعب. عندما يتم تدمير جميع سفن العدو، قم بعرض رسالة انتصار.
- أولاً، قم بإنشاء وظيفة
displayMessage():
function displayMessage(message, color = "red") { ctx.font = "30px Arial"; ctx.fillStyle = color; ctx.textAlign = "center"; ctx.fillText(message, canvas.width / 2, canvas.height / 2); }- قم بإنشاء وظيفة
endGame():
function endGame(win) { clearInterval(gameLoopId); // set a delay so we are sure any paints have finished setTimeout(() => { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); if (win) { displayMessage( "Victory!!! Pew Pew... - Press [Enter] to start a new game Captain Pew Pew", "green" ); } else { displayMessage( "You died !!! Press [Enter] to start a new game Captain Pew Pew" ); } }, 200) } - أولاً، قم بإنشاء وظيفة
-
منطق إعادة البدء. عندما يتم فقدان جميع الأرواح أو يفوز اللاعب باللعبة، قم بعرض أن اللعبة يمكن إعادة تشغيلها. بالإضافة إلى ذلك، قم بإعادة تشغيل اللعبة عند الضغط على مفتاح إعادة البدء (يمكنك تحديد المفتاح الذي يجب أن يتم تعيينه لإعادة البدء).
- قم بإنشاء وظيفة
resetGame():
function resetGame() { if (gameLoopId) { clearInterval(gameLoopId); eventEmitter.clear(); initGame(); gameLoopId = setInterval(() => { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); drawPoints(); drawLife(); updateGameObjects(); drawGameObjects(ctx); }, 100); } } - قم بإنشاء وظيفة
-
أضف استدعاء إلى
eventEmitterلإعادة ضبط اللعبة فيinitGame():eventEmitter.on(Messages.KEY_EVENT_ENTER, () => { resetGame(); }); -
أضف وظيفة
clear()إلى EventEmitter:clear() { this.listeners = {}; }
-
👽 💥 🚀 تهانينا، أيها القبطان! لقد اكتملت لعبتك! عمل رائع! 🚀 💥 👽
تحدي GitHub Copilot Agent 🚀
استخدم وضع Agent لإكمال التحدي التالي:
الوصف: قم بتحسين لعبة الفضاء عن طريق تنفيذ نظام تقدم المستويات مع زيادة الصعوبة والميزات الإضافية.
المهمة: قم بإنشاء نظام لعبة متعدد المستويات حيث يحتوي كل مستوى على المزيد من سفن العدو مع زيادة في السرعة والصحة. أضف مضاعف نقاط يزيد مع كل مستوى، وقم بتنفيذ ميزات إضافية (مثل إطلاق النار السريع أو الدرع) تظهر بشكل عشوائي عند تدمير الأعداء. قم بتضمين مكافأة إكمال المستوى وعرض المستوى الحالي على الشاشة بجانب النقاط الحالية والأرواح.
🚀 التحدي
أضف صوتًا! هل يمكنك إضافة صوت لتحسين تجربة اللعب، ربما عند حدوث ضربة ليزر، أو عندما يموت البطل أو يفوز؟ ألقِ نظرة على هذا sandbox لتتعلم كيفية تشغيل الصوت باستخدام JavaScript.
اختبار ما بعد المحاضرة
المراجعة والدراسة الذاتية
مهمتك هي إنشاء لعبة نموذجية جديدة، لذا استكشف بعض الألعاب المثيرة للاهتمام الموجودة لترى نوع اللعبة التي قد تبنيها.
المهمة
إخلاء المسؤولية:
تم ترجمة هذا المستند باستخدام خدمة الترجمة بالذكاء الاصطناعي Co-op Translator. بينما نسعى لتحقيق الدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو عدم دقة. يجب اعتبار المستند الأصلي بلغته الأصلية المصدر الرسمي. للحصول على معلومات حاسمة، يُوصى بالترجمة البشرية الاحترافية. نحن غير مسؤولين عن أي سوء فهم أو تفسير خاطئ ينشأ عن استخدام هذه الترجمة.