Подтвердить что ты не робот

Рисовать прямоугольник с помощью XNA

Я работаю над игрой. Я хочу выделить место на экране, когда что-то произойдет.

Я создал класс, чтобы сделать это для меня, и нашел немного кода для рисования прямоугольника:

static private Texture2D CreateRectangle(int width, int height, Color colori)
{
    Texture2D rectangleTexture = new Texture2D(game.GraphicsDevice, width, height, 1, TextureUsage.None,
    SurfaceFormat.Color);// create the rectangle texture, ,but it will have no color! lets fix that
    Color[] color = new Color[width * height];//set the color to the amount of pixels in the textures
    for (int i = 0; i < color.Length; i++)//loop through all the colors setting them to whatever values we want
    {
        color[i] = colori;
    }
    rectangleTexture.SetData(color);//set the color data on the texture
    return rectangleTexture;//return the texture
}

Проблема заключается в том, что приведенный выше код называется каждым обновлением (60 раз в секунду), и он не был написан с оптимизацией. Он должен быть очень быстрым (код выше зависает от игры, которая имеет только код скелета прямо сейчас).

Любые предложения?

Примечание. Любой новый код будет отличным (WireFrame/Fill оба хороши). Я хотел бы указать цвет.

4b9b3361

Ответ 1

демонстрация SafeArea на сайте Клуба разработчиков XNA имеет код, специально предназначенный для этого.

Вам не нужно создавать текстуру каждого кадра, только в LoadContent. Очень урезанная версия кода из этой демонстрации:

public class RectangleOverlay : DrawableGameComponent
{
    SpriteBatch spriteBatch;
    Texture2D dummyTexture;
    Rectangle dummyRectangle;
    Color Colori;

    public RectangleOverlay(Rectangle rect, Color colori, Game game)
        : base(game)
    {
        // Choose a high number, so we will draw on top of other components.
        DrawOrder = 1000;
        dummyRectangle = rect;
        Colori = colori;
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        dummyTexture = new Texture2D(GraphicsDevice, 1, 1);
        dummyTexture.SetData(new Color[] { Color.White });
    }

    public override void Draw(GameTime gameTime)
    {
        spriteBatch.Begin();
        spriteBatch.Draw(dummyTexture, dummyRectangle, Colori);
        spriteBatch.End();
    }
}

Ответ 2

Вот как я это сделал. Это, вероятно, не самое быстрое или лучшее решение, но оно работает.

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Engine
{
    /// <summary>
    /// An extended version of the SpriteBatch class that supports line and
    /// rectangle drawing.
    /// </summary>
    public class ExtendedSpriteBatch : SpriteBatch
    {
        /// <summary>
        /// The texture used when drawing rectangles, lines and other 
        /// primitives. This is a 1x1 white texture created at runtime.
        /// </summary>
        public Texture2D WhiteTexture { get; protected set; }

        public ExtendedSpriteBatch(GraphicsDevice graphicsDevice)
            : base(graphicsDevice)
        {
            this.WhiteTexture = new Texture2D(this.GraphicsDevice, 1, 1);
            this.WhiteTexture.SetData(new Color[] { Color.White });
        }

        /// <summary>
        /// Draw a line between the two supplied points.
        /// </summary>
        /// <param name="start">Starting point.</param>
        /// <param name="end">End point.</param>
        /// <param name="color">The draw color.</param>
        public void DrawLine(Vector2 start, Vector2 end, Color color)
        {
            float length = (end - start).Length();
            float rotation = (float)Math.Atan2(end.Y - start.Y, end.X - start.X);
            this.Draw(this.WhiteTexture, start, null, color, rotation, Vector2.Zero, new Vector2(length, 1), SpriteEffects.None, 0);
        }

        /// <summary>
        /// Draw a rectangle.
        /// </summary>
        /// <param name="rectangle">The rectangle to draw.</param>
        /// <param name="color">The draw color.</param>
        public void DrawRectangle(Rectangle rectangle, Color color)
        {
            this.Draw(this.WhiteTexture, new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, 1), color);
            this.Draw(this.WhiteTexture, new Rectangle(rectangle.Left, rectangle.Bottom, rectangle.Width, 1), color);
            this.Draw(this.WhiteTexture, new Rectangle(rectangle.Left, rectangle.Top, 1, rectangle.Height), color);
            this.Draw(this.WhiteTexture, new Rectangle(rectangle.Right, rectangle.Top, 1, rectangle.Height + 1), color);
        }

        /// <summary>
        /// Fill a rectangle.
        /// </summary>
        /// <param name="rectangle">The rectangle to fill.</param>
        /// <param name="color">The fill color.</param>
        public void FillRectangle(Rectangle rectangle, Color color)
        {
            this.Draw(this.WhiteTexture, rectangle, color);
        }
    }
}

Ответ 3

Это, вероятно, не лучшее решение, но вы можете использовать текстуру размером 1 × 1, растянутую для прямоугольника.