Como crio partículas que reagem ao jogador e aos inimigos?

38

Atualmente, estou criando um jogo com meu próprio mecanismo de jogo, que escrevi em C ++, e estou usando o SDK do directx mais recente.

O jogo é um shooter espacial de cima para baixo (com uma reviravolta bastante interessante) e estou procurando um tipo de efeito nebuloso pelo qual o jogador voará. Eu realmente quero experimentar essa sensação tátil agradável de centenas de partículas saindo do caminho da nave do jogador enquanto ela voa para elas. De certa forma, como as partículas se moveriam no caminho do jogador em Geomtry Wars no XBLA.

Eu sou um programador experiente quando se trata de C ++. Não sei, no entanto, como começar a implementar esse efeito. Alguém tem alguma idéia legal ou opções de design que eu possa querer examinar? Sinta-se à vontade para responder a qualquer grau de profundidade que desejar.

Matt McDonald
fonte

Respostas:

65

É uma ideia legal. Você precisaria de algum tipo de gradiente de difusão ao redor do seu navio. Existem três modelos físicos em que posso pensar:

  1. Você quer que pareça quase um meio líquido, onde o gradiente de pressão se reequilibra, ou seja, depois de passar algumas partículas, elas retornam ao seu rastro (como a água atrás de um barco). Nesse caso, as posições das partículas são absolutas, e é apenas a relação delas com o jogador que modifica temporariamente sua posição de renderização . É um pouco como quando você passa uma lupa grossa sobre as coisas, e a difração parece fazê-las se mover - mas apenas até você afastar o vidro. Nesse caso, seu navio é o vidro.

  2. Se você deseja que eles se afastem do navio e continuem se movendo depois que se mudarem. É como a física padrão em espaços geralmente vazios, onde não há gradientes de pressão (ou muito pequenos).

  3. Você deseja mover as partículas para longe do navio rapidamente à medida que se aproxima, como em (1) e (2), mas assim que o navio se for, as partículas se reequilibrarão lentamente para se tornarem equidistantes.

Comum a todas as três soluções : você precisa ter um campo de difusão que se mova com sua nave. Neste exemplo, vamos torná-lo circular. Em seguida, você detecta o vetor, chamado v1, entre a nave e cada partícula nessa região. Empurre sua partícula ao longo desse vetor. A força com que você o afastará dependerá da distância do navio: use 1 - v1.magnitude. Essa fórmula fornecerá uma força linear; no entanto, você pode modificá-la para usar outra coisa como uma curva de força circular que diminui a força em direção às arestas. Isso pareceria mais com um gradiente de pressão esférica do que circular ao redor do navio.

Para a solução 1 : Tudo o que você faz agora é modificar a posição de renderização dessa partícula (ou seja, a posição do sprite) em cada atualização de renderização , por esse vetor. Como você está fazendo dessa maneira, isso é puramente um efeito de renderização e não afeta a posição real do mundo da partícula. Assim, você adiciona a posição mundial ao deslocamento da renderização (v1) e agora possui partículas bem deslocadas à medida que se move em direção a elas ou ao lado delas, e reverte suavemente as partículas à medida que passa (atrás de você).

Para a solução 2 : em vez de apenas aplicar v1 à posição de visualização, aplique-a em cada atualização lógica , na posição da partícula. Então p1.position += v1,. Então você está aplicando uma força aceleradora na partícula, que se traduz em velocidade. Provavelmente, você deseja que a velocidade de cada partícula seja diminuída para que elas diminuam gradualmente e parem assim que você passar. Você pode ver como essa solução resultará em partículas agrupadas em sua nebulosa, porque elas nunca serão difundidas. Não é muito realista, tenho certeza, já que as nebulosas têm gradientes de pressão dentro delas, não importa quão fraca seja a realidade.

Para solução 3: O mesmo que (2), mas neste caso você terá que redifundir suas partículas. Fazer isso com facilidade é uma abordagem de força bruta, mas como essas são apenas partículas e, portanto, atraentes, você provavelmente não precisará cobrir uma área enorme de interesse (provavelmente apenas um raio de playerPosition + maxPlayerSpeedPerTick ou qualquer outra coisa área retangular circunscreve isso, para fins lógicos). Cada partícula aplicará uma força sobre a outra partícula dentro da área de interesse. Eles aplicarão forças baseadas, mais uma vez, nas distâncias entre si. Calcule todas as forças interpartículas em uma única varredura na área de interesse e aplique todas as forças em uma única varredura. Por fim, certifique-se de executar apenas esse processamento de força entre partículas em partículas com velocidade zero. E uma vez que qualquer partícula atinge uma velocidade mínima,

Existem todos os tipos de fórmulas de difusão, etc., mas acho que, neste caso, uma solução simples funciona melhor.

Engenheiro
fonte
Companheiro, infelizmente, atualmente não tenho a reputação de aprovar sua resposta (e só poderia fazê-lo uma vez, o que é menor do que merece). Você acertou em cheio o que estou procurando em sua primeira solução. Resposta fantástica. Honestamente. Obrigado!
Matt McDonald
Prazer total Matt, é uma boa pergunta e vale a pena flexionar o cérebro!
coordenador
Também decidi que, com pouquíssima alteração no código, isso poderia se aplicar a asteróides menores dentro de um cinto. Obrigado novamente.
Matt McDonald