Difference between revisions of "Drawing Shapes"
Line 1: | Line 1: | ||
− | + | 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(); | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
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 18: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:
Contents
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.