Jogo 2D C # clique para mover amostras?

7

Atualmente estou aprendendo a usar o XNA fazendo um jogo 2D. Até agora, estou indo bem, mas quero implementar um clique para mover em vez de usar as teclas para passear, mas não encontrei nenhum exemplo e não tenho noção de como abordá-lo.

Eu sei que o XNA funciona bem para controles e teclado do xbox, mas não vi nada relacionado à interação do mouse. Também não me importo com o xbox, já que não estou buscando nada além de um jogo para PC.

Então, o que eu estou procurando são alguns exemplos de como o clique para mover é calculado e se o ícone do mouse exibido no jogo também é trabalhado a partir da estrutura xna ou se você precisa fazer o seu próprio modo para fazer o azulejo atual brilha ou mostra que o mouse está lá ou algo parecido.


ATUALIZAR:

Mover-se com o mouse não é exatamente o mesmo, você deve considerar também os obstáculos, pelo menos no meu caso do que estou planejando ...

Por exemplo, eu quero que os cliques sejam considerados uma caminhada direta, forçando o usuário a navegar no mapa em vez de navegar automaticamente pelo usuário por clique. Se ele clicar em uma parede, por exemplo, ele caminha até a parede e para em vez de encontrar o caminho para o outro lado, se houver uma ... outra dúvida que me vem à mente usando o estado de X e Y, por exemplo, em uma janela de rolagem, ele realmente reconhecerá onde está o mouse ou haverá a necessidade de cálculo na tela para divulgar onde o ponto B foi clicado pelo usuário?


Obrigado por qualquer ajuda e conselhos ...

PS: Alguém poderia adicionar a tag clique para mover ou o mundo para a tela?

PPS: por que não me permite adicionar a tag C #?

Prémio
fonte
Marcado novamente com C # e 2D, não vejo por que o clique para mover ou o mundo para a tela seria necessário como tags. Além disso, apenas para que tudo possa ser focado, não parece que a segunda pergunta que você faz está realmente relacionada à sua primeira. Poste isso em uma pergunta separada.
Jesse Dorsey
Por que você teria uma janela de rolagem? Normalmente, a janela é apenas uma porta de visualização para uma determinada parte do seu mundo. Definitivamente, você poderia fazer uma equação linear do ponto a ao ponto b. Então você pode usar algumas funções curvas para fazer algumas coisas legais, como acelerar no início e desacelerar no final.
Michael Coleman
Mencionei como exemplo, não uso a janela de rolagem. Você pode ter entendido mal o forcing the user to navigate himself on the map instead of auto-navigating the user per clickque é basicamente quando o usuário clica em um local determinado, ele moverá a janela enquanto o jogador se move, mas se o jogador tentar clicá-lo dentro de uma casa onde a porta está fechada, por exemplo, ele irá caminhar em direção à casa em um local determinado. linha reta e pare no primeiro obstáculo, o que significa que o usuário não tem um clique de navegação automática para se mover, mas ele deve clicar no seu próprio caminho para o local que deseja ir.
Prix

Respostas:

6

Edit: Ok, acabei de ler em um de seus comentários que você não deseja navegação automática. Nesse caso, considere apenas a seção final deste post ("Percorrendo esse caminho") com o caso simples de que a lista armazena apenas o local em que o mouse clicou e se limpa quando um obstáculo é encontrado. Também notei que você mencionou peças uma vez no post. Nesse caso, não há necessidade de um gráfico de visibilidade, a própria grade pode ser usada para rodar uma estrela A. Enfim, ainda estou postando isso como uma solução mais geral para o ponto 2D e clique no problema de navegação.

O que você está pedindo é como fazer a busca de caminhos em um ambiente 2D. Eu escrevi um artigo antes de descrever uma técnica que é capaz de resolver esse problema. Começarei estabelecendo um link para o artigo e adicionarei uma breve explicação do algoritmo.

http://www.david-gouveia.com/pathfinding-on-a-2d-polygonal-map/

Obviamente, essa não é a única maneira de resolvê-lo. Estou usando um gráfico de visibilidade. Você também pode usar uma malha de navegação. Ou uma grade. O gráfico de visibilidade tem uma vantagem particular: ele sempre retorna o caminho mais direto entre os pontos, sem a necessidade de corrigir o caminho. E construindo o gráfico de visibilidade no topo de um polígono, você pode especificar as regiões que podem ser percorridas com precisão.

Conceito

A idéia principal aqui é representar sua região percorrível como um polígono e construir um gráfico de visibilidade usando os vértices côncavos do polígono . Se o polígono contiver orifícios, você também usará seus vértices convexos .

Criar um gráfico de visibilidade significa pegar todos os nós (ou vértices, neste caso) do gráfico e conectá-los a todos os outros vértices que ele pode "ver". Você precisa de uma verificação da linha de visão para fazer isso. O que eu usei foi construído sobre um teste simples de interseção de segmento de linha, com algumas verificações adicionais.

Então, sempre que você quiser encontrar o caminho entre dois locais, adicione-os temporariamente ao gráfico de visibilidade e execute um algoritmo A * pathfinding clássico .

Aqui está a aparência de toda a estrutura:

gráfico de visibilidade

Onde:

  • As linhas amarelas são o polígono que representa onde você pode andar.
  • Os círculos brancos são os vértices poligonais que compõem o gráfico de visibilidade (nós)
  • As linhas roxas conectam vértices que estão alinhados entre si (arestas).
  • A linha azul clara é um exemplo de localização de um caminho entre dois locais (ponto verde e ponto vermelho).
  • As linhas verdes claras são arestas temporárias adicionadas ao gráfico junto com os nós inicial e final no caminho (ponto verde e ponto vermelho).

