Clone PyGame QIX, preenchendo áreas


8

Estou brincando com o PyGame.

Agora estou tentando implementar um clone do QIX .

Eu tenho meu loop de jogo e posso mover o jogador (cursor) na tela.

No QIX, o movimento do player deixa um rastro (cauda) na tela, criando uma polilinha.

Se a polilinha com os limites da tela criar um polígono, a área será preenchida.

Como posso realizar esse comportamento?

Como armazenar a cauda na memória?

Como detectar quando ele cria uma forma fechada que deve ser preenchida?

Eu não preciso de uma solução exata de trabalho, alguns ponteiros, nomes de algo seria legal.

insira a descrição da imagem aqui

No início, existe apenas a borda cinza, onde o jogador pode mover o cursor.

  • Primeiro cenário:

O usuário move o cursor do ponto A até o ponto B, desenhando a multilinha vermelha até o ponto C. Nesse ponto, por cruzar a borda, o ponto A deve ser conectado automaticamente ao ponto C, criando um polígono, que deve ser preenchido ( aquela coisa laranja no meu desenho). Preencher o polígono é muito simples no PyGame, porque eu forneço a sequência de pontos e o PyGame se importa com o resto.

  • Segundo cenário:

O usuário se move na borda para o ponto D, de onde ele desenha uma linha para o ponto E. Como ele está cruzando a linha do polígono anterior e, com suas linhas e a borda, outro polígono pode ser criado, ele também deve ser preenchido. (o verde).

  • Terceiro cenário:

O jogador avança no polígono (ele pode se mover nas linhas poligonais existentes) e desenha uma linha do ponto G ao ponto F. Aqui, novamente, devido à borda e às linhas existentes, outro polígono deve ser preenchido (o azul) .


Talvez haja algumas respostas aqui (pergunta semelhante): gamedev.stackexchange.com/questions/26377/…
tigrou

Obrigado, mas o link mostra casos de uso primitivos. Eu atualizei a minha pergunta, então talvez seja mais claro o que eu tento acomplish
astropanic

Respostas:


5

Aqui está como eu abordaria isso:

  1. Sempre existe uma única área aberta, representada por um polígono. Todas as outras áreas são irrelevantes.
  2. Uma linha começa quando você se move do perímetro do polígono para o interior do polígono.
  3. Uma linha para quando você se move do interior do polígono de volta para o perímetro.
  4. Quando você para a linha, divide o polígono em dois polígonos.
  5. Você decide qual dos dois polígonos preencher e quais manter como área aberta. Em Qix, o lado em que o Qix (inimigo) ficava aberto e o outro lado estava cheio.

Como subdividir o polígono? Você usa os pontos finais da sua linha para dividir o perímetro do polígono em duas seções e, em seguida, a nova linha para concluir essas duas seções em novos polígonos.

Por exemplo, digamos que sua área aberta seja um polígono com pontos [p0, p1, p2, p3, p4, p5]. Seu ponto inicial Aocorre entre p1e p2, e seu ponto final Bocorre entre p3e p4. A nova linha que foi desenhada é [A, s, t, u, v, B]. Primeiro dividimos o polígono em dois segmentos [A, p2, p3, B]e [B, p4, p5, p0, p1, A]. Esses dois segmentos juntos formam o polígono original. Em seguida, colamos a nova linha em cada uma (uma para a frente, outra para trás), formando [A, p2, p3, B, v, u, t, s]e [B, p4, p5, p0, p1, A, s, t, u, v]. Você preenche um desses polígonos e mantém o outro como sua nova área aberta.

Eu não implementei isso e não sei ao certo se funcionará, mas essa é a abordagem que eu usaria: subdivisão de polígono em vez de preenchimento de polígono.


1

Este é um problema que envolve várias subetapas discretas. Aqui está um resumo do que eu sugeriria:

  • Aguarde até o jogador formar uma interseção de várias linhas
  • Obtenha um pixel de cada lado da interseção
  • Pathfind para ver se eles podem se conectar
  • Pixels que não podem se conectar são áreas separadas
  • Realize um preenchimento para obter todos os pixels na área

Eu armazenaria o estado dos pixels do jogo em uma matriz Numpy (org numpy dot scipy dot org). A cor pode ter três matrizes separadas para RGB, mas a matriz em que vou focar é a matriz de linhas / sem linhas. Apenas inicialize-o com zeros e defina-o para o tamanho do seu campo de jogo, e toda vez que o jogador passar por um pixel, defina o item correspondente na matriz como 1. Você deseja exibi-los na tela com uma cor diferente , como eles são sua linha!

Toda vez que o pixel do jogador se move, eu verificava se ele passou (e desenhou uma linha ao lado) de uma linha existente. Nesse caso, eu obteria um pixel de cada divisão possível:

. . . | . 
. . . | . 
. . . | x 
. . x < -

Pontos são pixels vazios, linhas são (obviamente) linhas e Xs são os pixels vazios que queremos selecionar. Podemos fazer isso da seguinte maneira:

  • Adicione todos os pixels vazios adjacentes ao player / cruzamento em uma lista.
  • Percorra a lista removendo pixels se o próximo item da lista for adjacente (no campo do jogo) ao item em que você está.

Depois de ter pixels de todos os lados possíveis da interseção, execute A * em cada par possível. (Consulte http://www-cs-students.stanford.edu/~amitp/gameprog.html#paths ou o Google a-star para obter mais informações.) Se for possível encontrar um caminho entre um par, remova um dos pixels conectados da lista.

Depois de percorrer e percorrer todos os pares, os pixels restantes devem estar em uma área fechada e separada! Para obter todos os pixels em cada área, execute um preenchimento de inundação a partir do pixel da área. Veja http://en.wikipedia.org/wiki/Flood_fill .

Boa sorte!


0

Suas áreas são apenas uma série de pontos. O trabalho duro consiste em pegar a série de pontos formando (geralmente) um polígono côncavo e triangulando-os para que você possa renderizar e provavelmente projetar uma textura neles. Veja http://en.wikipedia.org/wiki/Polygon_triangulation para mais detalhes


11
não é um problema de triangulação, o PyGame cuida disso. Atualizei minha pergunta com uma imagem e, em alguns casos de uso, dê uma olhada para entender melhor. Obrigado de qualquer maneira
astropanic
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.