Закруглені кути в XNA?


10

Чи є якийсь спосіб зробити закруглені кути на прямокутнику, виведеному в XNA за допомогою примітивів (ліній-смужок)? Я хочу зробити свій інтерфейс трохи більш фантазійним, ніж він є, і я хотів би, щоб код був гнучким, без занадто багато текстур.


В основному: використовуйте одну текстуру для лінії, одну текстуру для круглих кінців лінії. Обертання та масштабування спрайтів, які використовують ці дві текстури належним чином.
Ольховський

Відповіді:


8

Ви можете зробити свій примітив і зробити шейдер, який може створити ці закруглені кути.
Ось простий піксельний шейдер у псевдокоді, який може намалювати округлий квадрат:

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)

Результат цього піксельного шейдера:

введіть тут опис зображення

Якщо ви використовуєте шейдери, ви можете зробити дійсно фантазійний інтерфейс, навіть анімований.

Для мене чудовою для прототипу простих піксельних шейдерів є програма EvalDraw


5

Інший спосіб зробити це - використовувати "розтягування кнопки" (також називається "розтягнення коробки" або "дев'ять патчів"). По суті, ви створюєте зображення, яке складається з 9 частин:

Ресурс кнопки

Щоб намалювати цю кнопку будь-якого розміру, ви намалюєте кожен шматок (зверху вниз, зліва направо):

  1. Намалюйте без накиду у верхньому лівому куті прямокутника призначення.
  2. Намалюйте масштабований горизонтально (з width - ((1) + (2)).Width) у верхній частині цільового прямокутника, зсунувши ліворуч на ширину (1).
  3. Намалюйте без накиду в правому верхньому куті прямокутника призначення.
  4. Намалюйте масштабований вертикально (з height - ((1) + (2)).Height) ліворуч від прямокутника призначення, верхній зсув на висоту (1).
  5. Намалюйте масштабоване в обох напрямках (з шириною (2) та висотою (4)), зміщеною на ширину та висоту (1).
  6. Намалюйте масштабований вертикально (таку ж висоту, як (4)) праворуч прямокутника призначення, зміщений на висоту (1).
  7. У нижньому лівому куті прямокутника призначення намалюйте без накидів.
  8. Намалюйте масштабований горизонтально (та ж висота, що і (2)) у нижній частині цільового прямокутника, зміщену на ширину (1).
  9. Намалюйте без накиду в правому нижньому куті прямокутника призначення.

Якщо ви подивитесь на кнопку, то побачите, що не має значення, якщо (2), (5) і (7) масштабуватись горизонтально (адже це по суті пряма лінія); таким же чином (4), (5) і (6) можна масштабувати вертикально, не впливаючи на якість зображення.


Так, це не відповідає безпосередньо на питання - але хтось все-таки може вважати його корисним.
Джонатан Дікінсон

4
Це називається дев'ять патчем і насправді набагато гнучкіше (і дешевше!), Ніж використання шейдера, оскільки ви можете зробити його схожим на текстуру. Потім ви можете розмістити всі свої віджети в одному атласі текстури. Більшість графічних інтерфейсів роблять це так.
Elisée

0

Ось код для підходу "дев'ять патчів":

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

Він викликається як:

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

це не працює для мене ... я просто отримую звичайний прямокутник. Ось як я його використавTexture2D _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();
Леонардо Секіа

Ваша текстура - це лише один синій піксель. Цей підхід передбачає, що закруглені кути є частиною вашої текстури.
sdgfsdh

вибачте - дуже нова платформа ... спасибі за те, що мені так швидко повернулися
Леонардо Сексія
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.