Difference between revisions of "Drawing Shapes"

From TRCCompSci - AQA Computer Science
Jump to: navigation, search
Line 1: Line 1:
=Primitives2d=
+
Believe it or not, MonoGame doesn't include any methods for drawing shapes. But you can still use one of many techniques to draw shapes:
  
 +
=Install a Library - Primitives2d=
 
https://bitbucket.org/C3/2d-xna-primitives/wiki/Home
 
https://bitbucket.org/C3/2d-xna-primitives/wiki/Home
  
 
=Using Textures=
 
=Using Textures=
 +
We can use a texture to draw each point of the shape, the texture is generated using 1 x 1 pixels:
 +
 
==Filled Rectangle==
 
==Filled Rectangle==
 
<syntaxhighlight lang=c#>
 
<syntaxhighlight lang=c#>
Line 34: Line 37:
 
spriteBatch.End();  
 
spriteBatch.End();  
  
/// <summary>
 
/// Will draw a border (hollow rectangle) of the given 'thicknessOfBorder' (in pixels)
 
/// of the specified color.
 
/// </summary>
 
/// <param name="rectangleToDraw"></param>
 
/// <param name="thicknessOfBorder"></param>
 
 
private void DrawBorder(Rectangle rectangleToDraw, int thicknessOfBorder, Color borderColor)  
 
private void DrawBorder(Rectangle rectangleToDraw, int thicknessOfBorder, Color borderColor)  
 
{  
 
{  
Line 52: Line 49:
 
rectangleToDraw.Y,  
 
rectangleToDraw.Y,  
 
thicknessOfBorder,  
 
thicknessOfBorder,  
rectangleToDraw.Height), borderColor);  
+
rectangleToDraw.Height), borderColor);
 +
 
// Draw bottom line  
 
// Draw bottom line  
 
spriteBatch.Draw(pixel, new Rectangle(rectangleToDraw.X,  
 
spriteBatch.Draw(pixel, new Rectangle(rectangleToDraw.X,  
Line 60: Line 58:
 
}  
 
}  
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
=Adding new methods=
 +
You need to have a working MonoGame project, so from the project tab choose new class. Give the class a name and copy the code below (remember to keep the same namespace as your project):
 +
 +
<syntaxhighlight lang=c#>
 +
using System;
 +
using Microsoft.Xna.Framework;
 +
using Microsoft.Xna.Framework.Graphics;
 +
 +
namespace DrawingShapes
 +
{
 +
    public static class DrawShapes
 +
    {
 +
        private static Texture2D _blankTexture;
 +
 +
        public static void LoadContent(GraphicsDevice graphicsDevice)
 +
        {
 +
            _blankTexture = new Texture2D(graphicsDevice, 1, 1, false, SurfaceFormat.Color);
 +
            _blankTexture.SetData(new[] { Color.White });
 +
        }
 +
 +
        public static void LoadContent(Texture2D blankTexture)
 +
        {
 +
            _blankTexture = blankTexture;
 +
        }
 +
 +
        public static void DrawLineSegment(this SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, int lineWidth)
 +
        {
 +
 +
            float angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
 +
            float length = Vector2.Distance(point1, point2);
 +
 +
            spriteBatch.Draw(_blankTexture, point1, null, color,
 +
                      angle, Vector2.Zero, new Vector2(length, lineWidth),
 +
                      SpriteEffects.None, 0);
 +
        }
 +
 +
        public static void DrawPolygon(this SpriteBatch spriteBatch, Vector2[] vertex, int count, Color color, int lineWidth)
 +
        {
 +
            if (count > 0)
 +
            {
 +
                for (int i = 0; i < count - 1; i++)
 +
                {
 +
                    DrawLineSegment(spriteBatch, vertex[i], vertex[i + 1], color, lineWidth);
 +
                }
 +
                DrawLineSegment(spriteBatch, vertex[count - 1], vertex[0], color, lineWidth);
 +
            }
 +
        }
 +
 +
        public static void DrawRectangle(this SpriteBatch spriteBatch, Rectangle rectangle, Color color, int lineWidth)
 +
        {
 +
            Vector2[] vertex = new Vector2[4];
 +
            vertex[0] = new Vector2(rectangle.Left, rectangle.Top);
 +
            vertex[1] = new Vector2(rectangle.Right, rectangle.Top);
 +
            vertex[2] = new Vector2(rectangle.Right, rectangle.Bottom);
 +
            vertex[3] = new Vector2(rectangle.Left, rectangle.Bottom);
 +
 +
            DrawPolygon(spriteBatch, vertex, 4, color, lineWidth);
 +
        }
 +
 +
        public static void DrawCircle(this SpriteBatch spritbatch, Vector2 center, float radius, Color color, int lineWidth, int segments = 16)
 +
        {
 +
 +
            Vector2[] vertex = new Vector2[segments];
 +
 +
            double increment = Math.PI * 2.0 / segments;
 +
            double theta = 0.0;
 +
 +
            for (int i = 0; i < segments; i++)
 +
            {
 +
                vertex[i] = center + radius * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));
 +
                theta += increment;
 +
            }
 +
 +
            DrawPolygon(spritbatch, vertex, segments, color, lineWidth);
 +
        }
 +
    }
 +
}
 +
</syntaxhighlight>
 +
 +
Now in your Game1.cs, you need to add the code below into the Initialize method:
 +
 +
<syntaxhighlight lang=c#>
 +
DrawShapes.LoadContent(GraphicsDevice);
 +
</syntaxhighlight>
 +
 +
Now in the Draw method you can use the methods to draw a shape, for example:
 +
 +
<syntaxhighlight lang=c#>
 +
spriteBatch.Begin();
 +
