|
|
<!--
|
|
|
CO_OP_TRANSLATOR_METADATA:
|
|
|
{
|
|
|
"original_hash": "05be6c37791668e3719c4fba94566367",
|
|
|
"translation_date": "2025-08-29T07:11:10+00:00",
|
|
|
"source_file": "6-space-game/6-end-condition/README.md",
|
|
|
"language_code": "el"
|
|
|
}
|
|
|
-->
|
|
|
# Δημιουργία ενός Παιχνιδιού Διαστήματος Μέρος 6: Τέλος και Επανεκκίνηση
|
|
|
|
|
|
## Κουίζ πριν το μάθημα
|
|
|
|
|
|
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/39)
|
|
|
|
|
|
Υπάρχουν διάφοροι τρόποι να εκφράσετε μια *συνθήκη τέλους* σε ένα παιχνίδι. Εσείς, ως δημιουργός του παιχνιδιού, αποφασίζετε γιατί το παιχνίδι τελειώνει. Εδώ είναι μερικοί λόγοι, αν υποθέσουμε ότι μιλάμε για το παιχνίδι διαστήματος που έχετε δημιουργήσει μέχρι τώρα:
|
|
|
|
|
|
- **`N` Εχθρικά σκάφη έχουν καταστραφεί**: Είναι αρκετά συνηθισμένο, αν χωρίζετε το παιχνίδι σε διαφορετικά επίπεδα, να χρειάζεται να καταστρέψετε `N` εχθρικά σκάφη για να ολοκληρώσετε ένα επίπεδο.
|
|
|
- **Το σκάφος σας έχει καταστραφεί**: Υπάρχουν σίγουρα παιχνίδια όπου χάνετε αν το σκάφος σας καταστραφεί. Μια άλλη κοινή προσέγγιση είναι η έννοια των ζωών. Κάθε φορά που το σκάφος σας καταστρέφεται, χάνετε μία ζωή. Όταν όλες οι ζωές χαθούν, τότε χάνετε το παιχνίδι.
|
|
|
- **Έχετε συλλέξει `N` πόντους**: Μια άλλη συνηθισμένη συνθήκη τέλους είναι να συλλέξετε πόντους. Το πώς κερδίζετε πόντους εξαρτάται από εσάς, αλλά είναι αρκετά συνηθισμένο να αποδίδονται πόντοι σε διάφορες δραστηριότητες, όπως η καταστροφή ενός εχθρικού σκάφους ή η συλλογή αντικειμένων που *πέφτουν* όταν καταστρέφονται.
|
|
|
- **Ολοκλήρωση ενός επιπέδου**: Αυτό μπορεί να περιλαμβάνει διάφορες συνθήκες, όπως `X` εχθρικά σκάφη που καταστράφηκαν, `Y` πόντους που συλλέχθηκαν ή ίσως τη συλλογή ενός συγκεκριμένου αντικειμένου.
|
|
|
|
|
|
## Επανεκκίνηση
|
|
|
|
|
|
Αν οι παίκτες απολαμβάνουν το παιχνίδι σας, είναι πιθανό να θέλουν να το παίξουν ξανά. Όταν το παιχνίδι τελειώνει για οποιονδήποτε λόγο, θα πρέπει να προσφέρετε μια επιλογή επανεκκίνησης.
|
|
|
|
|
|
✅ Σκεφτείτε λίγο υπό ποιες συνθήκες τελειώνει ένα παιχνίδι και πώς σας προτρέπουν να το επανεκκινήσετε.
|
|
|
|
|
|
## Τι να δημιουργήσετε
|
|
|
|
|
|
Θα προσθέσετε αυτούς τους κανόνες στο παιχνίδι σας:
|
|
|
|
|
|
1. **Νίκη στο παιχνίδι**. Όταν όλα τα εχθρικά σκάφη έχουν καταστραφεί, κερδίζετε το παιχνίδι. Επιπλέον, εμφανίστε κάποιο μήνυμα νίκης.
|
|
|
1. **Επανεκκίνηση**. Όταν όλες οι ζωές σας χαθούν ή το παιχνίδι κερδηθεί, θα πρέπει να προσφέρετε έναν τρόπο επανεκκίνησης του παιχνιδιού. Θυμηθείτε! Θα χρειαστεί να επανεκκινήσετε το παιχνίδι και να καθαρίσετε την προηγούμενη κατάσταση του παιχνιδιού.
|
|
|
|
|
|
## Προτεινόμενα βήματα
|
|
|
|
|
|
Βρείτε τα αρχεία που έχουν δημιουργηθεί για εσάς στον υποφάκελο `your-work`. Θα πρέπει να περιέχει τα εξής:
|
|
|
|
|
|
```bash
|
|
|
-| assets
|
|
|
-| enemyShip.png
|
|
|
-| player.png
|
|
|
-| laserRed.png
|
|
|
-| life.png
|
|
|
-| index.html
|
|
|
-| app.js
|
|
|
-| package.json
|
|
|
```
|
|
|
|
|
|
Ξεκινήστε το πρότζεκτ σας στον φάκελο `your_work` πληκτρολογώντας:
|
|
|
|
|
|
```bash
|
|
|
cd your-work
|
|
|
npm start
|
|
|
```
|
|
|
|
|
|
Το παραπάνω θα ξεκινήσει έναν HTTP Server στη διεύθυνση `http://localhost:5000`. Ανοίξτε έναν περιηγητή και εισάγετε αυτή τη διεύθυνση. Το παιχνίδι σας θα πρέπει να είναι σε κατάσταση που μπορεί να παιχτεί.
|
|
|
|
|
|
> συμβουλή: για να αποφύγετε προειδοποιήσεις στο Visual Studio Code, επεξεργαστείτε τη συνάρτηση `window.onload` ώστε να καλεί το `gameLoopId` όπως είναι (χωρίς `let`), και δηλώστε το `gameLoopId` στην κορυφή του αρχείου, ανεξάρτητα: `let gameLoopId;`
|
|
|
|
|
|
### Προσθήκη κώδικα
|
|
|
|
|
|
1. **Παρακολούθηση συνθήκης τέλους**. Προσθέστε κώδικα που παρακολουθεί τον αριθμό των εχθρών ή αν το σκάφος του ήρωα έχει καταστραφεί, προσθέτοντας αυτές τις δύο συναρτήσεις:
|
|
|
|
|
|
```javascript
|
|
|
function isHeroDead() {
|
|
|
return hero.life <= 0;
|
|
|
}
|
|
|
|
|
|
function isEnemiesDead() {
|
|
|
const enemies = gameObjects.filter((go) => go.type === "Enemy" && !go.dead);
|
|
|
return enemies.length === 0;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
1. **Προσθήκη λογικής στους διαχειριστές μηνυμάτων**. Επεξεργαστείτε το `eventEmitter` για να χειρίζεται αυτές τις συνθήκες:
|
|
|
|
|
|
```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);
|
|
|
});
|
|
|
```
|
|
|
|
|
|
1. **Προσθήκη νέων τύπων μηνυμάτων**. Προσθέστε αυτά τα Μηνύματα στο αντικείμενο constants:
|
|
|
|
|
|
```javascript
|
|
|
GAME_END_LOSS: "GAME_END_LOSS",
|
|
|
GAME_END_WIN: "GAME_END_WIN",
|
|
|
```
|
|
|
|
|
|
2. **Προσθήκη κώδικα επανεκκίνησης** που επανεκκινεί το παιχνίδι με το πάτημα ενός επιλεγμένου κουμπιού.
|
|
|
|
|
|
1. **Ακρόαση για πάτημα πλήκτρου `Enter`**. Επεξεργαστείτε τον eventListener του παραθύρου σας για να ακούει αυτό το πάτημα:
|
|
|
|
|
|
```javascript
|
|
|
else if(evt.key === "Enter") {
|
|
|
eventEmitter.emit(Messages.KEY_EVENT_ENTER);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
1. **Προσθήκη μηνύματος επανεκκίνησης**. Προσθέστε αυτό το Μήνυμα στο constant Messages:
|
|
|
|
|
|
```javascript
|
|
|
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
|
|
|
```
|
|
|
|
|
|
1. **Υλοποίηση κανόνων παιχνιδιού**. Υλοποιήστε τους παρακάτω κανόνες παιχνιδιού:
|
|
|
|
|
|
1. **Συνθήκη νίκης παίκτη**. Όταν όλα τα εχθρικά σκάφη καταστραφούν, εμφανίστε ένα μήνυμα νίκης.
|
|
|
|
|
|
1. Πρώτα, δημιουργήστε μια συνάρτηση `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);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
1. Δημιουργήστε μια συνάρτηση `endGame()`:
|
|
|
|
|
|
```javascript
|
|
|
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)
|
|
|
}
|
|
|
```
|
|
|
|
|
|
1. **Λογική επανεκκίνησης**. Όταν όλες οι ζωές χαθούν ή ο παίκτης κερδίσει το παιχνίδι, εμφανίστε ότι το παιχνίδι μπορεί να επανεκκινηθεί. Επιπλέον, επανεκκινήστε το παιχνίδι όταν πατηθεί το πλήκτρο επανεκκίνησης (μπορείτε να αποφασίσετε ποιο πλήκτρο θα αντιστοιχεί στην επανεκκίνηση).
|
|
|
|
|
|
1. Δημιουργήστε τη συνάρτηση `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);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
1. Προσθέστε μια κλήση στο `eventEmitter` για να επανεκκινήσει το παιχνίδι στη `initGame()`:
|
|
|
|
|
|
```javascript
|
|
|
eventEmitter.on(Messages.KEY_EVENT_ENTER, () => {
|
|
|
resetGame();
|
|
|
});
|
|
|
```
|
|
|
|
|
|
1. Προσθέστε μια συνάρτηση `clear()` στο EventEmitter:
|
|
|
|
|
|
```javascript
|
|
|
clear() {
|
|
|
this.listeners = {};
|
|
|
}
|
|
|
```
|
|
|
|
|
|
👽 💥 🚀 Συγχαρητήρια, Καπετάνιε! Το παιχνίδι σας είναι ολοκληρωμένο! Μπράβο! 🚀 💥 👽
|
|
|
|
|
|
---
|
|
|
|
|
|
## 🚀 Πρόκληση
|
|
|
|
|
|
Προσθέστε έναν ήχο! Μπορείτε να προσθέσετε έναν ήχο για να βελτιώσετε την εμπειρία παιχνιδιού, ίσως όταν υπάρχει χτύπημα λέιζερ, ή όταν ο ήρωας πεθαίνει ή κερδίζει; Ρίξτε μια ματιά σε αυτό το [sandbox](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play) για να μάθετε πώς να παίζετε ήχο χρησιμοποιώντας JavaScript.
|
|
|
|
|
|
## Κουίζ μετά το μάθημα
|
|
|
|
|
|
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/40)
|
|
|
|
|
|
## Ανασκόπηση & Αυτομελέτη
|
|
|
|
|
|
Η εργασία σας είναι να δημιουργήσετε ένα νέο δείγμα παιχνιδιού, οπότε εξερευνήστε μερικά ενδιαφέροντα παιχνίδια εκεί έξω για να δείτε τι είδους παιχνίδι μπορείτε να δημιουργήσετε.
|
|
|
|
|
|
## Εργασία
|
|
|
|
|
|
[Δημιουργία ενός Δείγματος Παιχνιδιού](assignment.md)
|
|
|
|
|
|
---
|
|
|
|
|
|
**Αποποίηση Ευθύνης**:
|
|
|
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης. |