You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/he/6-space-game/6-end-condition/README.md

368 lines
19 KiB

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "46bcdd9a0174031655a49bb062aa279c",
"translation_date": "2025-10-23T01:37:15+00:00",
"source_file": "6-space-game/6-end-condition/README.md",
"language_code": "he"
}
-->
# בניית משחק חלל חלק 6: סיום והתחלה מחדש
כל משחק מעולה זקוק לתנאי סיום ברורים ולמנגנון התחלה מחדש חלק. יצרתם משחק חלל מרשים עם תנועה, קרב וניקוד - עכשיו הגיע הזמן להוסיף את החלקים האחרונים שיהפכו אותו למושלם.
המשחק שלכם כרגע פועל ללא הגבלה, כמו גשושיות וויאג'ר ששיגרה נאס"א בשנת 1977 - ועדיין נעות בחלל עשורים לאחר מכן. בעוד שזה מתאים לחקר החלל, משחקים זקוקים לנקודות סיום מוגדרות כדי ליצור חוויות מספקות.
היום, ניישם תנאי ניצחון/הפסד ומערכת התחלה מחדש. בסוף השיעור הזה, יהיה לכם משחק מלוטש ששחקנים יכולים לסיים ולשחק שוב, בדיוק כמו משחקי הארקייד הקלאסיים שהגדירו את התחום.
## שאלון לפני השיעור
[שאלון לפני השיעור](https://ff-quizzes.netlify.app/web/quiz/39)
## הבנת תנאי סיום במשחקים
מתי המשחק שלכם צריך להסתיים? שאלה בסיסית זו עיצבה את עיצוב המשחקים מאז עידן הארקייד המוקדם. פק-מן מסתיים כשנתפסתם על ידי רוחות רפאים או כשניקיתם את כל הנקודות, בעוד ש-Space Invaders מסתיים כשהחייזרים מגיעים לתחתית או כשאתם משמידים את כולם.
כמפתחי המשחק, אתם מגדירים את תנאי הניצחון וההפסד. עבור משחק החלל שלנו, הנה גישות מוכחות שיוצרות משחקיות מרתקת:
- **השמדת `N` ספינות אויב**: זה די נפוץ אם מחלקים את המשחק לרמות שונות שבהן צריך להשמיד `N` ספינות אויב כדי להשלים רמה.
- **הספינה שלכם הושמדה**: יש בהחלט משחקים שבהם מפסידים אם הספינה שלכם נהרסת. גישה נפוצה נוספת היא שיש מושג של חיים. בכל פעם שהספינה שלכם נהרסת, זה מפחית חיים. ברגע שכל החיים אוזלים, מפסידים את המשחק.
- **צברתם `N` נקודות**: תנאי סיום נפוץ נוסף הוא צבירת נקודות. איך משיגים נקודות תלוי בכם, אבל זה די נפוץ להקצות נקודות לפעילויות שונות כמו השמדת ספינת אויב או אולי איסוף פריטים שהפריטים *משאירים* כשהם נהרסים.
- **השלמת רמה**: זה עשוי לכלול מספר תנאים כמו השמדת `X` ספינות אויב, צבירת `Y` נקודות או אולי איסוף פריט מסוים.
## יישום פונקציונליות התחלה מחדש במשחק
משחקים טובים מעודדים משחק חוזר באמצעות מנגנוני התחלה מחדש חלקים. כאשר שחקנים מסיימים משחק (או מפסידים), הם לעיתים קרובות רוצים לנסות שוב מיד - בין אם כדי לשפר את הניקוד או את הביצועים שלהם.
טטריס מדגים זאת בצורה מושלמת: כאשר הבלוקים שלכם מגיעים לראש, אתם יכולים להתחיל משחק חדש מיד מבלי לנווט בתפריטים מורכבים. נבנה מערכת התחלה מחדש דומה שמאפסה את מצב המשחק בצורה נקייה ומחזירה את השחקנים לפעולה במהירות.
**הרהור**: חשבו על המשחקים ששיחקתם. באילו תנאים הם מסתיימים, וכיצד אתם מתבקשים להתחיל מחדש? מה הופך חוויית התחלה מחדש לחלקה לעומת מתסכלת?
## מה תבנו
תיישמו את התכונות האחרונות שיהפכו את הפרויקט שלכם לחוויית משחק שלמה. אלמנטים אלו מבדילים משחקים מלוטשים מאבות טיפוס בסיסיים.
**הנה מה שנוסיף היום:**
1. **תנאי ניצחון**: השמידו את כל האויבים וקבלו חגיגה ראויה (הרווחתם את זה!)
2. **תנאי הפסד**: נגמרו החיים שלכם ותתמודדו עם מסך הפסד
3. **מנגנון התחלה מחדש**: לחצו Enter כדי לחזור מיד - כי משחק אחד אף פעם לא מספיק
4. **ניהול מצב**: התחלה נקייה בכל פעם - בלי אויבים שנותרו או תקלות מוזרות מהמשחק הקודם
## התחלת העבודה
בואו נכין את סביבת הפיתוח שלכם. עליכם שיהיו כל קבצי משחק החלל שלכם מהשיעורים הקודמים מוכנים.
**הפרויקט שלכם צריך להיראות בערך כך:**
```bash
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| life.png
-| index.html
-| app.js
-| package.json
```
**הפעילו את שרת הפיתוח שלכם:**
```bash
cd your-work
npm start
```
**הפקודה הזו:**
- מפעילה שרת מקומי ב-`http://localhost:5000`
- משרתת את הקבצים שלכם בצורה תקינה
- מתעדכנת אוטומטית כשאתם מבצעים שינויים
פתחו את `http://localhost:5000` בדפדפן שלכם וודאו שהמשחק שלכם פועל. אתם אמורים להיות מסוגלים לזוז, לירות ולתקשר עם אויבים. לאחר שתאשרו זאת, נוכל להמשיך עם היישום.
> 💡 **טיפ מקצועי**: כדי להימנע מאזהרות ב-Visual Studio Code, הכריזו על `gameLoopId` בראש הקובץ שלכם כ-`let gameLoopId;` במקום להכריז עליו בתוך פונקציית `window.onload`. זה עוקב אחר שיטות ההכרזה המודרניות של משתנים ב-JavaScript.
## שלבי היישום
### שלב 1: יצירת פונקציות מעקב לתנאי סיום
אנחנו צריכים פונקציות שיבדקו מתי המשחק צריך להסתיים. כמו חיישנים בתחנת החלל הבינלאומית שמנטרים כל הזמן מערכות קריטיות, הפונקציות הללו יבדקו באופן רציף את מצב המשחק.
```javascript
function isHeroDead() {
return hero.life <= 0;
}
function isEnemiesDead() {
const enemies = gameObjects.filter((go) => go.type === "Enemy" && !go.dead);
return enemies.length === 0;
}
```
**הנה מה שקורה מאחורי הקלעים:**
- **בודק** אם הגיבור שלנו איבד את כל החיים (אוי!)
- **סופר** כמה אויבים עדיין חיים ובועטים
- **מחזיר** `true` כשהשדה קרב נקי מאויבים
- **משתמש** בלוגיקה פשוטה של true/false כדי לשמור על הדברים פשוטים
- **מסנן** את כל אובייקטי המשחק כדי למצוא את השורדים
### שלב 2: עדכון מאזיני אירועים לתנאי סיום
עכשיו נחבר את בדיקות התנאים למערכת האירועים של המשחק. בכל פעם שמתרחשת התנגשות, המשחק יעריך אם היא מפעילה תנאי סיום. זה יוצר משוב מיידי לאירועים קריטיים במשחק.
```javascript
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);
});
```
**מה קורה כאן:**
- **לייזר פוגע באויב**: שניהם נעלמים, אתם מקבלים נקודות, ואנחנו בודקים אם ניצחתם
- **אויב פוגע בכם**: אתם מאבדים חיים, ואנחנו בודקים אם אתם עדיין נושמים
- **סדר חכם**: אנחנו בודקים הפסד קודם (אף אחד לא רוצה לנצח ולהפסיד באותו זמן!)
- **תגובות מיידיות**: ברגע שמשהו חשוב קורה, המשחק יודע על זה
### שלב 3: הוספת קבועי הודעות חדשים
תצטרכו להוסיף סוגי הודעות חדשים לאובייקט הקבועים `Messages` שלכם. קבועים אלו עוזרים לשמור על עקביות ולמנוע שגיאות כתיב במערכת האירועים שלכם.
```javascript
GAME_END_LOSS: "GAME_END_LOSS",
GAME_END_WIN: "GAME_END_WIN",
```
**במה עסקנו כאן:**
- **הוספנו** קבועים לאירועי סיום המשחק כדי לשמור על עקביות
- **השתמשנו** בשמות תיאוריים שמציינים בבירור את מטרת האירוע
- **עקבנו** אחרי תבנית השמות הקיימת לסוגי הודעות
### שלב 4: יישום בקרות התחלה מחדש
עכשיו תוסיפו בקרות מקלדת שיאפשרו לשחקנים להתחיל מחדש את המשחק. מקש Enter הוא בחירה טבעית מכיוון שהוא מזוהה בדרך כלל עם אישור פעולות והתחלת משחקים חדשים.
**הוסיפו זיהוי מקש Enter למאזין האירועים הקיים של keydown:**
```javascript
else if(evt.key === "Enter") {
eventEmitter.emit(Messages.KEY_EVENT_ENTER);
}
```
**הוסיפו את קבוע ההודעה החדש:**
```javascript
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
```
**מה שאתם צריכים לדעת:**
- **מרחיב** את מערכת טיפול באירועי המקלדת הקיימת שלכם
- **משתמש** במקש Enter כטריגר להתחלה מחדש לחוויית משתמש אינטואיטיבית
- **פולט** אירוע מותאם אישית שחלקים אחרים במשחק שלכם יכולים להאזין לו
- **שומר** על אותה תבנית כמו בקרות המקלדת האחרות שלכם
### שלב 5: יצירת מערכת תצוגת הודעות
המשחק שלכם צריך לתקשר תוצאות בצורה ברורה לשחקנים. ניצור מערכת הודעות שמציגה מצבי ניצחון והפסד באמצעות טקסט בצבעים שונים, בדומה לממשקי הטרמינל של מחשבים מוקדמים שבהם ירוק סימן הצלחה ואדום אותת על שגיאות.
**צרו את הפונקציה `displayMessage()`:**
```javascript
function displayMessage(message, color = "red") {
ctx.font = "30px Arial";
ctx.fillStyle = color;
ctx.textAlign = "center";
ctx.fillText(message, canvas.width / 2, canvas.height / 2);
}
```
**שלב אחר שלב, הנה מה שקורה:**
- **מגדיר** את גודל הגופן והמשפחה לטקסט ברור וקריא
- **מיישם** פרמטר צבע עם "אדום" כברירת מחדל לאזהרות
- **מרכז** את הטקסט אופקית ואנכית על הקנבס
- **משתמש** בפרמטרים ברירת מחדל מודרניים של JavaScript לאפשרויות צבע גמישות
- **מנצל** את הקשר 2D של הקנבס לציור טקסט ישיר
**צרו את הפונקציה `endGame()`:**
```javascript
function endGame(win) {
clearInterval(gameLoopId);
// Set a delay to ensure any pending renders complete
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)
}
```
**מה הפונקציה הזו עושה:**
- **מקפיאה** הכל במקום - אין יותר תנועת ספינות או לייזרים
- **לוקחת** הפסקה קטנה (200ms) כדי לתת למסגרת האחרונה לסיים להצטייר
- **מנקה** את המסך ומציירת אותו בשחור לאפקט דרמטי
- **מציגה** הודעות שונות למנצחים ולמפסידים
- **מקודדת** את החדשות בצבעים - ירוק לטוב, אדום ל... טוב, לא כל כך טוב
- **אומרת** לשחקנים בדיוק איך לחזור למשחק
### שלב 6: יישום פונקציונליות איפוס המשחק
מערכת האיפוס צריכה לנקות לחלוטין את מצב המשחק הנוכחי ולהתחיל סשן משחק חדש. זה מבטיח שהשחקנים יקבלו התחלה נקייה בלי נתונים שנותרו מהמשחק הקודם.
**צרו את הפונקציה `resetGame()`:**
```javascript
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);
}
}
```
**בואו נבין כל חלק:**
- **בודק** אם לולאת משחק פועלת כרגע לפני האיפוס
- **מנקה** את לולאת המשחק הקיימת כדי לעצור את כל פעילות המשחק הנוכחית
- **מסיר** את כל מאזיני האירועים כדי למנוע דליפות זיכרון
- **מאתחל** את מצב המשחק עם אובייקטים ומשתנים חדשים
- **מתחיל** לולאת משחק חדשה עם כל הפונקציות החיוניות של המשחק
- **שומר** על אותו מרווח של 100ms לביצועי משחק עקביים
**הוסיפו את מאזין אירוע מקש Enter לפונקציה `initGame()`:**
```javascript
eventEmitter.on(Messages.KEY_EVENT_ENTER, () => {
resetGame();
});
```
**הוסיפו את השיטה `clear()` למחלקה EventEmitter שלכם:**
```javascript
clear() {
this.listeners = {};
}
```
**נקודות מפתח לזכור:**
- **מחבר** את לחיצת מקש Enter לפונקציונליות איפוס המשחק
- **רושם** את מאזין האירועים הזה במהלך אתחול המשחק
- **מספק** דרך נקייה להסיר את כל מאזיני האירועים בין משחקים
- **מונע** דליפות זיכרון על ידי ניקוי מטפלי אירועים בין משחקים
- **מאפס** את אובייקט המאזינים למצב ריק לאתחול חדש
## מזל טוב! 🎉
👽 💥 🚀 הצלחתם לבנות משחק שלם מאפס. כמו המתכנתים שיצרו את משחקי הווידאו הראשונים בשנות ה-70, הפכתם שורות קוד לחוויה אינטראקטיבית עם מכניקת משחק נכונה ומשוב משתמש. 🚀 💥 👽
**הישגיכם:**
- **יישמתם** תנאי ניצחון והפסד מלאים עם משוב משתמש
- **יצרתם** מערכת התחלה מחדש חלקה למשחק רציף
- **עיצבתם** תקשורת חזותית ברורה למצבי משחק
- **ניהלתם** מעברים מורכבים במצב המשחק וניקוי
- **הרכבתם** את כל הרכיבים למשחק שלם שניתן לשחק בו
## אתגר סוכן GitHub Copilot 🚀
השתמשו במצב סוכן כדי להשלים את האתגר הבא:
**תיאור:** שפרו את משחק החלל על ידי יישום מערכת התקדמות רמות עם קושי הולך וגובר ותכונות בונוס.
**הנחיה:** צרו מערכת משחק מרובת רמות שבה לכל רמה יש יותר ספינות אויב עם מהירות ובריאות מוגברות. הוסיפו מכפיל ניקוד שמתגבר עם כל רמה, ויישמו חיזוקים (כמו ירי מהיר או מגן) שמופיעים באופן אקראי כאשר אויבים נהרסים. הוסיפו בונוס על השלמת רמה והציגו את הרמה הנוכחית על המסך לצד הניקוד והחיים הקיימים.
למידע נוסף על [מצב סוכן](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) כאן.
## 🚀 אתגר שיפור אופציונלי
**הוסיפו אודיו למשחק שלכם**: שפרו את חוויית המשחק שלכם על ידי יישום אפקטים קוליים! שקלו להוסיף אודיו עבור:
- **ירי לייזר** כשהשחקן יורה
- **השמדת אויב** כשהספינות נפגעות
- **נזק לגיבור** כשהשחקן נפגע
- **מוזיקת ניצחון** כשהמשחק מנצח
- **צליל הפסד** כשהמשחק מפסיד
**דוגמה ליישום אודיו:**
```javascript
// Create audio objects
const laserSound = new Audio('assets/laser.wav');
const explosionSound = new Audio('assets/explosion.wav');
// Play sounds during game events
function playLaserSound() {
laserSound.currentTime = 0; // Reset to beginning
laserSound.play();
}
```
**מה שאתם צריכים לדעת:**
- **יוצר** אובייקטי אודיו עבור אפקטים קוליים שונים
- **מאפס** את ה-`currentTime` כדי לאפשר אפקטים קוליים מהירים
- **מטפל** במדיניות הפעלה אוטומטית של דפדפנים על ידי הפעלת צלילים מאינטראקציות משתמש
- **מנהל** את עוצמת הקול והתזמון לחוויית משחק טובה יותר
> 💡 **משאב לימודי**: חקרו את [סביבת האודיו הזו](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play) כדי ללמוד עוד על יישום אודיו במשחקי JavaScript.
## שאלון לאחר השיעור
[שאלון לאחר השיעור](https://ff-quizzes.netlify.app/web/quiz/40)
## סקירה ולימוד עצמי
המשימה שלכם היא ליצור דוגמת משחק חדשה, אז חקרו כמה מהמשחקים המעניינים שם כדי לראות איזה סוג משחק אתם עשויים לבנות.
## משימה
[צרו דוגמת משחק](assignment.md)
---
**הצהרת אחריות**:
מסמך זה תורגם באמצעות שירות תרגום AI [Co-op Translator](https://github.com/Azure/co-op-translator). למרות שאנו שואפים לדיוק, יש לקחת בחשבון שתרגומים אוטומטיים עשויים להכיל שגיאות או אי דיוקים. המסמך המקורי בשפתו המקורית צריך להיחשב כמקור סמכותי. עבור מידע קריטי, מומלץ להשתמש בתרגום מקצועי אנושי. איננו אחראים לאי הבנות או לפרשנויות שגויות הנובעות משימוש בתרגום זה.