Depois de adicionar velocidade ao meu jogo, sinto que minhas texturas estão tremendo. Eu pensei que eram apenas meus olhos, até que finalmente capturei em uma captura de tela:
O da esquerda é o que renderiza no meu jogo; o da direita é o sprite original, colado. (Esta é uma captura de tela do Photoshop, ampliada em 6x.)
Observe que as bordas estão com alias - parece quase como renderização sub-pixel. De fato, se eu não tivesse forçado meus sprites (que têm posição e velocidade como ints) a desenhar usando valores inteiros, eu juraria que o MonoGame está desenhando com valores de ponto flutuante. Mas não é.
Qual poderia ser a causa dessas coisas parecerem borradas? Isso não acontece sem a velocidade aplicada.
Para ser mais preciso, minha SpriteComponent
turma tem um Vector2 Position
campo. Quando ligo Draw
, uso essencialmente new Vector2((int)Math.Round(this.Position.X), (int)Math.Round(this.Position.Y))
para a posição.
Eu já tinha um bug antes em que objetos estacionários tremiam - isso se deve ao fato de eu usar o Position
vetor direto e não arredondar os valores para ints
. Se eu usar Floor
/ em Ceiling
vez de redondo, o sprite afunda / paira (diferença de um pixel de qualquer maneira), mas ainda fica embaçado.
Respostas:
Bem, isso é constrangedor.
Acontece que eu não estava desenhando usando posições inteiras, mas posições flutuantes. Archy me apontou o caminho certo com seu comentário
@ashes999 did you debug this call and checked this.X, this.Y and this.origin?
Assim que adicionei uma declaração de rastreamento, notei que nada era traçado. Acontece que minha
SpriteComponent
classe usava corretamente valores inteiros, masSpriteSheetComponent
ainda utilizava valores flutuantes do brutoVector2 Position
.Embora eu não tenha tentado filtrar e fixar a textura, suspeitava que essas não eram a alteração correta, porque estava desenhando uma imagem 2D na mesma largura e altura da imagem de origem (sem redimensionamento).
fonte
O XNA usa o DirectX9, que usa o centro do pixel como sua localização. Isso é perceptível ao usar as sobrecargas baseadas em Vector2 da classe draw. Acredito que subtrair (.5, .5) deve resolver seu problema.
Mais informações aqui.
fonte
int, int
os argumentos. Além disso, as coisas parecem perfeitamente bem quando não tenho nenhum objeto em movimento.SpriteComponent
tem umaVector2
posição, que aumenta à medida que flutua, dependendo da velocidade; quando desenho, crio uma novaVector2
com versões inteiras (arredondadas) dos meusposition
X e Y. Esse não é o problema, pois objetos estacionários sem velocidade parecem bem.p += v
duranteUpdate
e renderizo comnew Vector2((int)Math.Round(p.X), (int)Math.Round(p.Y)))
.A renderização não sabe nada sobre sua velocidade; portanto, a posição, tamanho ou qualquer outra coisa que você passe para o SpriteBatch.Draw é diferente ou o erro estava presente antes de você adicionar velocidade. Como você chama SpriteBatch.Draw exatamente?
Você depurou esta chamada e verificou this.X, this.Y e this.origin? O que é this.origin definido como? Basicamente, não há como o resultado da renderização com velocidade ser diferente quando essa chamada do Draw for a mesma.
fonte
O problema é provável que a filtragem de textura esteja ativada. Se você não tiver certeza do que isso significa, considere uma situação em que você tem uma imagem com 2 pixels de largura: o primeiro pixel é preto, o segundo pixel é branco. Se você ampliar esta textura, se a filtragem de textura estiver ativada, verá que ela fica embaçada e que a área entre o pixel preto e branco usa uma cor cinza degradê.
Um exemplo clássico de jogos com e sem filtragem é Super Mario 64, que teve filtragem enquanto Doom não.
Quando você não usa velocidade, é provável que o seu Sprite esteja posicionado de forma que o centro da textura esteja no ponto de amostra em que o XNA (ou qualquer API subjacente que esteja sendo usada) está capturando a cor. Quando você se move com uma velocidade de flutuação, a posição do seu Sprite muda, portanto, o ponto de amostra pode não se alinhar diretamente com o centro de um pixel; portanto, o resultado final é que uma cor que é uma média dos pixels mais próximos está sendo usado para renderizar.
Você pode verificar se a filtragem está ativada simplesmente tornando seu Sprite muito grande na tela. Se estiver embaçado, esse é o problema.
Se você precisa ter uma precisão de pixel perfeita na renderização, convém ter um valor flutuante para a posição armazenada em algum lugar, mas use valores inteiros para a posição do objeto que você está renderizando ... ou, é claro, você pode simplesmente desativar a filtragem se o seu jogo não precisar dele.
Você também pode querer ler isso .
fonte
Draw
. Portanto, não tenho certeza de como poderia ser o caso - mas tentarei renderizar em larga escala e ver se a desativação da filtragem de textura ajudará.Tente definir seu SamplerState como SamplerState.PointClamp na chamada SpriteBatch.Begin.
fonte