Implementação

1) Representação

Para implementar isso, primeiro você precisa ter uma maneira de representar um polígono para o seu piso. A seguinte classe deve ser suficiente:

public class Polygon
{
    public class SimplePolygon
    {
        List<Vector2> Vertices;
    }

    List<SimplePolygon> Outlines;
    List<SimplePolygon> Holes;
}

2) Selecionando nós

Depois, você precisa percorrer cada um dos vértices do polígono e decidir se eles devem ser nós no gráfico de visibilidade. O critério para isso é vértices côncavos no contorno e vértices convexos nos furos. Eu uso uma função como esta:

public static bool IsVertexConcave(IList<Vector2> vertices, int vertex)
{
    Vector2 current = vertices[vertex];
    Vector2 next = vertices[(vertex + 1) % vertices.Count];
    Vector2 previous = vertices[vertex == 0 ? vertices.Count - 1 : vertex - 1];

    Vector2 left = new Vector2(current.X - previous.X, current.Y - previous.Y);
    Vector2 right = new Vector2(next.X - current.X, next.Y - current.Y);

    float cross = (left.X * right.Y) - (left.Y * right.X);

    return cross < 0;
}

3) Selecionando arestas

Agora você precisará examinar cada par desses vértices e decidir se eles estão na linha de visão ou não. Eu usei o seguinte método como ponto de partida para essa verificação:

static bool LineSegmentsCross(Vector2 a, Vector2 b, Vector2 c, Vector2 d)
{
    float denominator = ((b.X - a.X) * (d.Y - c.Y)) - ((b.Y - a.Y) * (d.X - c.X));

    if (denominator == 0)
    {
        return false;
    }

    float numerator1 = ((a.Y - c.Y) * (d.X - c.X)) - ((a.X - c.X) * (d.Y - c.Y));

    float numerator2 = ((a.Y - c.Y) * (b.X - a.X)) - ((a.X - c.X) * (b.Y - a.Y));

    if (numerator1 == 0 || numerator2 == 0)
    {
        return false;
    }

    float r = numerator1 / denominator;
    float s = numerator2 / denominator;

    return (r > 0 && r < 1) && (s > 0 && s < 1);
}

Mas teve que recorrer ao uso de alguns outros hacks para obter estabilidade em casos extremos, por isso não está em boas condições para postar. Ainda tentando descobrir uma solução limpa e estável para o problema.

4) Construa o gráfico e execute uma estrela A

Você precisará criar um gráfico de visibilidade usando esses vértices e arestas e executar A * nele. Para aprender a construir um gráfico e aplicar A *, recomendo estudar o seguinte artigo:

http://blogs.msdn.com/b/ericlippert/archive/2007/10/02/path-finding-using-a-in-c-3-0.aspx

Você pode querer encapsular tudo isso em uma única classe, para ter uma interface fácil de usar, como:

public class Floor
{
    public Floor(Polygon polygon) 
    { 
        _polygon = polygon; 
        BuildGraph();
    }

    public IEnumerable<Vector> GetPath(Vector2 start, Vector2 end)
    {
       // Add start and end as temporary nodes and connect them to the graph
       // Run A* on the graph
       // Remove temporary nodes and edges
    }

    private Polygon _polygon;

    private Graph _graph;
}

Dessa forma, você só precisa criar uma instância do Floor e chamar o método GetPath sempre que precisar encontrar o caminho entre dois locais.

5) Trilhando esse caminho

Finalmente, você precisa fazer seu personagem percorrer o caminho gerado. Ele precisa ter algum tipo de memória interna para isso, mas não é muito difícil implementá-lo. Por exemplo:

  1. Adicione uma lista dentro do personagem para armazenar o caminho que ele está seguindo no momento.
  2. Em cada ciclo de atualização, pegue o primeiro valor da lista e mova seu personagem para ele.
  3. Se ele chegar perto o suficiente do destino, remova o primeiro elemento da lista e repita.
  4. Se a lista ficar vazia, ele chegou ao seu destino.
David Gouveia
fonte
Resposta incrível, eu nem vou me incomodar em responder porque acho que você cobriu qualquer coisa que eu pudesse dizer. +1
Joshua Hedges
3

Bem ... Enquanto você está aprendendo, não esqueça que o Google é seu verdadeiro amigo neste fim de semana.

A etapa 1 é obter a localização do mouse - http://msdn.microsoft.com/en-us/library/bb197572.aspx

O passo 2 é mover o sprite para o local A para o local B, que envolve física / movimento básico - http://www.xnadevelopment.com/tutorials/thewizard/theWizard.shtml

A idéia é a mesma que mover o mouse para obter o seu destino onde o usuário clica. Você ainda está indo do ponto A ao ponto B.

O que você está descrevendo é um detalhe de implementação, com o qual você pode determinar como deseja lidar. Estou assumindo que você está trabalhando com algum tipo de grade. Os ladrilhos nessas grades terão propriedades específicas, como facilidade de locomoção. Tente mover seu sprite um passo mais perto na direção do destino. Se um bloco não puder ser percorrido, pare.

Se você deseja que seu sprite realmente atinja o destino desejado, implemente um algoritmo de busca de caminho real que analise a capacidade de caminhar dos ladrilhos.

David McGraw
fonte
obrigado pelo primeiro link que ajuda, mas o segundo não tanto, eu atualizei minha pergunta com alguns outros pontos, se você não se importa de verificar ... obrigado.
Prix