Estou fazendo um jogo baseado em uma grade 2D, com algumas células aceitáveis e outras não. Objetos dinâmicos podem se mover continuamente, independentemente da grade, mas precisam colidir com células intransitáveis.
Eu escrevi um algoritmo para rastrear um raio contra a grade, que me fornece todas as células que cruzam o raio. No entanto, o objeto real não tem tamanho de ponto; Atualmente, estou representando-os como círculos. Mas não consigo descobrir um algoritmo eficaz para rastrear um círculo em movimento. Aqui está uma foto do que eu preciso:
Os números mostram em que ordem o círculo colide com as células da grade. Alguém conhece o algoritmo para encontrar essas colisões? De preferência em C #.
Atualizar O círculo pode ser maior que uma única célula da grade.
fonte
Respostas:
Acho que seu desenho é um pouco enganador, porque você escolhe desenhar traços do ponto do círculo tangente à sua direção em movimento. Percebo que as colisões nas arestas da grade acontecem quando os pontos SUPERIOR e ESQUERDO do seu círculo tocam uma aresta.
Seja C o seu centro e r o raio, de modo que P ' = C + ( r , 0) e P " = C + (0, r).
Se D é o seu vetor de direção (o versor), você tem duas linhas:
R '= D · t + P' ,
R "= D · t + P"
Você simplesmente precisa encontrar a interseção dessas linhas com as linhas da equação:
y = ie y = i que são as arestas da sua grade!
A solução é fácil, porque você tem que considerar simplesmente o x ou o componente y de R' e R". Você vai encontrar o t valor s para cada insersection, e os pontos para thoose t s, simplesmente tipo aqueles ponto por t e você estão feitos.
Eu acredito que você pode facilmente dizer qual célula é atingida se você souber o ponto de interseção.
Isso funciona se r <1 (a largura e a altura da célula).
Funciona também para os outros casos, simplesmente fazendo alguma consideração sobre P ' e P " . Nós escolhemos TOP e ESQUERDA por causa da direção, INFERIOR e DIREITA devem ser consideradas na direção oposta, você entende o porquê.
Agora veja esta imagem:
O círculo é maior que uma única célula e supomos que esteja seguindo a mesma direção do seu desenho. P1 é o primeiro ponto que tocará, P2 é o segundo, P3 é inútil porque está na metade inferior. O que você precisa fazer é lançar raios de P1 e P2 como vimos anteriormente e fazer o mesmo para as linhas verticais.
Em geral, você terá outros pontos de partida junto com o TOP e o ESQUERDO de onde disparar seus raios, quanto maior o seu círculo, mais raios serão lançados.
Para ser honesto, você pode evitar disparar em todos os raios fazendo alguma consideração geométrica, mas isso pode tornar as coisas mais difíceis de entender.
fonte
Se você quiser usar o algoritmo de colisão de raios, poderá escolher oito pontos em cada círculo (em incrementos de 45 graus, alinhados à sua grade quadrada) e usar a colisão de raios entre os pontos correspondentes (ou seja, do topo de um círculo para o topo do outro). A união de todas essas colisões de raios é o conjunto inteiro de células cruzadas.
Você provavelmente poderia melhorar um pouco isso - por exemplo, usando o segmento de linha do centro de um círculo para o centro do outro, mas estendido de ambos os lados pelo raio do círculo, bem como os segmentos de linha paralelos em de ambos os lados nas extremidades dos círculos.
fonte
Não estou dizendo que essa é uma analogia perfeita, mas você pode pensar no algoritmo de linha de Bresenham . Uma modificação desse algoritmo ou de uma de suas extensões pode ser útil, especialmente se você o associar a algumas das outras postagens e comentários. Normalmente, esse algoritmo não se preocupa com pedidos, mas acho que você seria capaz de adicioná-lo de maneira bastante trivial.
fonte