Linha de visão diagonal com dois cantos

9

No momento, estou usando o algoritmo de linha de Bresenham como linha de visão. O problema é que encontrei um caso em que jogadores podem olhar através das paredes. Ocorre quando o jogador olha entre dois cantos de uma parede com um espaço do outro lado em ângulos específicos.

Caixa da borda da linha de visão

O resultado que desejo é que o bloco entre duas paredes seja marcado como inválido.

Resultado desejado

Qual é a maneira mais rápida de modificar o algoritmo de linha de Bresenham para resolver isso? Se não houver uma boa solução, existe um algoritmo mais adequado? Todas as idéias são bem-vindas. Observe que a solução também deve ser capaz de suportar 3d.

Edit: Minha solução simples foi verificar se os dois cantos estão fechados quando as coordenadas x e y de uma linha são alteradas. Para obter o código fonte de trabalho e uma demonstração interativa do produto concluído, consulte http://ashblue.github.io/javascript-pathfinding/

Azul Cinzento
fonte
2
Faz diferença se você alternar o ponto inicial e final? Talvez você possa aceitar resultados apenas se os dois cálculos retornarem uma linha de visão não obstruída. Você também pode encontrar alguns dos artigos de LOS úteis no RogueBasin.
Thalador 31/05
11
De qualquer maneira, esses dois blocos pretos na diagonal 4-5 não estão conectados a uma parede em primeiro lugar, e digo isso porque você está implicitamente permitindo o movimento diagonal. Você deve ajustar o quadrado dessa diagonal para torná-lo uma parede contígua ou fazer com que o seu alinhador quadrilhe seus movimentos diagonais, em vez de ficar puramente diagonal como 2-3 e 4-5.
Patrick Hughes
Inverter parecia uma boa ideia, mas não resolve o problema. A única coisa que consigo pensar é verificar e ver se um dos dois cantos está vazio. Parece caro.
Ash Blue
5
"Parece caro" nunca é justificativa suficiente para não tentar algo. "Vai ser muito caro" geralmente é, supondo que você possa provar que algo será muito lento.
Mokosha 31/05
3
A única alteração no algoritmo necessário é que, se X e Y estiverem mudando na mesma etapa, primeiro mude X e depois Y, isso eliminaria as diagonais completamente.
Patrick Hughes

Respostas:

7

Eric Lippert escreveu uma excelente série sobre a geração de linha de visão em C # com Shadow Casting em uma grade plana retangular.

Entre outras questões, Eric lidou com várias perguntas que devem ser respondidas sobre os requisitos da linha de visão, que fornecem resultados diferentes e exemplos de alguns resultados diferentes. Um dos artigos trata em profundidade de uma circunstância "olhando ao virar da esquina" que ocorreu em uma versão inicial de seu algoritmo.

Adaptei o algoritmo de Eric a uma grade hexagonal aqui e o usei com sucesso em grandes grades hexagonais (> 400 x 700) com um amplo raio de visibilidade (> 60 hexágonos). Essa implementação calcula e exibe o campo de visão completo o mais rápido possível, usando uma única CPU i7. Isso certamente é rápido o suficiente para qualquer uso que eu espere colocar.

Atualização - Linha de visão com elevação: a
implementação da grade hexadecimal vinculada acima calcula a linha de visão com elevação, não apenas obstáculos. As notas da documentação também discutem uma decisão adicional que deve ser tomada com relação aos cálculos de elevação: A altura do alvo e a altura do observador. A seleção padrão é tornar os dois iguais, o que cria um campo de visão simétrico, mas o solo para o solo e os olhos do observador para o solo também podem ser selecionados. (O código é Open Source sob licença MIT)

Pieter Geerkens
fonte
Estou realmente gostando do Shadow Casting, mas encontrei um problema. Problemas para encontrar informações sobre a escala do algoritmo para operar com um eixo z. Lamento mencionar isso, mas você tem algum recurso sugerido para fazê-lo funcionar em 3d?
Ash Blue
@AshBlue: veja o adendo acima
Pieter Geerkens
Eu estou olhando para sua base de código. Tem ótimas coisas, mas não acho um algoritmo de desenho de linha semelhante a Bresenham adaptado a hexágonos. Você faz isso com o LOS?
MLProgrammer-CiM
@EfEs: FieldOfView é o objeto retornado; ShadowCastingFov * .cs gera o campo de visão projetando sombras. Se você tiver perguntas específicas sobre o código, poderá ser melhor perguntar na seção Discussões do site; perguntas mais gerais, fico feliz em responder aqui.
Pieter Geerkens
@PieterGeerkens Você pode encontrar a pergunta aqui gamedev.stackexchange.com/questions/57087/…
MLProgrammer-CiM
1

E se, para o cálculo do LOS, você tiver uma grade separada de "maior resolução" que preencha as lacunas dos cantos. Eu estava pensando algo assim:

insira a descrição da imagem aqui

A esquerda é a seção original do bloco de 4 quadrados.

O certo é a versão "alta resolução", pois você pode ver que cada quadrado original foi subdividido em quadrantes e um dos cantos foi preenchido. Não sei ao certo o algoritmo para gerar isso, mas pode ser pré-calculado do mapa atual.

Isso significa que o espaço de coordenadas é quadruplicado, mas não imagino que seja um problema de desempenho significativo.

Davy8
fonte
Certamente a resolução mais alta seria exatamente igual à original. Ao dividir uma grade em uma grade menor, você obtém a mesma representação visual, apenas com uma grade menor. Cada quadrado único se torna 4 quadrados menores no mesmo local.
MichaelHouse
@ Byte56 Correto, quis dizer que uma lógica adicional seria aplicada após a divisão para adicionar blocos extras a essa cópia. A lógica para fazer isso é um exercício deixado para o leitor.
Davy8
Você pode gerar facilmente a grade de alta resolução desfocando o original. Em seguida, defina um limite de, digamos, 0.5para células de alta resolução a serem preenchidas ou não. Assim, o uso de uma grade de alta resolução me parece bastante hacky.
danijar