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

311 lines
16 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": "a6ce295ff03bb49df7a3e17e6e7100a0",
"translation_date": "2025-08-29T11:50:45+00:00",
"source_file": "6-space-game/4-collision-detection/README.md",
"language_code": "bg"
}
-->
# Създаване на космическа игра, част 4: Добавяне на лазер и откриване на сблъсъци
## Предварителен тест
[Предварителен тест](https://ff-quizzes.netlify.app/web/quiz/35)
В този урок ще научите как да стреляте с лазери с помощта на JavaScript! Ще добавим две неща към нашата игра:
- **Лазер**: този лазер се изстрелва от кораба на героя и се движи вертикално нагоре.
- **Откриване на сблъсъци**: като част от реализирането на способността за *стрелба*, ще добавим някои интересни правила за играта:
- **Лазер удря враг**: Врагът умира, ако бъде ударен от лазер.
- **Лазер удря горната част на екрана**: Лазерът се унищожава, ако удари горната част на екрана.
- **Сблъсък между враг и герой**: Врагът и героят се унищожават, ако се сблъскат.
- **Враг удря долната част на екрана**: Врагът и героят се унищожават, ако врагът достигне долната част на екрана.
Накратко, вие -- *героят* -- трябва да унищожите всички врагове с лазер, преди те да успеят да достигнат долната част на екрана.
✅ Направете малко проучване за първата компютърна игра, която някога е била написана. Каква беше нейната функционалност?
Нека бъдем героични заедно!
## Откриване на сблъсъци
Как да откриваме сблъсъци? Трябва да мислим за обектите в играта като за правоъгълници, които се движат. Защо, може би ще попитате? Е, изображението, използвано за рисуване на обект в играта, е правоъгълник: то има `x`, `y`, `width` и `height`.
Ако два правоъгълника, например герой и враг, *се пресекат*, имаме сблъсък. Какво трябва да се случи след това зависи от правилата на играта. За да реализирате откриване на сблъсъци, ви е необходимо следното:
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 или да използвате кода от [Part III- starter](../../../../../../../../../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 сървър на адрес `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. **Добавете слушатели**. Редактирайте функцията `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). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.