--- title: Prática de construção de objetos slug: Aprender/JavaScript/Objetos/Object_building_practice translation_of: Learn/JavaScript/Objects/Object_building_practice ---
Nos artigos anteriores, analisamos todos os detalhes essenciais da teoria e da sintaxe do objeto JavaScript, fornecendo uma base sólida para começar. Neste artigo, vamos mergulhar em um exercício prático, dando a você mais prática na construção de objetos JavaScript personalizados, com um resultado divertido e colorido.
Prerequisites: | Conhecimentos básicos de informática, conhecimento básico de HTML e CSS, familiaridade com o básico de JavaScript (veja First steps e Building blocks) e o básico de OOJS (veja Introduction to objects). |
---|---|
Objective: | Adiquirir alguma prática no uso de objetos e técnicas de orientação a objetos num contexto real. |
Neste artigo, vamos escrever uma demo clássica de "bolas saltitantes", para mostrar o quão úteis os objetos podem ser em JavaScript. Nossas bolinhas vão saltar pela tela e mudam de cor quando se tocam. O exemplo acabado vai parecer um pouco assim:
Este exemplo fará uso da Canvas API, para desenhar as bolas na tela, e da requestAnimationFrame API para animar toda a exibição — você não precisa ter nenhum conhecimento prévio dessas APIs e esperamos que, no momento em que você terminar este artigo, você esteja interessado em explorá-los mais. Ao longo do caminho, faremos uso de alguns objetos bacanas, e mostraremos algumas técnicas legais, como bolas quicando nas paredes, e verificando se elas se chocaram (também conhecidas como detecção de colisão).
Para começar, faça cópias locais de nossos arquivos index.html
, style.css
, e main.js
. Estes contêm o seguinte, respectivamente:
<h1>
, e se livrar de qualquer barra de rolagem ou margem ao redor da borda da página (para que fique bonito e arrumado).<canvas>
e fornecer uma função geral que vamos usar.A primeira parte do script é assim:
const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); const width = canvas.width = window.innerWidth; const height = canvas.height = window.innerHeight;
Esse script obtém uma referência ao elemento <canvas>
e, em seguida, chama o método getContext()
para nos fornecer um contexto no qual podemos começar a desenhar. A variável resultante (ctx
) é o objeto que representa diretamente a área de desenho da tela e nos permite desenhar formas 2D nela.
Em seguida, definimos variáveis chamadas width
e height
, e a largura e altura do elemento canvas (representado pelas propriedades canvas.width
e canvas.height
) para igualar a largura e a altura da viewport do navegador (a área em que a página da Web aparece — isso pode ser obtido das propriedades {{domxref("Window.innerWidth")}} e {{domxref("Window.innerHeight")}} ).
Você verá aqui que estamos encadeando várias tarefas juntas, para que as variáveis sejam todas mais rápidas — isso é perfeitamente aceitável.
A última parte do script inicial é a seguinte:
function random(min, max) { const num = Math.floor(Math.random() * (max - min + 1)) + min; return num; }
Essa função usa dois números como argumentos e retorna um número aleatório no intervalo entre os dois.
Nosso programa contará com muitas bolas saltando ao redor da tela. Como todas essas bolas se comportarão da mesma maneira, faz sentido representá-las com um objeto. Vamos começar adicionando o construtor a seguir ao final do código.
function Ball(x, y, velX, velY, color, size) { this.x = x; this.y = y; this.velX = velX; this.velY = velY; this.color = color; this.size = size; }
Aqui incluímos alguns parâmetros que definem as propriedades que cada bola precisa para funcionar em nosso programa:
x
e y
— coordenadas horizontal e vertical onde a bola vai começar na tela. Isso pode variar entre 0 (canto superior esquerdo) à largura e altura da janela de visualização do navegador (canto inferior direito).velX
e velY
) — cada bola recebe uma velocidade horizontal e vertical; em termos reais, esses valores serão adicionados regularmente aos valores das coordenadas x
/y
quando começarmos a animar as bolas, para movê-las tanto em cada quadro.color
— cada bola recebe uma cor.size
— cada bola recebe um tamanho — este será o seu raio, em pixels.Isso classifica as propriedades, mas e os métodos? Queremos realmente fazer com que nossas bolas façam algo em nosso programa.
Primeiro adicione o seguinte método draw()
ao prototype
do Ball()
:
Ball.prototype.draw = function() { ctx.beginPath(); ctx.fillStyle = this.color; ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); ctx.fill(); }
Usando esta função, podemos dizer a nossa bola para desenhar-se na tela, chamando uma série de membros do contexto de tela 2D que definimos anteriormente (ctx
). O contexto é como o papel, e agora queremos comandar nossa caneta para desenhar algo nela:
beginPath()
para declarar que queremos desenhar uma forma no papel.fillStyle
para definir a cor que queremos que a forma seja — nós a definimos como a propriedade color
da nossa bola.arc()
para traçar uma forma de arco no papel. Seus parâmetros são:
x
e y
do centro do arco — estamos especificando as propriedades x
e y
da nossa bola.size
da nossa bola.2 * PI
, que é o equivalente a 360 graus em radianos (irritantemente, você tem que especificar isso em radianos). Isso nos dá um círculo completo. Se você tivesse especificado apenas 1 * PI
, você obteria um semicírculo (180 graus).fill()
, que basicamente diz "terminar de desenhar o caminho que começamos com beginPath()
, e preencher a área que ocupa com a cor que especificamos anteriormente em fillStyle
."Você pode começar a testar seu objeto já.
let testBall = new Ball(50, 100, 4, 4, 'blue', 10);
testBall.x testBall.size testBall.color testBall.draw()
Podemos desenhar a bola na posição, mas para começar a mover a bola, precisamos de uma função de atualização de algum tipo. Adicione o seguinte código na parte inferior do seu arquivo JavaScript, para adicionar um método update()
ao prototype
do Ball()
:
Ball.prototype.update = function() { if ((this.x + this.size) >= width) { this.velX = -(this.velX); } if ((this.x - this.size) <= 0) { this.velX = -(this.velX); } if ((this.y + this.size) >= height) { this.velY = -(this.velY); } if ((this.y - this.size) <= 0) { this.velY = -(this.velY); } this.x += this.velX; this.y += this.velY; }
As primeiras quatro partes da função verificam se a bola atingiu a borda da tela. Se tiver, invertemos a polaridade da velocidade relevante para fazer a bola viajar na direção oposta. Assim, por exemplo, se a bola estava viajando para cima (positivo velY
), então a velocidade vertical é alterada de forma que ela comece a viajar para baixo (negativo velY
).
Nos quatro casos, estamos verificando se:
x
é maior que a largura da tela (a bola está saindo da borda direita).x
é menor que 0 (a bola está saindo da borda esquerda).y
é maior que a altura da tela (a bola está saindo da borda inferior).y
é menor que 0 (a bola está saindo da borda superior).Em cada caso, estamos incluindo o size
da bola no cálculo, porque as coordenadas x
/y
estão no centro da bola, mas queremos que a borda da bola saia do perímetro — não queremos a bola para fique no meio da tela antes de quicar de volta.
As duas últimas linhas adicionam o valor velX
à coordenada x
, e o valor velY
à coordenada y
— a bola é efitivamente movida cada vez que este método é chamado.
Isso é o que será feito por ora; vamos continuar com alguma animação!
Agora vamos tornar isso divertido. Vamos começar a adicionar bolas à tela e a animá-las.
let balls = [];
Todos os programas que animam as coisas geralmente envolvem um loop de animação, que serve para atualizar as informações no programa e renderizar a visualização resultante em cada quadro da animação; esta é a base para a maioria dos jogos e outros programas.
function loop() { ctx.fillStyle = 'rgba(0, 0, 0, 0.25)'; ctx.fillRect(0, 0, width, height); while (balls.length < 25) { let size = random(10,20); let ball = new Ball( // ball position always drawn at least one ball width // away from the edge of the canvas, to avoid drawing errors random(0 + size,width - size), random(0 + size,height - size), random(-7,7), random(-7,7), 'rgb(' + random(0,255) + ',' + random(0,255) + ',' + random(0,255) +')', size ); balls.push(ball); } for (let i = 0; i < balls.length; i++) { balls[i].draw(); balls[i].update(); } requestAnimationFrame(loop); }
Nossa função loop()
faz o seguinte:
fillRect()
(os quatro parâmetros fornecem uma coordenada de início e uma largura e altura para o retângulo desenhado ). Isso serve para encobrir o desenho do quadro anterior antes que o próximo seja desenhado. Se você não fizer isso, você verá apenas longas cobras se movimentando ao redor da tela, em vez de mover as bolas! A cor do preenchimento é definida como semitransparente, rgba(0,0,0,0.25)
, para permitir que os poucos quadros anteriores brilhem levemente, produzindo as pequenas trilhas atrás das bolas à medida que elas se movem. Se você mudou 0,25 para 1, você não vai mais vê-los. Tente variar esse número para ver o efeito que ele tem.Ball()
usando valores aleatórios gerados com a nossa função random()
então push()
para o final de nosso array de bolas, mas somente enquanto o número de bolas no array é menor que 25. Então quando temos 25 bolas na tela, não aparecem mais bolas. Você pode tentar variar o número emballs.length < 25
para obter mais ou menos bolas na tela. Dependendo de quanto poder de processamento seu computador / navegador possui, especificar vários milhares de bolas pode retardar bastante a animação!balls
no array de bolas e executa a função draw()
e update()
de cada bola para desenhar cada uma delas na tela, depois faz as atualizações necessárias para a posição e a velocidade no tempo para o próximo quadro.requestAnimationFrame()
— quando esse método é executado constantemente e passa o mesmo nome de função, ele executará essa função um número definido de vezes por segundo para criar uma animação suave. Isso geralmente é feito de forma recursiva — o que significa que a função está chamando a si mesma toda vez que é executada, portanto, ela será executada repetidas vezes.loop();
É isso para o básico — tente salvar e atualizar para testar suas bolas quicando!
Agora, para um pouco de diversão, vamos adicionar alguma detecção de colisão ao nosso programa, para que nossas bolas saibam quando bateram em outra bola.
update()
(ou seja, o bloco Ball.prototype.update
).
Ball.prototype.collisionDetect = function() { for (let j = 0; j < balls.length; j++) { if (!(this === balls[j])) { const dx = this.x - balls[j].x; const dy = this.y - balls[j].y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < this.size + balls[j].size) { balls[j].color = this.color = 'rgb(' + random(0, 255) + ',' + random(0, 255) + ',' + random(0, 255) +')'; } } } }
Esse método é um pouco complexo, então não se preocupe se você não entender exatamente como isso funciona agora. Uma explicação a seguir:
for
para percorrer todas as bolas no array balls[]
.if
para verificar se a bola atual em loop é a mesma bola que estamos verificando no momento. Não queremos verificar se uma bola colidiu consigo mesma! Para fazer isso, verificamos se a bola atual (ou seja, a bola cujo método collisionDetect está sendo invocado) é a mesma que a bola de loop (ou seja, a bola que está sendo referenciada pela iteração atual do loop for no collisionDetect método). Nós então usamos !
para negar a verificação, para que o código dentro da instrução if seja executado apenas se eles não forem iguais.if
interna será executado. Neste caso, estamos apenas definindo a propriedade color
de ambos os círculos para uma nova cor aleatória. Poderíamos ter feito algo muito mais complexo, como fazer com que as bolas saltassem umas das outras de forma realista, mas isso teria sido muito mais complexo de implementar. Para essas simulações físicas, os desenvolvedores tendem a usar jogos ou bibliotecas físicas, como PhysicsJS, matter.js, Phaser, etc.balls[i].update();
:
balls[i].collisionDetect();
Note: If you have trouble getting this example to work, try comparing your JavaScript code against our finished version (also see it running live).
Esperamos que você tenha se divertido escrevendo seu próprio exemplo de bolas saltitantes aleatórias do mundo real, usando várias técnicas orientadas a objetos e objetos de todo o módulo! Isso deve ter lhe dado alguma prática útil no uso de objetos e um bom contexto do mundo real.
É isso para artigos de objetos — tudo o que resta agora é para você testar suas habilidades na avaliação de objetos.
{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}