Estou usando o MatterJs para um jogo baseado em física e não encontrei uma solução para o problema de impedir que os corpos sejam arrastados à força pelo mouse através de outros corpos. Se você arrastar um corpo para outro, o corpo que está sendo arrastado pode forçar-se a entrar e atravessar o outro corpo. Estou procurando uma maneira confiável de impedir que eles se cruzem. Você pode observar esse efeito em qualquer demonstração do MatterJS selecionando um corpo com o mouse e tentando forçá-lo a outro corpo. Aqui está um exemplo típico:
https://brm.io/matter-js/demo/#staticFriction
Infelizmente, isso quebra todos os jogos ou simulações, dependendo do recurso de arrastar e soltar. Tentei várias soluções, como quebrar a restrição do mouse quando ocorre uma colisão ou reduzir a rigidez da restrição, mas nada que funcione de maneira confiável.
Todas as sugestões são bem-vindas!
Respostas:
Penso que a melhor resposta aqui seria uma revisão significativa do
Matter.Resolver
módulo para implementar a prevenção preditiva de conflitos físicos entre quaisquer órgãos. É garantido que tudo menos que isso falhe em determinadas circunstâncias. Dito isto, aqui estão duas "soluções" que, na realidade, são apenas soluções parciais. Eles estão descritos abaixo.Solução 1 (atualização)
Esta solução tem várias vantagens:
A idéia por trás dessa abordagem é resolver o paradoxo do que acontece " quando uma força imparável encontra um objeto imóvel ", tornando a força parável. Isso é habilitado pelo
Matter.Event
beforeUpdate
, que permite que a velocidade e o impulso absolutos (ou melhorpositionImpulse
, o que não é realmente o impulso físico) em cada direção sejam limitados dentro dos limites definidos pelo usuário.No exemplo que estou restringindo o
velocity
epositionImpulse
nax
ey
para a magnitude máxima de25.0
. O resultado é apresentado abaixoComo você pode ver, é possível ser bastante violento ao arrastar os corpos e eles não passarão um pelo outro. É isso que diferencia essa abordagem das outras: a maioria das outras soluções em potencial falha quando o usuário é suficientemente violento com o arrastamento.
A única falha que encontrei com esse método é que é possível usar um corpo não estático para atingir outro corpo não estático com força suficiente para dar velocidade suficiente ao ponto em que o
Resolver
módulo falhará ao detectar a colisão e permitir que o segundo corpo a passar por outros corpos. (No exemplo de atrito estático, a velocidade necessária está em torno50.0
, só consegui fazer isso com êxito uma vez e, consequentemente, não tenho uma animação representando).Solução 2
Esta é uma solução adicional, porém, um aviso justo: não é simples.
Em termos gerais, a maneira como isso funciona é verificar se o corpo que está sendo arrastado
dragBody
colidiu com um corpo estático e se o mouse se moveu muito longe semdragBody
segui-lo. Se detectar que a separação entre o mouse edragBody
se tornou muito grande, remove o ouvinte de eventos e o substitui por uma função diferente de remoção de mouse ,. Esta função verifica se o mouse retornou a uma determinada proximidade do centro do corpo. Infelizmente, não consegui fazer com que o método interno funcionasse corretamente, por isso tive que incluí-lo diretamente (alguém com mais conhecimento que eu em Javascript precisará descobrir isso). Por fim, se um evento for detectado, ele retornará ao ouvinte normal .Matter.js
mouse.mousemove
mouse.element
mousemove()
Matter.Mouse._getRelativeMousePosition()
mouseup
mousemove
Depois de aplicar o esquema de troca de ouvinte de eventos, os corpos agora se comportam mais como este
Eu testei isso bastante bem, mas não posso garantir que funcione em todos os casos. Também é importante notar que o
mouseup
evento não é detectado, a menos que o mouse esteja dentro da tela quando ocorre - mas isso é verdade para qualquermouseup
detecção do Matter.js, por isso não tentei corrigir isso.Se a velocidade for suficientemente grande,
Resolver
falhará na detecção de qualquer colisão e, como carece de prevenção preditiva desse sabor de conflito físico, permitirá que o corpo passe, como mostrado aqui.Isso pode ser resolvido combinando-se com a solução 1 .
Uma última observação aqui, é possível aplicar isso apenas a certas interações (por exemplo, entre um corpo estático e um corpo não estático). Fazer isso é conseguido alterando
para (por exemplo, corpos estáticos)
Soluções com falha
Caso algum usuário futuro se depare com essa questão e encontre as duas soluções insuficientes para o caso de uso, aqui estão algumas das soluções que tentei que não funcionaram. Um guia das sortes para o que não fazer.
mouse.mouseup
diretamente: objeto excluído imediatamente.mouse.mouseup
viaEvent.trigger(mouseConstraint, 'mouseup', {mouse: mouse})
: substituído porEngine.update
, comportamento inalterado.Matter.Body.setStatic(body, false)
oubody.isStatic = false
).(0,0)
viasetForce
ao se aproximar de um conflito: o objeto ainda pode passar, precisaria ser implementadoResolver
para realmente funcionar.mouse.element
para uma tela diferente por meio desetElement()
ou pela mutaçãomouse.element
direta: objeto excluído imediatamente.collisionStart
: a detecção inconsistente de colisão ainda permite a passagem com esse métodofonte
Eu teria gerenciado o recurso de outra maneira:
fonte
matter.js
lida com arrastar corpos? a partir daqui "... como uma mola virtual que atribui ao rato Ao arrastar ... a mola é anexado [para o corpo] e puxa na direção do rato ...."Resolver
para decidir o que fazer com a colisão de corpos - tendo examinado um pouco esse código, espero que ele ainda decida permitir o arrastamento sob muitas circunstâncias ..... pode funcionar se você também implementou sua própria versão desolveVelocity
esolvePosition
mas nesse ponto você ainda está fazendo manualmente o que você quer MatterJS para lidar diretamente ....Para controlar a colisão quando arrastada, você precisa utilizar eventos e filtro de colisão .
Crie corpos com a máscara de filtro de colisão padrão
0x0001
. Adicione capturasstartdrag
eenddrag
eventos e defina diferentes categorias de filtros de colisão do corpo para evitar temporariamente colisões.fonte
Isso parece estar relacionado ao problema 672 na página do GitHub, que parece sugerir que isso ocorre devido à falta de detecção contínua de colisão (CCD).
Foi feita uma tentativa de remediar isso, e o código pode ser encontrado aqui, mas o problema ainda está aberto. Parece que você pode precisar editar o mecanismo para criar o CCD por conta própria.
fonte