Considere um jogo cuja resolução padrão seja 800x600. Objetos com máscaras de colisão são colocados em um mundo de jogo de tamanho 800x600. As máscaras de colisão podem detectar quando o mouse colide com elas.
Agora considere escalar o jogo em 1024x768 (suponha que escalemos os gráficos simplesmente renderizando tudo em uma camada e depois escalando a camada inteira de uma só vez). Temos duas opções para fazer com que as colisões com o mouse funcionem corretamente nesta nova resolução:
A.) Escale o mundo para 1024x768 e dimensione a máscara de colisão de cada objeto de acordo.
B.) "Mapeie" a posição do mouse no mundo original (800x600).
Por "mapa", quero dizer, basta escalar a posição do mouse no mundo original de 800x600. Por exemplo, se a posição do mouse na tela for (1024, 768), a posição do mouse no mundo será (800, 600).
Agora, obviamente, a opção B requer muito menos computação e provavelmente é menos propensa a erros geométricos, mas também parece meio "hack" para mim, como se houvesse conseqüências imprevistas de seguir esse método que serão um inferno para corrigir mais tarde.
Com qual método devo ir: A, B ou outra coisa?
fonte
Respostas:
Normalmente (mesmo para jogos em 2D), existe um sistema de coordenadas separado para o jogo, que é independente da resolução, geralmente chamado de espaço no mundo. Isso permite que você dimensione para uma resolução arbitrária.
A maneira mais fácil de conseguir isso é usar uma câmera 2D, que é essencialmente uma matriz que define a transição do espaço do mundo (suas unidades arbitrárias) para o espaço da tela (os pixels na tela). Isso torna trivial lidar com a matemática.
Dê uma olhada na seção abaixo em Rolagem de câmera XNA 2d - por que usar a transformação de matriz?
Facilita a conversão entre as definições do sistema de coordenadas
Para ir da tela para o espaço mundial, basta usar Vector2.Transform. Isso é comumente usado para obter a localização do mouse no mundo para a seleção de objetos.
Para ir do mundo para o espaço da tela, basta fazer o oposto.
Não há desvantagens em usar uma matriz que não seja um pouco de aprendizado.
fonte
Outra opção seria: Em cada evento de movimento do mouse de entrada, mova o cursor do mouse no jogo pelo número de pixels do jogo correspondente ao número de pixels no evento do mouse. Isso ocorre naturalmente em jogos 3D que bloqueiam o ponteiro real do mouse no centro e giram a direção da mira em uma quantidade correspondente ao movimento do mouse de entrada, mas você pode fazer o mesmo movendo um sprite representando o cursor do mouse no jogo.
Obviamente, você deve ignorar qualquer evento de movimento do mouse causado por deformar o objeto para o centro, e se o seu jogo apresentar algum atraso de entrada, a falta de resposta do cursor será o aspecto mais perturbador e perceptível.
Parcialmente, qual solução você usa depende da importância da posição do mouse na jogabilidade. Se este é um RTS e o jogador está simplesmente clicando para selecionar as unidades, você provavelmente pode simplesmente optar pelo que for mais fácil para o seu A ou B. Se é um jogo de tiro de cima para baixo e o mouse controla diretamente os movimentos do personagem, você provavelmente desejará uma solução mais profunda que limite a quantidade de variabilidade na maneira como o personagem pode se mover com base não apenas na resolução, mas também em movimentos do mouse Rapidez. Se o mouse controlar a direção da segmentação, você desejará uma solução diferente etc.
fonte
A resposta do ClassicThunder está correta, mas eu gostaria de fornecer um exemplo de um meio alternativo / mais simples de obter o efeito desejado. Esta é uma solução mais simples para prototipagem rápida, casos em que você não tem acesso a uma biblioteca com todos os recursos ou casos em que você não tem acesso a uma GPU (por exemplo, em sistemas embarcados).
Para executar o referido mapeamento, você pode usar a seguinte função (suponha que ela seja definida na classe estática
Helper
):(Você não especificou um idioma, mas vejo que você tem algum conhecimento de C #, então meu exemplo está em C #.)
Você pode usar esta função da seguinte maneira:
Onde
camera.Bounds
está um retângulo representando a área do mundo que a câmera pode ver (ou seja, a área sendo projetada na tela).Se você tiver uma classe
Vector
ouPoint
, poderá simplificar ainda mais esse processo criando um equivalente em 2D da função de mapa, assim:O que tornaria seu código de mapeamento um liner simples:
fonte
Opção (C): altere a resolução da tela para 800x600.
Mesmo se você não fizer isso, considere isso como um experimento mental. Nesse caso, é de responsabilidade do monitor redimensionar os gráficos para ajustá-los ao tamanho físico e, em seguida, de responsabilidade do sistema operacional fornecer eventos de ponteiro com uma resolução de 800x600.
Eu acho que tudo depende se seus gráficos são bitmap ou vetor. Se eles são bitmap e você está renderizando para um buffer de 800x600, sim, é muito mais fácil remapear o mouse no espaço da tela e ignorar a resolução real da tela. No entanto, a grande desvantagem disso é que o upscaling pode parecer feio, especialmente se você estiver criando gráficos em estilo "8 bits".
fonte