Como represento projéteis em um videogame?

14

Estou fazendo um jogo simples de tiro fixo, semelhante ao "Galaga" ,) como parte de uma apresentação que estou fazendo. Estou imaginando que estratégias e estruturas de dados as pessoas usariam para rastrear projéteis, como lasers disparados da nave espacial. Uma implementação super simples que eu usei antes é apenas representar cada projétil como um ponto e verificar colisões com todos os objetos na cena.

No entanto, isso parece caro, em grandes cenas com muitos projéteis; Estou imaginando que outros tipos de estratégias ou implementações são usadas para esse tipo de caso de uso. O que jogos como o FPS usam para rastrear projéteis (balas, cartuchos de tanque, etc.)?

Polaris878
fonte
5
Muitos jogos de FPS assumem que os marcadores são instantâneos, mas existem aqueles que calculam trajetórias e tempo de viagem.
John McDonald
2
+1 é uma ótima pergunta, e eu também não limitaria a 3d necessariamente.
ashes999

Respostas:

8

Para projéteis muito rápidos (como lasers ou balas), você pode usar um raio .

Um raio tem um ponto inicial e um ponto final. Uma estrutura de dados (mínima) para um raio é:

struct Ray
{
  Vector3f start, end ;
} ;

Se parece com isso:

insira a descrição da imagem aqui

(Você também pode armazenar em cache o vetor e o comprimento da direção, mas usei uma definição muito simples acima).

Se o raio é um feixe de laser que viaja na velocidade da luz, você apenas o mantém (como começar no bico da pistola e terminar em uma parede em algum lugar) por alguns quadros. Qualquer coisa que cruze o raio de cada quadro sofre danos.

Se o raio é um projétil mais lento (como uma bala, por exemplo), a distância que a bala percorreu ao longo de um passo temporal é modelada pelo raio. O ponto inicial é onde o raio está no início do quadro e o ponto final é onde o raio estará após o término do quadro. Qualquer coisa no caminho do raio da bala é danificada pela bala.

Os raios podem ser colididos com eficiência com esferas, esferas, cascos convexos etc. Confira meu projeto Hullinator para obter um programa de execução real (CTRL + Clique para disparar raios)

bobobobo
fonte
1
Um raio não funciona muito bem para muitos projéteis. Por exemplo, qualquer projétil que possa ser arremessado, como conchas de tanques. Entretanto, os raios são ótimos para projéteis de tiro certeiro.
Michaelhouse
Bem, se o reservatório é extremamente lento em movimento (em comparação com uma bala ou laser), então sim eu modelá-lo como um corpo normal (assim como o jogador)
bobobobo
7
Tecnicamente, um raio é um ponto de partida e uma direção. Isso pode ser determinado COM um ponto inicial e outro ponto, mas isso não faz parte de sua definição. Por definição, os raios são infinitos e não têm ponto final.
Casey Kuball
1
Você está certo, o que descrevi é na verdade um segmento de linha , mas a maioria das pessoas os chama de raios quando se fala em detecção de colisões.
bobobobo
3

Usar um raio funciona bem para viajar instantaneamente projéteis, como balas. Para projéteis com velocidade mais lenta, como o tipo que você utilizará para o seu jogo espacial, faz sentido simplesmente rastrear sua posição no mundo do jogo como faria com qualquer outra entidade. O que costumo fazer é ter uma classe base chamada Entidade, que contém propriedades de qualquer objeto duradouro do jogo - posição, rotação, caixa de colisão, etc. a superclasse Entidade, não cada tipo individual de entidade.

Para aumentar o desempenho, é muito comum manter um pool para todos os objetos que você criará e destruirá com frequência. Quando você precisar de um novo projétil que retiraria desse pool, modifique o novo projétil conforme necessário e retorne-o de volta ao pool quando ele expirar.

JPRO
fonte
2

Quando você deseja otimizar a detecção de colisões, pode armazenar todos os objetos do jogo em uma árvore bidimensional ou tridimensional . Essa estrutura de dados torna muito eficiente recuperar todos os objetos em uma determinada área.

No entanto, as árvores binárias têm a desvantagem de degenerar facilmente quando objetos são adicionados, removidos e alteram suas posições, portanto, você precisará balancear automaticamente .

Um compromisso que seria mais fácil de implementar, mas não seria tão eficiente, seria usar uma abordagem baseada em partes. Divida o campo de jogo em cubos e acompanhe quais objetos estão tocando em cada cubo. Ao verificar colisões com um objeto, você só precisa compará-lo com as listas de objetos dos cubos em que está tocando (substitua "cubo" por "retângulo" para um jogo em 2D).

Philipp
fonte