|
3 weeks ago | |
---|---|---|
.. | ||
solution | 4 weeks ago | |
your-work | 4 weeks ago | |
README.md | 3 weeks ago | |
assignment.md | 4 weeks ago |
README.md
بناء لعبة فضاء الجزء السادس: النهاية وإعادة التشغيل
اختبار ما قبل المحاضرة
هناك طرق مختلفة للتعبير عن شرط النهاية في اللعبة. الأمر متروك لك كمُصمم اللعبة لتحديد سبب انتهاء اللعبة. إليك بعض الأسباب، إذا افترضنا أننا نتحدث عن لعبة الفضاء التي كنت تبنيها حتى الآن:
- تم تدمير
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); }
-
إضافة رسالة إعادة التشغيل. أضف هذه الرسالة إلى constant الخاص بالرسائل:
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 = {}; }
-
👽 💥 🚀 تهانينا، أيها القبطان! لعبتك مكتملة! عمل رائع! 🚀 💥 👽
🚀 تحدي
أضف صوتًا! هل يمكنك إضافة صوت لتحسين تجربة اللعب، ربما عند حدوث ضربة ليزر، أو عندما يموت البطل أو يفوز؟ ألقِ نظرة على هذا sandbox لتتعلم كيفية تشغيل الصوت باستخدام JavaScript.
اختبار ما بعد المحاضرة
المراجعة والدراسة الذاتية
مهمتك هي إنشاء لعبة نموذجية جديدة، لذا استكشف بعض الألعاب المثيرة للاهتمام الموجودة لترى نوع اللعبة التي قد تبنيها.
المهمة
إخلاء المسؤولية:
تم ترجمة هذا المستند باستخدام خدمة الترجمة بالذكاء الاصطناعي Co-op Translator. بينما نسعى لتحقيق الدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو معلومات غير دقيقة. يجب اعتبار المستند الأصلي بلغته الأصلية المصدر الموثوق. للحصول على معلومات حاسمة، يُوصى بالاستعانة بترجمة بشرية احترافية. نحن غير مسؤولين عن أي سوء فهم أو تفسيرات خاطئة تنشأ عن استخدام هذه الترجمة.