Estou fazendo um jogo de defesa em torre 2D. Até agora eu tenho uma matriz 2D que funciona como uma grade para o meu jogo. Sou capaz de colocar torres nele, executar inimigos e algumas coisas de arrasto e torre.
Agora estou enfrentando um problema na lógica de posicionamento da torre. Quero que sempre haja um caminho percorrido pelos inimigos, o que significa que o usuário não deve ser capaz de bloquear completamente o caminho colocando torres. Por exemplo. se o usuário colocar torres verticalmente em um mapa, o algoritmo deverá impedir a colocação de uma torre que completará a linha vertical. Ou, de qualquer outra forma, deve haver pelo menos um espaço livre (passável) para que o inimigo possa escapar.
Minha lógica atual verifica em todas as direções sempre que a torre é colocada. Se houver uma torre para cima, ela chamará novamente a mesma função nessa torre superior até atingir uma parede. Retorna 1 para parede superior e 5 para parede inferior e retorna a função (torre para cima / baixo) se houver uma torre. aqui está o código:
int checkCollision(tower)
{
if( there is a tower up)
return checkCollision(up tower);
if(there is a tower down)
return checkCollision(down tower);
......all directions.....
if( there is a wall on UP )
return 1;
if( there is a wall DOWN )
return 5;
....all walls......
return 0;
}
Agora, o que eu quero é verificar simultaneamente se existe uma parede norte e uma parede sul ou verificar outras direções com qualquer outra possibilidade (como para cima, para baixo, diagonal para cima, diagonal para baixo ... e assim por diante) para não deixar o usuário coloque uma torre, pois deve haver um lugar para o inimigo.
Estou insatisfeito com meu código no momento. Quero dizer, meu código diz que uma parede foi encontrada, mas como posso verificar se uma parede é encontrada em uma direção e uma parede também é encontrada em outra direção? Não quero entrar em possibilidades como:
if(checkCollision(tower) == 1 && checkCollision(tower) == 5)
"You cannot place"
Eu quero algo como:
if( any combination of more than 2 wall found and there is entry/exit point in between) //so it is wall to wall
"You cant place"
Eu também tentei pré-calcular sinalizadores se houver paredes nos dois lados (como de cima para baixo, de diagonal etc.), então não deixe o usuário colocar a torre, mas isso ainda não funciona.
fonte
Respostas:
Não seria mais simples usar um algoritmo de busca de caminhos para verificar se a IA ainda tem uma rota clara? Presumivelmente, você já usa um para fazer com que os inimigos naveguem da entrada até a saída; basta executá-lo com a torre adicionada e, se falhar, a torre não será permitida.
fonte
Suponho que você já tenha algum código (usando algo como o algoritmo A * ) para que os inimigos encontrem um caminho para seu destino. Toda vez que o jogador tenta colocar uma torre, você pode simplesmente colocar um obstáculo temporário onde a torre estaria e executar o código de busca de caminhos para verificar se ainda haverá um caminho para os inimigos.
Você pode otimizar isso de várias maneiras. Por exemplo, se a torre recém-colocada tocar apenas no máximo um obstáculo existente, não poderá bloquear o caminho. Você também pode salvar os resultados de verificações anteriores (pelo menos até que algo mude), para que, se o jogador tentar o mesmo local várias vezes, não precise verificar novamente todas as vezes.
Também existem algumas técnicas que só funcionam em alguns casos. Por exemplo:
Se o campo de jogo for bidimensional, há um truque inteligente baseado no fato de que existe um caminho claro do lado esquerdo para a direita, se e somente se não existir uma parede contínua de cima para baixo. Assim, você pode rotular cada torre (ou outro obstáculo) dependendo de qual lado do campo de jogo estiver conectado, se houver algum, por uma parede.
Manter essas etiquetas à medida que novas torres são adicionadas é fácil e rápido. Se uma nova torre ligasse os dois lados, bloqueava o caminho dos inimigos. Claro que, se uma torre é removida, você ainda tem que recalcular os rótulos, mas você só precisa fazer isso quando a torre é realmente destruído, em vez de cada vez que o jogador simplesmente passa o cursor sobre um local potencial para uma nova torre.
fonte
Concordo com o SimonW que você deve executar seu algoritmo de processamento. Para ser completo, eis um truque usado pelos mapas TD de Starcraft / Warcraft, que não têm como verificar se o algoritmo de caminho passa / falha.
Digamos que os inimigos possam vir de qualquer lugar do topo da área edificável e ter que passar para qualquer lugar abaixo da área edificável; e existem paredes à esquerda / direita. Faça uma inundação de todas as torres tocando a parede esquerda. Se alguma torre encontrada tocar na parede direita, o caminho está bloqueado.
fonte
deveria ser mais como
mais tarde, no seu código, onde você deseja verificar se é permitido colocar a torre ou não:
Além disso, altere seu algoritmo para adicionar a capacidade de retornar as coordenadas de qual bloco de parede foi encontrado adjacente à sequência de torres. Verificar se o mesmo revestimento foi devolvido e descartar o que permitiria passar por loops de torres também.
Por loop de torre, quero dizer (não me importo com a minha arte ascii):
Não permitiria que você colocasse uma torre em X. A torre acima, a torre nas diagonais, a torre à direita e a torre abaixo de tudo reportarão colisões de paredes, no entanto, a coordenada do revestimento será a mesma. É isso que você precisa filtrar também.
fonte
Fácil, eu acabei de criar meu primeiro programa de localização de caminhos hoje, levei um pouco mais de 2 horas e, além de declarar variáveis, são apenas 27 linhas de código, incluindo colchetes.
programe no seu pathfinder uma matriz para todas as suas paredes reais e uma matriz para todas as suas paredes hipotéticas, se um jogador quiser fazer uma torre em um espaço, o espaço selecionado será uma parede hipotética; Execute o seu pathfinder para incluir paredes hipotéticas; se o programa voltar com um caminho encontrado, a torre poderá ser construída; caso contrário, a torre não poderá ser construída.
Felicidades
Aqui está o meu código,
}
Basicamente, meu código criará uma matriz de seqüências de caracteres X e Y de pareamento. Em seguida, minhas unidades móveis herdam as primeiras seqüências de emparelhamento bem-sucedidas e, em seguida, elas apenas desativam as seqüências, um segmento de cada vez. Cada coordenada é quebrada com um "$".
E o mais bonito do código acima é que 'keep going' só terá tamanho tão grande quanto o tamanho da grade e se tornará mais eficiente com as mais torres colocadas, sua eficiência sendo maximizada quando houver apenas um caminho definido.
Se você precisar de alguma ajuda com o que eu tenho acima aqui, informe-me.
fonte