Cantos arredondados no XNA?

10

Existe alguma maneira de fazer cantos arredondados em um retângulo renderizado no XNA por meio de primitivas (tiras de linha)? Quero tornar minha interface do usuário um pouco mais sofisticada do que já é, e gostaria que o código fosse flexível, sem muitas texturas envolvidas.

Mathias Lykkegaard Lorenzen
fonte
Basicamente: use uma textura para a linha, uma textura para as extremidades redondas da linha. Gire e dimensione sprites que usem essas duas texturas adequadamente.
precisa saber é o seguinte

Respostas:

8

Você pode renderizar sua primitiva e criar um sombreador que possa criar esses cantos arredondados.
Aqui está um shader de pixel simples no pseudocódigo que pode desenhar um quadrado arredondado:

xDist = abs(x-0.5)
yDist = abs(y-0.5)
xD = xDist*xDist*4
yD = yDist*yDist*4
alpha = floor((1-xD)*(1-yD)*5)

Resultado deste sombreador de pixel:

insira a descrição da imagem aqui

Se você usa shaders, é possível criar uma interface realmente sofisticada, mesmo uma animada.

Para mim, ótimo protótipo de pixel shaders simples é o programa EvalDraw

Piotrek
fonte
5

Outra maneira de fazer isso é usar um 'alongamento de botão' (também chamado de 'alongamento de caixa' ou 'nove remendos'). Essencialmente, você cria uma imagem composta de 9 partes:

Recurso de botão

Para desenhar esse botão em qualquer tamanho, você desenha cada peça (de cima para baixo, da esquerda para a direita):

  1. Desenhe sem escala na parte superior esquerda do retângulo de destino.
  2. Desenhe dimensionado horizontalmente (com width - ((1) + (2)).Width) na parte superior do retângulo de destino, com o deslocamento esquerdo pela largura de (1).
  3. Desenhe sem escala no canto superior direito do retângulo de destino.
  4. Desenhe dimensionado verticalmente (com height - ((1) + (2)).Height) à esquerda do retângulo de destino, com o deslocamento superior pela altura de (1).
  5. Desenhar dimensionado nas duas direções (com a largura de (2) e altura de (4)), compensado pela largura e altura de (1).
  6. Desenhe dimensionado verticalmente (mesma altura que (4)) no retângulo direito do destino, compensado pela altura de (1).
  7. Desenhe sem escala na parte inferior esquerda do retângulo de destino.
  8. Desenhe dimensionado horizontalmente (mesma altura que (2)) na parte inferior do retângulo de destino, compensado pela largura de (1).
  9. Desenhe sem escala no canto inferior direito do retângulo de destino.

Se você olhar para o botão, verá que não importa se (2), (5) e (7) são dimensionados horizontalmente (porque é essencialmente uma linha reta); da mesma maneira (4), (5) e (6) podem ser dimensionados verticalmente sem afetar a qualidade da imagem.

Jonathan Dickinson
fonte
Sim, isso não responde diretamente à pergunta - mas alguém ainda pode achar útil.
Jonathan Dickinson
4
Ele é chamado de nove correções e, na verdade, é muito mais flexível (e mais barato!) Do que usar um shader, pois você pode fazer com que pareça da maneira que desejar com uma textura. Você pode colocar todas as suas imagens de widget em um único atlas de textura. A maioria das GUIs faz dessa maneira.
Elisée
0

Aqui está o código para a abordagem "nove patches":

public static class SpriteBatchExtensions
{
    public static void DrawRoundedRect(this SpriteBatch spriteBatch, Rectangle destinationRectangle, 
        Texture2D texture, int border, Color color)
    {
        // Top left
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location, new Point(border)), 
            new Rectangle(0, 0, border, border), 
            color);

        // Top
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(border, 0), 
                new Point(destinationRectangle.Width - border * 2, border)), 
            new Rectangle(border, 0, texture.Width - border * 2, border), 
            color);

        // Top right
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(destinationRectangle.Width - border, 0), new Point(border)), 
            new Rectangle(texture.Width - border, 0, border, border), 
            color);

        // Middle left
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(0, border), new Point(border, destinationRectangle.Height - border * 2)), 
            new Rectangle(0, border, border, texture.Height - border * 2), 
            color);

        // Middle
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(border), destinationRectangle.Size - new Point(border * 2)), 
            new Rectangle(border, border, texture.Width - border * 2, texture.Height - border * 2), 
            color);

        // Middle right
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(destinationRectangle.Width - border, border), 
                new Point(border, destinationRectangle.Height - border * 2)), 
            new Rectangle(texture.Width - border, border, border, texture.Height - border * 2), 
            color);

        // Bottom left
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(0, destinationRectangle.Height - border), new Point(border)), 
            new Rectangle(0, texture.Height - border, border, border), 
            color);

        // Bottom
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + new Point(border, destinationRectangle.Height - border), 
                new Point(destinationRectangle.Width - border * 2, border)), 
            new Rectangle(border, texture.Height - border, texture.Width - border * 2, border), 
            color);

        // Bottom right
        spriteBatch.Draw(
            texture, 
            new Rectangle(destinationRectangle.Location + destinationRectangle.Size - new Point(border), new Point(border)), 
            new Rectangle(texture.Width - border, texture.Height - border, border, border), 
            color);
    }
}

É invocado como:

spriteBatch.DrawRoundedRect(
    dest, // The coordinates of the Rectangle to be drawn
    rectangleTexture, // Texture for the whole rounded rectangle
    16, // Distance from the edges of the texture to the "middle" patch
    Color.OrangeRed);
sdgfsdh
fonte
isso não funciona para mim ... Acabei de receber um retângulo normal. Isto é como eu o useiTexture2D _texture = new Texture2D(GraphicsDevice, 1, 1); _texture.SetData(new Color[] { Color.Blue }); SpriteBatch sb = new SpriteBatch(GraphicsDevice); sb.Begin(); //sb.Draw(_texture, new Rectangle(100, 100, 100, 100), Color.White); sb.DrawRoundedRect(_texture, new Rectangle(100, 100, 100, 100), Color.Pink, 16); sb.End();
Leonardo Seccia
Sua textura é apenas um pixel azul, essa abordagem assume que os cantos arredondados fazem parte da sua textura.
Sdgfsdh
sorry - muito novo para a plataforma ... obrigado por voltar para mim tão rapidamente
Leonardo Seccia