spriteBatch.DrawRectangle(new Rectangle(0, 0, 200, 200), Color.White, 5);
 +
spriteBatch.End();
 +
</syntaxhighlight>
 +
 +
Remember DrawRectangle, DrawPolygon, DrawCircle, and DrawLineSegment methods can be used to draw the appropriate shapes.

Revision as of 19:49, 31 July 2018

Believe it or not, MonoGame doesn't include any methods for drawing shapes. But you can still use one of many techniques to draw shapes:

Install a Library - Primitives2d

https://bitbucket.org/C3/2d-xna-primitives/wiki/Home

Using Textures

We can use a texture to draw each point of the shape, the texture is generated using 1 x 1 pixels:

Filled Rectangle

// Make a 1x1 texture named pixel.  
Texture2D pixel = new Texture2D(graphicsDeviceReferenceHere, 1, 1);  
 
// Create a 1D array of color data to fill the pixel texture with.  
Color[] colorData = {  
                        Color.White,   
                    };  
 
// Set the texture data with our color information.  
pixel.SetData<Color>(colorData);  
 
// Draw a fancy purple rectangle.  
spriteBatch.Draw(pixel, new Rectangle(0, 0, 300, 300), Color.Purple);

Outline Only

// In LoadContent() 
Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1, false, SurfaceFormat.Color); 
pixel.SetData(new[] { Color.White }); // so that we can draw whatever color we want on top of it 

// In Draw() 
spriteBatch.Begin(); 
Rectangle titleSafeRectangle = GraphicsDevice.Viewport.TitleSafeArea; 
DrawBorder(titleSafeRectangle, 5, Color.Red); // can draw any rectangle here 
spriteBatch.End(); 

private void DrawBorder(Rectangle rectangleToDraw, int thicknessOfBorder, Color borderColor) 
{ 
// Draw top line 
spriteBatch.Draw(_pixel, new Rectangle(rectangleToDraw.X, rectangleToDraw.Y, rectangleToDraw.Width, thicknessOfBorder), borderColor); 

// Draw left line 
spriteBatch.Draw(pixel, new Rectangle(rectangleToDraw.X, rectangleToDraw.Y, thicknessOfBorder, rectangleToDraw.Height), borderColor); 

// Draw right line 
spriteBatch.Draw(pixel, new Rectangle((rectangleToDraw.X + rectangleToDraw.Width - thicknessOfBorder), 
rectangleToDraw.Y, 
thicknessOfBorder, 
rectangleToDraw.Height), borderColor);
 
// Draw bottom line 
spriteBatch.Draw(pixel, new Rectangle(rectangleToDraw.X, 
rectangleToDraw.Y + rectangleToDraw.Height - thicknessOfBorder, 
rectangleToDraw.Width, 
thicknessOfBorder), borderColor); 
}

Adding new methods

You need to have a working MonoGame project, so from the project tab choose new class. Give the class a name and copy the code below (remember to keep the same namespace as your project):

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

namespace DrawingShapes
{
    public static class DrawShapes
    {
        private static Texture2D _blankTexture;

        public static void LoadContent(GraphicsDevice graphicsDevice)
        {
            _blankTexture = new Texture2D(graphicsDevice, 1, 1, false, SurfaceFormat.Color);
            _blankTexture.SetData(new[] { Color.White });
        }

        public static void LoadContent(Texture2D blankTexture)
        {
            _blankTexture = blankTexture;
        }

        public static void DrawLineSegment(this SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, int lineWidth)
        {

            float angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
            float length = Vector2.Distance(point1, point2);

            spriteBatch.Draw(_blankTexture, point1, null, color,
                       angle, Vector2.Zero, new Vector2(length, lineWidth),
                       SpriteEffects.None, 0);
        }

        public static void DrawPolygon(this SpriteBatch spriteBatch, Vector2[] vertex, int count, Color color, int lineWidth)
        {
            if (count > 0)
            {
                for (int i = 0; i < count - 1; i++)
                {
                    DrawLineSegment(spriteBatch, vertex[i], vertex[i + 1], color, lineWidth);
                }
                DrawLineSegment(spriteBatch, vertex[count - 1], vertex[0], color, lineWidth);
            }
        }

        public static void DrawRectangle(this SpriteBatch spriteBatch, Rectangle rectangle, Color color, int lineWidth)
        {
            Vector2[] vertex = new Vector2[4];
            vertex[0] = new Vector2(rectangle.Left, rectangle.Top);
            vertex[1] = new Vector2(rectangle.Right, rectangle.Top);
            vertex[2] = new Vector2(rectangle.Right, rectangle.Bottom);
            vertex[3] = new Vector2(rectangle.Left, rectangle.Bottom);

            DrawPolygon(spriteBatch, vertex, 4, color, lineWidth);
        }

        public static void DrawCircle(this SpriteBatch spritbatch, Vector2 center, float radius, Color color, int lineWidth, int segments = 16)
        {

            Vector2[] vertex = new Vector2[segments];

            double increment = Math.PI * 2.0 / segments;
            double theta = 0.0;

            for (int i = 0; i < segments; i++)
            {
                vertex[i] = center + radius * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));
                theta += increment;
            }

            DrawPolygon(spritbatch, vertex, segments, color, lineWidth);
        }
    }
}

Now in your Game1.cs, you need to add the code below into the Initialize method:

DrawShapes.LoadContent(GraphicsDevice);

Now in the Draw method you can use the methods to draw a shape, for example:

spriteBatch.Begin();
spriteBatch.DrawRectangle(new Rectangle(0, 0, 200, 200), Color.White, 5);
spriteBatch.End();

Remember DrawRectangle, DrawPolygon, DrawCircle, and DrawLineSegment methods can be used to draw the appropriate shapes.