0

I have a Shape class that has 4 points (Vector2). This way, the shape can be manipulated for whatever purpose. I'm wanting to be able to fill this shape with a color of choice, but am not sure where to begin. I found references to something called "VertexPositionColorTexture" but soon realized it was for 3D space only. My program is 2D only and I am at a loss.

If someone has suggestions to get to where I am trying, I will appreciate the help.

public class CShape
{
    public Vector2 PointA { get; set; }
    public Vector2 PointB { get; set; }
    public Vector2 PointC { get; set; }
    public Vector2 PointD { get; set; }

    public Color Color { get; set; }

    public float GetWidth()
    {
        Vector2 Left, Right;
        Left = PointA;
        if (PointB.X < Left.X) { Left = PointB; }
        if (PointC.X < Left.X) { Left = PointC; }
        if (PointD.X < Left.X) { Left = PointD; }

        Right = PointA;
        if (PointB.X > Right.X) { Right = PointB; }
        if (PointC.X > Right.X) { Right = PointC; }
        if (PointD.X > Right.X) { Right = PointD; }

        return (Left.X - Right.X);
    }

    public float GetHeight()
    {
        Vector2 Top, Bottom;
        Top = PointA;
        if (PointB.Y < Top.Y) { Top = PointB; }
        if (PointC.Y < Top.Y) { Top = PointC; }
        if (PointD.Y < Top.Y) { Top = PointD; }

        Bottom = PointA;
        if (PointB.Y > Bottom.Y) { Bottom = PointB; }
        if (PointC.Y > Bottom.Y) { Bottom = PointC; }
        if (PointD.Y > Bottom.Y) { Bottom = PointD; }

        return (Top.Y - Bottom.Y);
    }

    public CShape(Vector2 Location, int Width, int Height, Color Color)
    {
        PointA = Location;
        PointB = new Vector2(PointA.X + Width, PointA.Y);
        PointC = new Vector2(PointA.X, PointA.Y + Height);
        PointD = new Vector2(PointA.X + Width, PointA.Y + Height);
        this.Color = Color;
    }
    public void Move(Vector2 Velocity)
    {
        PointA = new Vector2(PointA.X + Velocity.X, PointA.Y + Velocity.Y);
        PointB = new Vector2(PointB.X + Velocity.X, PointB.Y + Velocity.Y);
        PointC = new Vector2(PointC.X + Velocity.X, PointC.Y + Velocity.Y);
        PointD = new Vector2(PointD.X + Velocity.X, PointD.Y + Velocity.Y);
    }
    public void Draw(SpriteBatch sb)
    {
        sb.Begin();
        SpriteBatchEx.DrawLine(sb, PointA, PointB, Color, 3);
        SpriteBatchEx.DrawLine(sb, PointB, PointD, Color, 3);
        SpriteBatchEx.DrawLine(sb, PointD, PointC, Color, 3);
        SpriteBatchEx.DrawLine(sb, PointC, PointA, Color, 3);
        sb.End();
    }


}
aybe
  • 15,516
  • 9
  • 57
  • 105
John Brooks
  • 69
  • 1
  • 8

2 Answers2

2

A common approach is simply to draw in 3D but using a 2D projection, it's really simple once setup and there are benefits in doing so (TODO find out more on that topic, there are plenty tutorials out there) !

So here's a simple code that draws squares anywhere and you can tint them:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Game1
{
    public class Game1 : Game
    {
        private BasicEffect _basicEffect;
        private GraphicsDeviceManager _graphics;


        public Game1()
        {
            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            _basicEffect = new BasicEffect(GraphicsDevice) {VertexColorEnabled = true};
            base.Initialize();
        }


        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
                Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
            base.Update(gameTime);
        }

        private void DrawSquare(BasicEffect basicEffect, Vector2 position, Vector2 size, Color tint)
        {
            // square made out of 2 triangles
            var colors = new[]
            {
                new VertexPositionColor(new Vector3(-0.5f, -0.5f, 0.0f), Color.White),
                new VertexPositionColor(new Vector3(+0.5f, -0.5f, 0.0f), Color.White),
                new VertexPositionColor(new Vector3(+0.5f, +0.5f, 0.0f), Color.White),
                new VertexPositionColor(new Vector3(-0.5f, -0.5f, 0.0f), Color.White),
                new VertexPositionColor(new Vector3(+0.5f, +0.5f, 0.0f), Color.White),
                new VertexPositionColor(new Vector3(-0.5f, +0.5f, 0.0f), Color.White)
            };

            basicEffect.World = // NOTE: the correct order for matrices is SRT (scale, rotate, translate)
                Matrix.CreateTranslation(0.5f, 0.5f, 0.0f)* // offset by half pixel to get pixel perfect rendering
                Matrix.CreateScale(size.X, size.Y, 1.0f)* // set size
                Matrix.CreateTranslation(position.X, position.Y, 0.0f)* // set position
                Matrix.CreateOrthographicOffCenter // 2d projection
                    (
                        0.0f,
                        GraphicsDevice.Viewport.Width, // NOTE : here not an X-coordinate (i.e. width - 1)
                        GraphicsDevice.Viewport.Height,
                        0.0f,
                        0.0f,
                        1.0f
                    );

            // tint it however you like
            basicEffect.DiffuseColor = tint.ToVector3();

            var passes = _basicEffect.CurrentTechnique.Passes;
            foreach (var pass in passes)
            {
                pass.Apply();
                GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, colors, 0, colors.Length/3);
            }
        }

        /// <summary>
        ///     This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            DrawSquare(_basicEffect, new Vector2(10, 10), new Vector2(100, 100), Color.Red);
            DrawSquare(_basicEffect, new Vector2(200, 200), new Vector2(50, 50), Color.Green);

            base.Draw(gameTime);
        }
    }
}

enter image description here

aybe
  • 15,516
  • 9
  • 57
  • 105
  • Thanks for the awesome reply. How would I get the VertexPositionColors to be directly proportionate to the size of the shape? I've been trying to come up with an algorithm for hours. – John Brooks Aug 28 '16 at 22:00
  • What you have to do is to keep things in a -0.5 to +0.5 range in all axes, you see my rectangle is exactly 1.0 units wide like this http://www.csharphelper.com/platonic_3_1.png . Then you see the world matrix of the basic effect has a scale which does scale it. Because using a scale of 1 when you multiply you get the exact size in pixels ... hope that makes sense ! PS. since you are doing 2d, it does not really matter to set Z components, I've put them all to zero. – aybe Aug 29 '16 at 02:05
  • Of course, the vertex array (or vertex+index buffers) should be cached in the Shape class in the real code. Great example, +1. – Petri Laarne Sep 01 '16 at 17:17
  • Thanks, yes of course, actually I did not optimize because I was more after readability and to not overwhelm OP. – aybe Sep 01 '16 at 17:37
0

You can still use the good'ol xblig sample :

http://xbox.create.msdn.com/en-US/education/catalog/sample/primitives

G.Vernier
  • 369
  • 2
  • 14