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

463 lines
18 KiB

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "4b1d441cfd31924084956000c0fee5a5",
"translation_date": "2025-10-22T23:15:25+00:00",
"source_file": "6-space-game/4-collision-detection/README.md",
"language_code": "br"
}
-->
# Construa um Jogo Espacial Parte 4: Adicionando um Laser e Detectando Colisões
## Quiz Pré-Aula
[Quiz pré-aula](https://ff-quizzes.netlify.app/web/quiz/35)
Pense no momento em Star Wars quando os torpedos de prótons de Luke atingem o porto de exaustão da Estrela da Morte. Essa detecção precisa de colisão mudou o destino da galáxia! Nos jogos, a detecção de colisão funciona da mesma forma - ela determina quando os objetos interagem e o que acontece em seguida.
Nesta lição, você adicionará armas de laser ao seu jogo espacial e implementará a detecção de colisões. Assim como os planejadores de missão da NASA calculam as trajetórias das espaçonaves para evitar detritos, você aprenderá a detectar quando os objetos do jogo se intersectam. Vamos dividir isso em etapas gerenciáveis que se complementam.
Ao final, você terá um sistema de combate funcional onde lasers destroem inimigos e colisões desencadeiam eventos no jogo. Esses mesmos princípios de colisão são usados em tudo, desde simulações de física até interfaces web interativas.
✅ Faça uma pequena pesquisa sobre o primeiro jogo de computador já criado. Qual era sua funcionalidade?
## Detecção de colisão
A detecção de colisão funciona como os sensores de proximidade do módulo lunar Apollo - verifica constantemente as distâncias e dispara alertas quando os objetos se aproximam demais. Nos jogos, esse sistema determina quando os objetos interagem e o que deve acontecer em seguida.
A abordagem que usaremos trata cada objeto do jogo como um retângulo, semelhante à forma como os sistemas de controle de tráfego aéreo usam formas geométricas simplificadas para rastrear aeronaves. Esse método retangular pode parecer básico, mas é computacionalmente eficiente e funciona bem para a maioria dos cenários de jogos.
### Representação de retângulo
Cada objeto do jogo precisa de limites de coordenadas, semelhante à forma como o rover Mars Pathfinder mapeou sua localização na superfície marciana. Veja como definimos essas coordenadas de limite:
```javascript
rectFromGameObject() {
return {
top: this.y,
left: this.x,
bottom: this.y + this.height,
right: this.x + this.width
}
}
```
**Vamos detalhar isso:**
- **Borda superior**: É onde seu objeto começa verticalmente (sua posição y)
- **Borda esquerda**: Onde começa horizontalmente (sua posição x)
- **Borda inferior**: Adicione a altura à posição y - agora você sabe onde termina!
- **Borda direita**: Adicione a largura à posição x - e você tem o limite completo
### Algoritmo de interseção
Detectar interseções de retângulos usa uma lógica semelhante à forma como o Telescópio Espacial Hubble determina se objetos celestiais estão se sobrepondo em seu campo de visão. O algoritmo verifica a separação:
```javascript
function intersectRect(r1, r2) {
return !(r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top);
}
```
**O teste de separação funciona como sistemas de radar:**
- O retângulo 2 está completamente à direita do retângulo 1?
- O retângulo 2 está completamente à esquerda do retângulo 1?
- O retângulo 2 está completamente abaixo do retângulo 1?
- O retângulo 2 está completamente acima do retângulo 1?
Se nenhuma dessas condições for verdadeira, os retângulos devem estar se sobrepondo. Essa abordagem reflete como os operadores de radar determinam se duas aeronaves estão a distâncias seguras.
## Gerenciando ciclos de vida dos objetos
Quando um laser atinge um inimigo, ambos os objetos precisam ser removidos do jogo. No entanto, excluir objetos no meio do loop pode causar falhas - uma lição aprendida da maneira mais difícil em sistemas de computador antigos, como o Computador de Orientação Apollo. Em vez disso, usamos uma abordagem de "marcar para exclusão" que remove objetos com segurança entre os quadros.
Veja como marcamos algo para remoção:
```javascript
// Mark object for removal
enemy.dead = true;
```
**Por que essa abordagem funciona:**
- Marcamos o objeto como "morto", mas não o excluímos imediatamente
- Isso permite que o quadro atual do jogo termine com segurança
- Sem falhas ao tentar usar algo que já foi removido!
Depois, filtramos os objetos marcados antes do próximo ciclo de renderização:
```javascript
gameObjects = gameObjects.filter(go => !go.dead);
```
**O que essa filtragem faz:**
- Cria uma lista nova com apenas os objetos "vivos"
- Descarta tudo que foi marcado como morto
- Mantém seu jogo funcionando sem problemas
- Evita o acúmulo de objetos destruídos na memória
## Implementando mecânica de laser
Projéteis de laser em jogos funcionam no mesmo princípio que torpedos de fótons em Star Trek - são objetos discretos que viajam em linhas retas até atingirem algo. Cada pressionamento da barra de espaço cria um novo objeto de laser que se move pela tela.
Para fazer isso funcionar, precisamos coordenar algumas peças diferentes:
**Componentes principais para implementar:**
- **Criar** objetos de laser que surgem na posição do herói
- **Lidar** com entrada do teclado para acionar a criação do laser
- **Gerenciar** o movimento e o ciclo de vida do laser
- **Implementar** representação visual para os projéteis de laser
## Implementando controle de taxa de disparo
Taxas de disparo ilimitadas sobrecarregariam o motor do jogo e tornariam o jogo muito fácil. Sistemas de armas reais enfrentam restrições semelhantes - até os phasers da USS Enterprise precisavam de tempo para recarregar entre os disparos.
Implementaremos um sistema de cooldown que impede disparos rápidos enquanto mantém controles responsivos:
```javascript
class Cooldown {
constructor(time) {
this.cool = false;
setTimeout(() => {
this.cool = true;
}, time);
}
}
class Weapon {
constructor() {
this.cooldown = null;
}
fire() {
if (!this.cooldown || this.cooldown.cool) {
// Create laser projectile
this.cooldown = new Cooldown(500);
} else {
// Weapon is still cooling down
}
}
}
```
**Como o cooldown funciona:**
- Quando criado, a arma começa "quente" (não pode disparar ainda)
- Após o período de espera, ela se torna "fria" (pronta para disparar)
- Antes de disparar, verificamos: "A arma está fria?"
- Isso impede cliques excessivos enquanto mantém os controles responsivos
✅ Consulte a lição 1 da série de jogos espaciais para lembrar sobre cooldowns.
## Construindo o sistema de colisão
Você ampliará o código existente do seu jogo espacial para criar um sistema de detecção de colisão. Como o sistema automatizado de prevenção de colisões da Estação Espacial Internacional, seu jogo monitorará continuamente as posições dos objetos e responderá às interseções.
A partir do código da lição anterior, você adicionará detecção de colisão com regras específicas que governam as interações dos objetos.
> 💡 **Dica Pro**: O sprite do laser já está incluído na sua pasta de recursos e referenciado no seu código, pronto para implementação.
### Regras de colisão para implementar
**Mecânicas do jogo para adicionar:**
1. **Laser atinge inimigo**: O objeto inimigo é destruído quando atingido por um projétil de laser
2. **Laser atinge limite da tela**: O laser é removido ao alcançar a borda superior da tela
3. **Colisão entre inimigo e herói**: Ambos os objetos são destruídos quando se intersectam
4. **Inimigo alcança o fundo**: Condição de fim de jogo quando os inimigos alcançam o fundo da tela
## Configurando seu ambiente de desenvolvimento
Boas notícias - já preparamos a maior parte da base para você! Todos os seus recursos do jogo e estrutura básica estão prontos na subpasta `your-work`, esperando para você adicionar os recursos legais de colisão.
### Estrutura do projeto
```bash
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| index.html
-| app.js
-| package.json
```
**Entendendo a estrutura dos arquivos:**
- **Contém** todas as imagens de sprites necessárias para os objetos do jogo
- **Inclui** o documento HTML principal e o arquivo de aplicação JavaScript
- **Fornece** configuração de pacote para servidor de desenvolvimento local
### Iniciando o servidor de desenvolvimento
Navegue até sua pasta de projeto e inicie o servidor local:
```bash
cd your-work
npm start
```
**Essa sequência de comandos:**
- **Altera** o diretório para sua pasta de trabalho do projeto
- **Inicia** um servidor HTTP local em `http://localhost:5000`
- **Serve** seus arquivos do jogo para teste e desenvolvimento
- **Habilita** desenvolvimento ao vivo com recarregamento automático
Abra seu navegador e navegue até `http://localhost:5000` para ver o estado atual do seu jogo com o herói e os inimigos renderizados na tela.
### Implementação passo a passo
Como a abordagem sistemática que a NASA usou para programar a espaçonave Voyager, implementaremos a detecção de colisão metodicamente, construindo cada componente passo a passo.
#### 1. Adicionar limites de colisão retangulares
Primeiro, vamos ensinar nossos objetos do jogo a descrever seus limites. Adicione este método à sua classe `GameObject`:
```javascript
rectFromGameObject() {
return {
top: this.y,
left: this.x,
bottom: this.y + this.height,
right: this.x + this.width,
};
}
```
**Este método realiza:**
- **Cria** um objeto retangular com coordenadas de limite precisas
- **Calcula** as bordas inferior e direita usando posição mais dimensões
- **Retorna** um objeto pronto para algoritmos de detecção de colisão
- **Fornece** uma interface padronizada para todos os objetos do jogo
#### 2. Implementar detecção de interseção
Agora vamos criar nosso detetive de colisões - uma função que pode dizer quando dois retângulos estão se sobrepondo:
```javascript
function intersectRect(r1, r2) {
return !(
r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top
);
}
```
**Este algoritmo funciona ao:**
- **Testar** quatro condições de separação entre retângulos
- **Retornar** `false` se qualquer condição de separação for verdadeira
- **Indicar** colisão quando não há separação
- **Usar** lógica de negação para testes de interseção eficientes
#### 3. Implementar sistema de disparo de laser
Aqui é onde as coisas ficam emocionantes! Vamos configurar o sistema de disparo de laser.
##### Constantes de mensagem
Primeiro, vamos definir alguns tipos de mensagem para que diferentes partes do nosso jogo possam se comunicar:
```javascript
KEY_EVENT_SPACE: "KEY_EVENT_SPACE",
COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER",
COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
```
**Essas constantes fornecem:**
- **Padronizam** os nomes dos eventos em toda a aplicação
- **Habilitam** comunicação consistente entre os sistemas do jogo
- **Evitam** erros de digitação no registro de manipuladores de eventos
##### Manipulação de entrada do teclado
Adicione a detecção da tecla de espaço ao seu listener de eventos de tecla:
```javascript
} else if(evt.keyCode === 32) {
eventEmitter.emit(Messages.KEY_EVENT_SPACE);
}
```
**Este manipulador de entrada:**
- **Detecta** pressionamentos da tecla de espaço usando keyCode 32
- **Emite** uma mensagem de evento padronizada
- **Habilita** lógica de disparo desacoplada
##### Configuração de listener de eventos
Registre o comportamento de disparo na sua função `initGame()`:
```javascript
eventEmitter.on(Messages.KEY_EVENT_SPACE, () => {
if (hero.canFire()) {
hero.fire();
}
});
```
**Este listener de eventos:**
- **Responde** a eventos de tecla de espaço
- **Verifica** o status de cooldown de disparo
- **Aciona** a criação de laser quando permitido
Adicione manipulação de colisão para interações entre laser e inimigos:
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
first.dead = true;
second.dead = true;
});
```
**Este manipulador de colisão:**
- **Recebe** dados de eventos de colisão com ambos os objetos
- **Marca** ambos os objetos para remoção
- **Garante** limpeza adequada após a colisão
#### 4. Criar a classe Laser
Implemente um projétil de laser que se move para cima e gerencia seu próprio ciclo de vida:
```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);
}
}
```
**Esta implementação de classe:**
- **Estende** GameObject para herdar funcionalidade básica
- **Define** dimensões apropriadas para o sprite do laser
- **Cria** movimento automático para cima usando `setInterval()`
- **Lida** com autodestruição ao alcançar o topo da tela
- **Gerencia** seu próprio tempo de animação e limpeza
#### 5. Implementar sistema de detecção de colisão
Crie uma função abrangente de detecção de colisão:
```javascript
function updateGameObjects() {
const enemies = gameObjects.filter(go => go.type === 'Enemy');
const lasers = gameObjects.filter(go => go.type === "Laser");
// Test laser-enemy collisions
lasers.forEach((laser) => {
enemies.forEach((enemy) => {
if (intersectRect(laser.rectFromGameObject(), enemy.rectFromGameObject())) {
eventEmitter.emit(Messages.COLLISION_ENEMY_LASER, {
first: laser,
second: enemy,
});
}
});
});
// Remove destroyed objects
gameObjects = gameObjects.filter(go => !go.dead);
}
```
**Este sistema de colisão:**
- **Filtra** objetos do jogo por tipo para testes eficientes
- **Testa** cada laser contra cada inimigo para interseções
- **Emite** eventos de colisão quando interseções são detectadas
- **Limpa** objetos destruídos após o processamento de colisões
> ⚠️ **Importante**: Adicione `updateGameObjects()` ao seu loop principal do jogo em `window.onload` para habilitar a detecção de colisão.
#### 6. Adicionar sistema de cooldown à classe Hero
Melhore a classe Hero com mecânicas de disparo e limitação de taxa:
```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;
}
}
```
**Entendendo a classe Hero aprimorada:**
- **Inicializa** o temporizador de cooldown em zero (pronto para disparar)
- **Cria** objetos de laser posicionados acima da nave do herói
- **Define** período de cooldown para evitar disparos rápidos
- **Decrementa** o temporizador de cooldown usando atualizações baseadas em intervalo
- **Fornece** verificação de status de disparo por meio do método `canFire()`
### Testando sua implementação
Seu jogo espacial agora possui detecção de colisão completa e mecânicas de combate. 🚀 Teste essas novas capacidades:
- **Navegue** com as teclas de seta para verificar os controles de movimento
- **Dispare lasers** com a barra de espaço - note como o cooldown impede cliques excessivos
- **Observe colisões** quando lasers atingem inimigos, acionando a remoção
- **Verifique a limpeza** enquanto objetos destruídos desaparecem do jogo
Você implementou com sucesso um sistema de detecção de colisão usando os mesmos princípios matemáticos que orientam a navegação de espaçonaves e robótica.
## Desafio do Agente GitHub Copilot 🚀
Use o modo Agente para completar o seguinte desafio:
**Descrição:** Melhore o sistema de detecção de colisão implementando power-ups que aparecem aleatoriamente e fornecem habilidades temporárias quando coletados pela nave do herói.
**Prompt:** Crie uma classe PowerUp que estenda GameObject e implemente detecção de colisão entre o herói e os power-ups. Adicione pelo menos dois tipos de power-ups: um que aumenta a taxa de disparo (reduz o cooldown) e outro que cria um escudo temporário. Inclua lógica de spawn que cria power-ups em intervalos e posições aleatórias.
---
## 🚀 Desafio
Adicione uma explosão! Dê uma olhada nos recursos do jogo no [repositório Space Art](../../../../6-space-game/solution/spaceArt/readme.txt) e tente adicionar uma explosão quando o laser atingir um alienígena.
## Quiz Pós-Aula
[Quiz pós-aula](https://ff-quizzes.netlify.app/web/quiz/36)
## Revisão & Autoestudo
Experimente os intervalos no seu jogo até agora. O que acontece quando você os altera? Leia mais sobre [eventos de temporização em JavaScript](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/).
## Tarefa
[Explore colisões](assignment.md)
---
**Aviso Legal**:
Este documento foi traduzido utilizando o serviço de tradução por IA [Co-op Translator](https://github.com/Azure/co-op-translator). Embora nos esforcemos para garantir a precisão, esteja ciente de que traduções automatizadas podem conter erros ou imprecisões. O documento original em seu idioma nativo deve ser considerado a fonte autoritativa. Para informações críticas, recomenda-se a tradução profissional feita por humanos. Não nos responsabilizamos por quaisquer mal-entendidos ou interpretações incorretas decorrentes do uso desta tradução.