Matter.js: Aplicação de Força em um Corpo
O Matter.js é uma biblioteca JavaScript que permite criar simulações físicas realistas em 2D. Com ela você pode:
Criar corpos com propriedades físicas (peso, atrito, elasticidade)
Simular colisões e interações entre objetos
Desenvolver jogos e experiências interativas
Conceitos Fundamentais
Corpos Físicos: Objetos que interagem com física (estáticos ou dinâmicos).
Aplicação de Força:
Matter.Body.applyForce(body, position, force)
body
: O corpo que receberá a força.position
: Ponto de aplicação (normalmente{x:0, y:0}
para o centro).force
: Vetor de força ({x: valor, y: valor}
).
Exemplo Prático: Simulação de Corpos Físicos
Aqui está a animação que usaremos como referência:
Passo 1: Configurando o ambiente
Antes de começarmos a programar, certifique-se de ter um ambiente de desenvolvimento configurado:
Um editor de código (VS Code)
- Um navegador (Google Chrome)
Arquivo de template
Passo 2: Criando as paredes (arquivo parede.js)
Neste arquivo, criamos uma classe que representa os limites do mundo (chão, teto e paredes laterais):
class Parede
{
constructor(x, y, w, h)
{
let options = {
isStatic: true
};
this.body = Bodies.rectangle(x, y, w, h, options);
this.w = w;
this.h = h;
World.add(world, this.body);
}
class Ground
: define uma nova classe chamadaGround
(chão ou parede).constructor(x, y, w, h)
: função especial que será chamada sempre que criarmos uma nova parede. Recebe:x
ey
: coordenadas onde o corpo será posicionado no canvas.w
eh
: largura e altura do corpo.
let options = { isStatic: true }
: define que o corpo será estático, ou seja, não será afetado pela gravidade nem por colisões com outros corpos.Bodies.rectangle(x, y, w, h, options)
: cria um retângulo com base nas coordenadas e dimensões passadas.this.body
: armazena o corpo criado.this.w
ethis.h
: armazenam as dimensões, úteis para desenhar depois.World.add(world, this.body)
: adiciona o corpo ao mundo físico, tornando-o parte da simulação.
show() {
var pos = this.body.position;
push();
rectMode(CENTER);
stroke(255);
fill(127);
rect(pos.x, pos.y, this.w, this.h);
pop();
}
}
show()
: método responsável por desenhar o corpo na tela.this.body.position
: acessa a posição atual do corpo no mundo simulado.push()
epop()
: salvam e restauram o estado de estilo do desenho, garantindo que as configurações não interfiram em outros elementos.rectMode(CENTER)
: faz com que os retângulos sejam desenhados a partir do centro, o que facilita o posicionamento.stroke(255)
: define a cor da borda do retângulo como branco.fill(127)
: define a cor interna como cinza.rect(pos.x, pos.y, this.w, this.h)
: desenha o retângulo com a posição e tamanho definidos.
Passo 3: Declaração de variáveis
Aqui estamos declarando as variáveis que serão usadas para armazenar os módulos do Matter.js e os corpos físicos.
// Módulos do Matter.js
const Engine = Matter.Engine;
const World = Matter.World;
const Bodies = Matter.Bodies;
const Body = Matter.Body;
// Variáveis do jogo
let engine;
let world;
var ground;
var left;
var right;
var top_wall;
var ball;
var btn1;
var btn2;
Engine
: O “cérebro” que calcula todas as interações físicasWorld
: O “container” onde todos os objetos físicos existemBodies
: Ferramenta para criar novos objetosBody
: Permite manipular objetos após a criação (ex.: girar paredes)
Passo 4: Função setup()
A função setup()
é executada apenas uma vez e configura o ambiente do jogo.
createCanvas(400,400)
: Cria uma área de desenho de 550×600 pixels
function setup(){
createCanvas(400,400);
Agora criamos o motor de física:
// Cria o motor de física
engine = Engine.create();
world = engine.world;
Engine.create()
: Inicializa o motor de físicaengine.world
: Acessa o mundo físico criado
Vamos criar os botões de controle:
btn1 = createImg('right.png');
btn1.position(220, 30);
btn1.size(50, 50);
btn1.mouseClicked(hForce);
btn2 = createImg('up.png');
btn2.position(20, 30);
btn2.size(50, 50);
btn2.mouseClicked(vForce);
createImg('right.png')
: Carrega uma imagem que será usada como botão (neste caso, uma seta apontando para a direita).position(x, y)
: Define a posição do botão na tela.size(w, h)
: Define o tamanho do botão em pixels.mouseClicked(função)
: Associa uma função que será chamada quando o botão for clicado.
Agora criando as paredes e o chão:
ground = new Parede(200, 390, 400, 20);
right = new Parede(390, 200, 20, 400);
left = new Parede(10, 200, 20, 400);
top_wall = new Parede(200, 10, 400, 20);
Ground(x, y, w, h)
: Cria uma parede ou piso com posição (x
,y
) e dimensões (w
,h
).ground
: chão inferior.right
: parede direita.left
: parede esquerda.top_wall
: teto da simulação.
E criamos a bola:
var ball_options = {
restitution: 0.95
};
ball = Bodies.circle(200, 100, 20, ball_options);
World.add(world, ball);
restitution: 0.95
: Define um quique alto (95% da energia conservada)Bodies.circle()
: Cria um círculo físicoWorld.add()
: Adiciona o corpo ao mundo físico
E por fim configuramos os modos de desenho:
rectMode(CENTER);
ellipseMode(RADIUS);
}
rectMode(CENTER)
: Faz com que os retângulos sejam desenhados a partir do centro (importante para alinhar com os corpos do Matter.js).ellipseMode(RADIUS)
: Faz com que os círculos sejam desenhados a partir do centro com base no raio, e não no diâmetro.
Passo 5: Renderizando o jogo (função draw())
A função draw() é chamada continuamente para atualizar e renderizar:
background("gray")
: Define o fundo da tela como cinza.Engine.update()
: Calcula todas as interações físicas a cada frame
function draw() {
background("gray");
// Atualiza a física
Engine.update(engine);
Agora vamos rotacionar a parede dois gradualmente:
ground.show();
top_wall.show();
left.show();
right.show();
.show()
: Função da classeParede
, usada para desenhar cada corpo do tipo retângulo na tela.
Por fim, renderizamos o corpo da bola para aparecem na tela:
ellipse(ball.position.x, ball.position.y, 20);
}
ellipse(x, y, raio)
: Desenha a bola na posição atual (x
,y
) fornecida pelo motor de física (ball.position
).
Passo 6: Aplicando forças com botões
Neste passo, criamos dois botões com imagens que, ao serem clicados, aplicam uma força na bola — um para a direita e outro para cima. Isso simula o impulso de um objeto sendo empurrado ou lançado.
Matter.Body.applyForce(corpo, ponto, força)
: Aplica uma força sobre o corpo físico.
function hForce() {
Matter.Body.applyForce(ball, { x: 0, y: 0 }, { x: 0.05, y: 0 });
}
function vForce() {
Matter.Body.applyForce(ball, { x: 0, y: 0 }, { x: 0, y: -0.05 });
}