Há alguns problemas que encontrei no meu jogo baseado em ruído Perlin. Dê uma olhada na captura de tela em anexo abaixo.
As áreas brancas que você vê são paredes e as áreas pretas são passáveis. O triângulo no meio é o jogador.
Eu implementei a física neste jogo, desenhando-a em uma textura (pixels brancos ou pretos) e depois obtendo isso da CPU.
No entanto, agora estou com um problema diferente em mãos. Quero que as unidades (ou creeps, como você as chama) sejam geradas constantemente, na borda da tela. O ponto aqui é que, no jogo final, haverá um "nevoeiro de guerra" que não permite que o jogador veja tão longe assim.
Imaginei que poderia apenas digitalizar os pixels na borda da tela e ver se a textura física deles era preta, e então gerar coisas aleatoriamente lá. No entanto, se você der uma segunda olhada na captura de tela, existe (no canto superior esquerdo) um exemplo de onde eu não gostaria que os creeps aparecessem (já que eles não seriam capazes de alcançar o jogador de lá) .
É possível que, de alguma forma, a GPU determine esses pontos de reprodução para mim, ou de alguma maneira diferente? Pensei em criar vetores entre o ponto proposto na borda da tela e o player e segui-lo a cada 10 voxels, e ver se uma parede colide antes de gerar uma unidade lá.
No entanto, a solução proposta acima pode exigir muita CPU.
Alguma sugestão sobre este assunto?
Nota 1 Para as unidades geradas, não quero usar nenhuma forma de busca de caminhos para evitar colisões na parede, pois essas unidades correm em direção ao jogador. Portanto, as unidades devem aparecer na borda da tela, em um local em que caminhar em linha reta em direção ao jogador não colidir com nenhuma parede.
fonte
Respostas:
Existe um algoritmo bastante útil para este trabalho, muito mais eficiente do que o algoritmo de inundação nesta situação (sua complexidade é o tempo de execução é proporcional ao tamanho do limite, em vez da área inundada): é o algoritmo de quadrados de marcha. O conceito é simples: comece a localização dos jogadores (ponto médio da tela), escolha uma direção e caminhe até encontrar uma parede. Ao colidir com a parede, você inicia o algoritmo: escolhe uma orientação (para cima ou para baixo) e começa a marchar sobre o limite dessa área, destacando os pixels. Isso fornece o limite interno para a área permitida. Depois, você simplesmente verifica se os pontos candidatos às unidades de reprodução estão nesse limite.
Este é o princípio que você deve seguir para executar o limite:
http://en.wikipedia.org/wiki/File:Marchsquares.png (meh ainda não posso postar fotos)
Descrição da Wikipedia (embora tenha muito mais complexidade porque é usada com outros aplicativos em mente):
http://en.wikipedia.org/wiki/Marching_squares
fonte
Faça uma inundação a partir da posição do jogador; toda área "inundada" é então uma área de recreação válida, e todas as outras são paredes.
EDIT: Quanto ao requisito adicional "alcançável em linha reta", lembre-se de que em um espaço discreto , é necessário definir um pouco mais. Por exemplo, todos os caminhos acima podem ser uma "linha reta" válida em um ambiente assim, e eu já vi todos eles usados em um jogo em algum momento ou outro:
Em particular, a maioria deles não é comutativa - o que significa que apenas porque você pode alcançar B de A em uma "linha reta" não significa que você também pode alcançar A de B; nem o oposto é necessariamente verdadeiro.
Além disso, há a questão de como você lida com o movimento diagonal se um ou ambos os pontos "laterais" estão bloqueando.
fonte
Que tal apenas deixar os filhotes acontecerem? Não vejo nenhum problema em particular nisso.
fonte
se for importante marcar apenas pontos com uma linha reta válida para o player, você pode usar um algoritmo como o seguinte (é um código c ++), ele consome mais do que o preenchimento normal. pode haver alguns bugs menores (ficarei feliz se alguém os corrigir), já que eu não testei o código sozinho, mas você entenderá.
fonte
Você pode preencher o mapa com cores que representam áreas convexas ..., dessa maneira você pode gerar sua unidade se estiver na mesma área. Ou você pode procurar mais facilmente áreas acessíveis.
Esses são dados estáticos, para que você possa pré-calcular.
você tinha que preencher os pontos de localização da imagem onde há uma mudança de convave para convexa, visualmente parece fácil de encontrar, você tem duas situações:
fonte
Aqui está algo que eu realmente usei no meu próprio jogo (mundo simplificado gerado por ruído em 2D, quase exatamente como o seu) - Raios. Comece no jogador, determine uma orientação (aleatória, se quiser) e siga essa linha até atingir algo (borda da tela OU asteróide). Se você atingir a borda da tela (e não um asteróide / blob branco), saberá que há uma linha reta e aberta da borda da tela até o player. Então crie um monstro no ponto em que você acertar. Se você acertar um asteróide, refaça o teste.
fonte
Outra solução (sem GPU) que você pode usar é a localização de caminhos. Antes de desenhar o mapa, localize o caminho a partir de cada ponto de desova em potencial em cada extremidade do mapa e veja se existe um caminho para o centro. Uma descoberta de caminho * é bastante boa em custo / desempenho, mas você pode fazer isso antes do jogo começar, se isso for um problema.
Qualquer ponto de desova que não possua um caminho pode ser colocado em uma lista de exclusão; ou vice-versa (qualquer ponto com um caminho pode ser colocado em uma lista de inclusão).
fonte