Angoli arrotondati in XNA?


10

Esiste un modo per creare angoli arrotondati su un rettangolo reso in XNA tramite primitive (line-strip)? Voglio rendere la mia interfaccia utente un po 'più elaborata di quanto non sia già, e vorrei che il codice fosse flessibile, senza troppe trame coinvolte.


Fondamentalmente: usa una trama per la linea, una trama per le estremità arrotondate della linea. Ruota e ridimensiona gli sprite che usano queste due trame in modo appropriato.
Olhovsky,

Risposte:


8

Puoi rendere la tua primitiva e creare uno shader in grado di creare questi angoli arrotondati.
Ecco un semplice pixel shader in pseudocodice che può disegnare un quadrato arrotondato:

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)

Risultato di questo pixel shader:

inserisci qui la descrizione dell'immagine

Se usi shader, puoi creare un'interfaccia utente davvero fantasiosa, anche animata.

Per me fantastico prototipo di semplici pixel shader è il programma EvalDraw


5

Un altro modo per farlo è quello di usare un "button stretch" (chiamato anche "box stretch" o "nine-patch"). In sostanza, crei un'immagine composta da 9 parti:

Risorsa pulsante

Per disegnare quel bottone di qualsiasi dimensione, disegni ogni pezzo (dall'alto verso il basso, da sinistra a destra):

  1. Disegna senza scala nella parte superiore sinistra del rettangolo di destinazione.
  2. Disegna in scala orizzontale (con width - ((1) + (2)).Width) nella parte superiore del rettangolo di destinazione, con l'offset sinistro della larghezza di (1).
  3. Disegna senza scala in alto a destra nel rettangolo di destinazione.
  4. Disegna in scala verticale (con height - ((1) + (2)).Height) a sinistra del rettangolo di destinazione, con l'offset superiore dell'altezza di (1).
  5. Disegna in scala in entrambe le direzioni (con la larghezza di (2) e l'altezza di (4)), sfalsata per la larghezza e l'altezza di (1).
  6. Disegna in scala verticale (stessa altezza di (4)) a destra del rettangolo di destinazione, sfalsato rispetto all'altezza di (1).
  7. Disegna senza scala nella parte inferiore sinistra del rettangolo di destinazione.
  8. Disegna in scala orizzontale (stessa altezza di (2)) nella parte inferiore del rettangolo di destinazione, sfalsato della larghezza di (1).
  9. Disegna senza scala nella parte inferiore destra del rettangolo di destinazione.

Se guardi il pulsante vedrai che non importa se (2), (5) e (7) vengono ridimensionati orizzontalmente (perché è essenzialmente una linea retta); allo stesso modo (4), (5) e (6) possono essere ridimensionati verticalmente senza influire sulla qualità dell'immagine.


Sì, questo non risponde direttamente alla domanda, ma qualcuno potrebbe ancora trovarla utile.
Jonathan Dickinson,

4
Si chiama nove patch ed è in realtà molto più flessibile (ed economico!) Rispetto all'utilizzo di uno shader poiché puoi farlo sembrare come vuoi con una trama. È quindi possibile inserire tutte le immagini del widget in un singolo atlante di trama. La maggior parte delle GUI lo fanno in questo modo.
Elisée,

0

Ecco il codice per l'approccio "nove patch":

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);
    }
}

È invocato come:

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);

questo non funziona per me ... ho solo un rettangolo normale. È così che l'ho usatoTexture2D _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,

La trama è solo un pixel blu, questo approccio presuppone che gli angoli arrotondati facciano parte della trama.
sdgfsdh,

scusate - molto nuovo sulla piattaforma ... grazie per essere tornato da me così in fretta
Leonardo Seccia,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.