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/el/6-space-game/4-collision-detection/README.md

311 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "2e83e38c35dc003f046d7cc0bbfd4920",
"translation_date": "2025-08-26T22:01:32+00:00",
"source_file": "6-space-game/4-collision-detection/README.md",
"language_code": "el"
}
-->
# Δημιουργία Παιχνιδιού Διαστήματος Μέρος 4: Προσθήκη Λέιζερ και Ανίχνευση Συγκρούσεων
## Κουίζ Πριν το Μάθημα
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/35)
Σε αυτό το μάθημα θα μάθετε πώς να πυροβολείτε λέιζερ με JavaScript! Θα προσθέσουμε δύο πράγματα στο παιχνίδι μας:
- **Ένα λέιζερ**: αυτό το λέιζερ εκτοξεύεται από το διαστημόπλοιο του ήρωά σας και κινείται κάθετα προς τα πάνω.
- **Ανίχνευση συγκρούσεων**, ως μέρος της υλοποίησης της δυνατότητας να *πυροβολείτε*, θα προσθέσουμε και κάποιους ωραίους κανόνες παιχνιδιού:
- **Το λέιζερ χτυπάει εχθρό**: Ο εχθρός πεθαίνει αν χτυπηθεί από λέιζερ.
- **Το λέιζερ χτυπάει την κορυφή της οθόνης**: Το λέιζερ καταστρέφεται αν φτάσει στην κορυφή της οθόνης.
- **Σύγκρουση εχθρού και ήρωα**: Εχθρός και ήρωας καταστρέφονται αν συγκρουστούν.
- **Ο εχθρός φτάνει στο κάτω μέρος της οθόνης**: Εχθρός και ήρωας καταστρέφονται αν ο εχθρός φτάσει στο κάτω μέρος της οθόνης.
Με λίγα λόγια, εσείς -- *ο ήρωας* -- πρέπει να χτυπήσετε όλους τους εχθρούς με λέιζερ πριν καταφέρουν να φτάσουν στο κάτω μέρος της οθόνης.
✅ Κάντε μια μικρή έρευνα για το πρώτο παιχνίδι υπολογιστή που δημιουργήθηκε ποτέ. Ποια ήταν η λειτουργικότητά του;
Ας γίνουμε ηρωικοί μαζί!
## Ανίχνευση Συγκρούσεων
Πώς κάνουμε ανίχνευση συγκρούσεων; Πρέπει να σκεφτούμε τα αντικείμενα του παιχνιδιού μας ως ορθογώνια που κινούνται. Γιατί αυτό, μπορεί να ρωτήσετε; Λοιπόν, η εικόνα που χρησιμοποιείται για να σχεδιάσει ένα αντικείμενο παιχνιδιού είναι ένα ορθογώνιο: έχει `x`, `y`, `πλάτος` και `ύψος`.
Αν δύο ορθογώνια, δηλαδή ένας ήρωας και ένας εχθρός, *τέμνονται*, έχουμε σύγκρουση. Τι πρέπει να συμβεί τότε εξαρτάται από τους κανόνες του παιχνιδιού. Για να υλοποιήσετε την ανίχνευση συγκρούσεων, χρειάζεστε τα εξής:
1. Έναν τρόπο να αποκτήσετε μια ορθογώνια αναπαράσταση ενός αντικειμένου παιχνιδιού, κάτι σαν αυτό:
```javascript
rectFromGameObject() {
return {
top: this.y,
left: this.x,
bottom: this.y + this.height,
right: this.x + this.width
}
}
```
2. Μια συνάρτηση σύγκρισης, η οποία μπορεί να μοιάζει κάπως έτσι:
```javascript
function intersectRect(r1, r2) {
return !(r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top);
}
```
## Πώς καταστρέφουμε αντικείμενα
Για να καταστρέψετε αντικείμενα σε ένα παιχνίδι, πρέπει να ενημερώσετε το παιχνίδι ότι δεν πρέπει πλέον να σχεδιάζει αυτό το αντικείμενο στον βρόχο του παιχνιδιού που ενεργοποιείται σε ένα συγκεκριμένο διάστημα. Ένας τρόπος να το κάνετε αυτό είναι να χαρακτηρίσετε ένα αντικείμενο παιχνιδιού ως *νεκρό* όταν συμβεί κάτι, όπως αυτό:
```javascript
// collision happened
enemy.dead = true
```
Στη συνέχεια, μπορείτε να φιλτράρετε τα *νεκρά* αντικείμενα πριν ξανασχεδιάσετε την οθόνη, όπως αυτό:
```javascript
gameObjects = gameObject.filter(go => !go.dead);
```
## Πώς πυροβολούμε ένα λέιζερ
Το να πυροβολήσετε ένα λέιζερ σημαίνει να ανταποκριθείτε σε ένα γεγονός πλήκτρου και να δημιουργήσετε ένα αντικείμενο που κινείται προς μια συγκεκριμένη κατεύθυνση. Πρέπει λοιπόν να εκτελέσουμε τα εξής βήματα:
1. **Δημιουργία ενός αντικειμένου λέιζερ**: από την κορυφή του διαστημοπλοίου του ήρωά μας, το οποίο μόλις δημιουργηθεί αρχίζει να κινείται προς τα πάνω.
2. **Σύνδεση κώδικα σε ένα γεγονός πλήκτρου**: πρέπει να επιλέξουμε ένα πλήκτρο στο πληκτρολόγιο που θα αντιπροσωπεύει την ενέργεια του παίκτη να πυροβολήσει το λέιζερ.
3. **Δημιουργία ενός αντικειμένου παιχνιδιού που μοιάζει με λέιζερ** όταν πατηθεί το πλήκτρο.
## Χρονικό διάστημα για το λέιζερ
Το λέιζερ πρέπει να πυροβολείται κάθε φορά που πατάτε ένα πλήκτρο, όπως το *space* για παράδειγμα. Για να αποτρέψουμε το παιχνίδι από το να δημιουργεί πάρα πολλά λέιζερ σε σύντομο χρονικό διάστημα, πρέπει να διορθώσουμε αυτό το πρόβλημα. Η λύση είναι να υλοποιήσουμε ένα λεγόμενο *χρονικό διάστημα*, έναν χρονοδιακόπτη, που διασφαλίζει ότι ένα λέιζερ μπορεί να πυροβοληθεί μόνο κάθε τόσο. Μπορείτε να το υλοποιήσετε με τον εξής τρόπο:
```javascript
class Cooldown {
constructor(time) {
this.cool = false;
setTimeout(() => {
this.cool = true;
}, time)
}
}
class Weapon {
constructor {
}
fire() {
if (!this.cooldown || this.cooldown.cool) {
// produce a laser
this.cooldown = new Cooldown(500);
} else {
// do nothing - it hasn't cooled down yet.
}
}
}
```
Ανατρέξτε στο μάθημα 1 της σειράς παιχνιδιών διαστήματος για να θυμηθείτε τα *χρονικά διαστήματα*.
## Τι να δημιουργήσετε
Θα πάρετε τον υπάρχοντα κώδικα (τον οποίο θα πρέπει να έχετε καθαρίσει και αναδιαρθρώσει) από το προηγούμενο μάθημα και θα τον επεκτείνετε. Ξεκινήστε είτε με τον κώδικα από το μέρος II είτε χρησιμοποιήστε τον κώδικα από το [Μέρος III - αρχικό](../../../../../../../../../your-work).
> συμβουλή: το λέιζερ με το οποίο θα δουλέψετε βρίσκεται ήδη στον φάκελο των πόρων σας και αναφέρεται στον κώδικά σας.
- **Προσθέστε ανίχνευση συγκρούσεων**, όταν ένα λέιζερ συγκρούεται με κάτι, οι παρακάτω κανόνες πρέπει να ισχύουν:
1. **Το λέιζερ χτυπάει εχθρό**: ο εχθρός πεθαίνει αν χτυπηθεί από λέιζερ.
2. **Το λέιζερ χτυπάει την κορυφή της οθόνης**: Το λέιζερ καταστρέφεται αν φτάσει στην κορυφή της οθόνης.
3. **Σύγκρουση εχθρού και ήρωα**: ένας εχθρός και ο ήρωας καταστρέφονται αν συγκρουστούν.
4. **Ο εχθρός φτάνει στο κάτω μέρος της οθόνης**: ένας εχθρός και ο ήρωας καταστρέφονται αν ο εχθρός φτάσει στο κάτω μέρος της οθόνης.
## Προτεινόμενα βήματα
Βρείτε τα αρχεία που έχουν δημιουργηθεί για εσάς στον υποφάκελο `your-work`. Θα πρέπει να περιέχει τα εξής:
```bash
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| index.html
-| app.js
-| package.json
```
Ξεκινήστε το πρότζεκτ σας στον φάκελο `your_work` πληκτρολογώντας:
```bash
cd your-work
npm start
```
Το παραπάνω θα ξεκινήσει έναν HTTP Server στη διεύθυνση `http://localhost:5000`. Ανοίξτε έναν περιηγητή και εισάγετε αυτή τη διεύθυνση. Προς το παρόν, θα πρέπει να εμφανίζεται ο ήρωας και όλοι οι εχθροί, αλλά τίποτα δεν κινείται - ακόμα :).
### Προσθέστε κώδικα
1. **Ρυθμίστε μια ορθογώνια αναπαράσταση του αντικειμένου παιχνιδιού σας για να χειριστείτε συγκρούσεις**. Ο παρακάτω κώδικας σας επιτρέπει να αποκτήσετε μια ορθογώνια αναπαράσταση ενός `GameObject`. Επεξεργαστείτε την κλάση GameObject για να την επεκτείνετε:
```javascript
rectFromGameObject() {
return {
top: this.y,
left: this.x,
bottom: this.y + this.height,
right: this.x + this.width,
};
}
```
2. **Προσθέστε κώδικα που ελέγχει συγκρούσεις**. Αυτή θα είναι μια νέα συνάρτηση που ελέγχει αν δύο ορθογώνια τέμνονται:
```javascript
function intersectRect(r1, r2) {
return !(
r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top
);
}
```
3. **Προσθέστε δυνατότητα πυροβολισμού λέιζερ**
1. **Προσθέστε μήνυμα γεγονότος πλήκτρου**. Το πλήκτρο *space* θα πρέπει να δημιουργεί ένα λέιζερ ακριβώς πάνω από το διαστημόπλοιο του ήρωα. Προσθέστε τρεις σταθερές στο αντικείμενο Messages:
```javascript
KEY_EVENT_SPACE: "KEY_EVENT_SPACE",
COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER",
COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
```
1. **Χειριστείτε το πλήκτρο space**. Επεξεργαστείτε τη συνάρτηση `window.addEventListener` keyup για να χειριστείτε το πλήκτρο space:
```javascript
} else if(evt.keyCode === 32) {
eventEmitter.emit(Messages.KEY_EVENT_SPACE);
}
```
1. **Προσθέστε listeners**. Επεξεργαστείτε τη συνάρτηση `initGame()` για να διασφαλίσετε ότι ο ήρωας μπορεί να πυροβολήσει όταν πατηθεί το πλήκτρο space:
```javascript
eventEmitter.on(Messages.KEY_EVENT_SPACE, () => {
if (hero.canFire()) {
hero.fire();
}
```
και προσθέστε μια νέα συνάρτηση `eventEmitter.on()` για να διασφαλίσετε τη συμπεριφορά όταν ένας εχθρός συγκρούεται με ένα λέιζερ:
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
first.dead = true;
second.dead = true;
})
```
1. **Κινήστε το αντικείμενο**, Διασφαλίστε ότι το λέιζερ κινείται σταδιακά προς την κορυφή της οθόνης. Θα δημιουργήσετε μια νέα κλάση Laser που επεκτείνει το `GameObject`, όπως κάνατε πριν:
```javascript
class Laser extends GameObject {
constructor(x, y) {
super(x,y);
(this.width = 9), (this.height = 33);
this.type = 'Laser';
this.img = laserImg;
let id = setInterval(() => {
if (this.y > 0) {
this.y -= 15;
} else {
this.dead = true;
clearInterval(id);
}
}, 100)
}
}
```
1. **Χειριστείτε συγκρούσεις**, Υλοποιήστε κανόνες συγκρούσεων για το λέιζερ. Προσθέστε μια συνάρτηση `updateGameObjects()` που ελέγχει τα αντικείμενα για συγκρούσεις:
```javascript
function updateGameObjects() {
const enemies = gameObjects.filter(go => go.type === 'Enemy');
const lasers = gameObjects.filter((go) => go.type === "Laser");
// laser hit something
lasers.forEach((l) => {
enemies.forEach((m) => {
if (intersectRect(l.rectFromGameObject(), m.rectFromGameObject())) {
eventEmitter.emit(Messages.COLLISION_ENEMY_LASER, {
first: l,
second: m,
});
}
});
});
gameObjects = gameObjects.filter(go => !go.dead);
}
```
Βεβαιωθείτε ότι προσθέσατε τη `updateGameObjects()` στον βρόχο του παιχνιδιού στο `window.onload`.
4. **Υλοποιήστε χρονικό διάστημα** για το λέιζερ, ώστε να μπορεί να πυροβολείται μόνο κάθε τόσο.
Τέλος, επεξεργαστείτε την κλάση Hero ώστε να μπορεί να έχει χρονικό διάστημα:
```javascript
class Hero extends GameObject {
constructor(x, y) {
super(x, y);
(this.width = 99), (this.height = 75);
this.type = "Hero";
this.speed = { x: 0, y: 0 };
this.cooldown = 0;
}
fire() {
gameObjects.push(new Laser(this.x + 45, this.y - 10));
this.cooldown = 500;
let id = setInterval(() => {
if (this.cooldown > 0) {
this.cooldown -= 100;
} else {
clearInterval(id);
}
}, 200);
}
canFire() {
return this.cooldown === 0;
}
}
```
Σε αυτό το σημείο, το παιχνίδι σας έχει κάποια λειτουργικότητα! Μπορείτε να πλοηγηθείτε με τα πλήκτρα βελών, να πυροβολήσετε λέιζερ με το πλήκτρο space και οι εχθροί εξαφανίζονται όταν τους χτυπάτε. Μπράβο!
---
## 🚀 Πρόκληση
Προσθέστε μια έκρηξη! Ρίξτε μια ματιά στα γραφικά του παιχνιδιού στον [φάκελο Space Art](../../../../6-space-game/solution/spaceArt/readme.txt) και προσπαθήστε να προσθέσετε μια έκρηξη όταν το λέιζερ χτυπάει έναν εξωγήινο.
## Κουίζ Μετά το Μάθημα
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/36)
## Ανασκόπηση & Αυτομελέτη
Πειραματιστείτε με τα διαστήματα στο παιχνίδι σας μέχρι τώρα. Τι συμβαίνει όταν τα αλλάζετε; Διαβάστε περισσότερα για τα [χρονικά γεγονότα της JavaScript](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/).
## Εργασία
[Εξερευνήστε τις συγκρούσεις](assignment.md)
---
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.