Colisões 2D: do “tocando em?” à colisão precisa estilo Mario
Colisão tem duas perguntas diferentes: “esses dois objetos estão se tocando?” (detecção) e “para onde empurro o personagem para ele não atravessar a parede?” (resolução). Confundir as duas é a causa da maioria dos bugs de jogo de plataforma — personagens que grudam em paredes, sobem degraus invisíveis ou atravessam o chão.
Detecção: o sensor “tocando em”
O bloco booleano “tocando em [ator]?” responde à primeira pergunta com precisão de pixel: ele compara as silhuetas reais das imagens (ignorando as partes transparentes), não apenas os retângulos. Para moedas, inimigos e gatilhos, é tudo de que você precisa:
se tocando em Moeda:
adicione 1 a pontuação
envie mensagem "moeda_coletada"Por que detecção sozinha não basta para paredes
Se você só checa “tocando em Parede?” e zera a velocidade, o personagem para DENTRO da parede — afinal, a colisão só é detectada depois que ele já entrou. Pior: dependendo da forma do sprite, empurrar “para cima até não tocar” faz o personagem escalar paredes como um degrau. A solução usada nos clássicos (e nos projetos de exemplo do Wicand Blocks) é a resolução por caixas, ou AABB.
Resolução AABB: o método Mario
AABB (axis-aligned bounding box) trata cada objeto como um retângulo alinhado aos eixos, definido por centro e meia-largura/meia-altura. Quando dois retângulos se sobrepõem, calcule a penetração em cada eixo e empurre o personagem pelo eixo de MENOR penetração:
sobreposX = (metadeLargA + metadeLargB) - |centroAx - centroBx|
sobreposY = (metadeAltA + metadeAltB) - |centroAy - centroBy|
se sobreposX < sobreposY:
// empurra na horizontal (parede)
adicione (sobreposX na direção contrária) a x
mude vx para 0
senão:
// empurra na vertical (chão ou teto)
adicione (sobreposY na direção contrária) a y
mude vy para 0
se empurrou para cima: mude noChao para verdadeiroA regra do menor eixo é o que faz paredes se comportarem como paredes e chão como chão, sem casos especiais. Bater na quina de uma plataforma empurra para o lado certo automaticamente.
Separando colisão do visual
Dica de quem já sofreu: não use o sprite desenhado como caixa de colisão. Defina as caixas com variáveis ou listas (centro, meia-largura, meia-altura) independentes da imagem. Assim a animação pode “respirar” — quadros maiores ou menores — sem mudar a física, e você pode ter uma caixa mais estreita que o desenho para o jogo parecer mais justo.
- ▸Guarde os retângulos do cenário em listas (SOL_X, SOL_Y, SOL_HW, SOL_HH) preenchidas por um ator gerador.
- ▸A cada quadro, percorra a lista e resolva a colisão do personagem contra cada retângulo.
- ▸Plataformas atravessáveis ganham uma lista separada e só resolvem colisão quando o personagem está caindo por cima.
Use blocos customizados (“Meus Blocos”) para encapsular a resolução: um bloco “resolve cx cy hw hh” chamado dentro do loop deixa o script principal legível e a física reutilizável.
Pronto para colocar em prática?
Abrir o editor