Rendering Rectangles
Go to the
guide project to see the source code for a fully working example of this guide.This guide will show you only some steps relative to the guide project.
It will only show you the most essential information related to rendering rectangles.
The guide project uses most of the concepts discussed in the previous guides.
Rendering primitive shapes is a fundamental part of game development. Shapes can be used to create custom UI elements for guides, tutorials, and even debug drawing.
What is debug drawing, you ask?
Debug drawing renders shapes to the screen to help you debug your game. For example, you could draw a rectangle for sprites bounding box to help you see where the sprite is on the screen, which can help with debugging issues with collision detection.
In this guide, you will learn how to render rectangles to the screen using Velaptor.
The rectangle has different attributes you can set to customize how the rectangle will look. These attributes range from position, size, color, gradients, and even the radius of the corners.
Let's render some rectangles!
Creating & Rendering Rectangles
Creating a rectangle is just as easy as creating any C# object. The type to use when creating a rectangle is
RectShape
. The RectShape
type is a record struct
. Using a struct
keeps things performant and lightweight.
Creating Empty Rectangle
Here is an example of creating a rectangle.
var rect = new RectShape();
The code above will create a rectangle with all attributes set to default values. If you were to render this, you would not see anything. The reason for this would be that we did not set the size of the rectangle.
Let's give the rectangle a size by setting the Width
and Height
properties.
var rect = new RectShape();
rect.Width = 100;
rect.Height = 100;
Rendering The Rectangle
To render the rectangle, we must create an IShapeRenderer
renderer.
public Game()
{
// If you are rendering from a `Game` class, make sure you have a batcher
this.batcher = RendererFactory.CreateBatcher();
this.shapeRenderer = RendererFactory.CreateShapeRenderer();
}
Now that we have the renderer, we can render the rectangle to the screen.
Add the code below to an OnDraw()
lifecycle method in your Game
or scene class.
protected void OnDraw(FrameTime frameTime)
{
IBatcher.Begin();
this.shapeRenderer.Render(rect);
IBatcher.End();
}
You should end up with a rectangle that looks like the image below.
Rectangle Color
Setting the color of the rectangle involves setting the 'Color' property. This uses the System.Drawing.Color
struct that is built
right into dotnet.
var rect = new RectShape();
rect.Color = Color.RoyalBlue;
This should give you a rectangle that looks like the image below.
Rectangle Position
Dealing with the position of the rectangle is straightforward. You can set the position of the rectangle by using the following properties:
Position
Top
Bottom
Left
Right
Changing the values of the properties above will affect the other property values. For example, let's say your rectangle was at the position of (10, 20) and the size was (100, 200).
If you were to move the rectangle to the right by 30 pixels to using the Left
property, then
the value of the Right
property would be 130.
The result is that it makes rectangle positioning easy to work with. Your code will also be more readable and maintainable because you can use the property that makes the most sense for the situation and the rest of your code.
Check out the code below:
var rect = new RectShape();
rect.Width = 10;
rect.Height = 20;
rect.Position = new Vector2(100, 200);
/* Starting Positions:
* Left: 95
* Right: 105
* Top: 190
* Bottom: 210
*/
rect.Left += 2;
/* Positions After Moving Left:
* Left: 97
* Right: 107
* Top: 190
* Bottom: 210
*/
rect.Top += 2;
/* Positions After Moving Down:
* Left: 95
* Right: 105
* Top: 192
* Bottom: 212
*/
rect.Width += 10;
/* Positions After Increasing Width:
* Left: 92
* Right: 112
* Top: 192
* Bottom: 212
*/
rect.Height += 20;
/* Positions After Increasing Width:
* Left: 92
* Right: 112
* Top: 182
* Bottom: 222
*/
The Position
of a RectShape
is relative to the center of the rectangle.
Not the top left corner.
Did you notice that the Width
and Height
properties changed the values of the Left
, Right
, Top
, and Bottom
properties?
Since the position of the rectangle is relative to the center of the rectangle, changing the value of the Width
and Height
of the
rectangle will affect the position of the sides of the rectangle.
Solid & Empty Rectangles
You can render rectangles as solid or empty by setting the IsSolid
property to true
or false
.
Here is an example of how to create a solid rectangle:
var rect = new RectShape(); // My default is solid
rect.IsSolid = false; // I am not solid
rect.IsSolid = true; // I am solid again
Border Thickness
When it comes to the border thickness, it is only visible when the rectangle is not solid.
The border thickness is set using the BorderThickness
property and is of type float
.
Refer to the code below to see how to set the border thickness.
var rect = new RectShape();
rect.Width = 100;
rect.Height = 100;
rect.IsSolid = false;
rect.BorderThickness = 25;
Using the settings above, this is what your rectangle would look like.
Corner Radius
You can use the CornerRadius
property to control the radius of the rectangle's corners.
This property is of type CornerRadius
, which is a read-only record struct
.
Different Values Per Corner
Create a corner radius with different values for each corner.
var rect = new RectShape();
rect.CornerRadius = new CornerRadius(10, 20, 30, 40);
If the width and height of the rectangle were 80, the result would be like the image below.
All Corners The Same
If you want all radius values to be the same, use the code below.
var rect = new RectShape();
rect.CornerRadius = new CornerRadius(25);
If the width and height of the rectangle was 100, the result would be like the image below.
One Corner At A Time
What if you wanted to change only one of the corners and keep the rest the same?
You can reduce code using the following static
methods on the CornerRadius
struct.
var rect = new RectShape();
rect.CornerRadius = new CornerRadius(200);
rect.CornerRadius = CornerRadius.SetTopLeft(rect.CornerRadius, 10);
rect.CornerRadius = CornerRadius.SetTopRight(rect.CornerRadius, 20);
rect.CornerRadius = CornerRadius.SetBottomRight(rect.CornerRadius, 30);
rect.CornerRadius = CornerRadius.SetBottomLeft(rect.CornerRadius, 40);
Empty Radius
If you want to empty the CornerRaduis
or check if the CornerRaduis
is empty.
var rect = new RectShape();
rect.CornerRadius = new CornerRadius(100);
var isEmpty = rect.CornerRadius.IsEmpty; // False
// NOTE: The 'Empty' method does not empty the current instance. It just creates a new empty instance.
rect.CornerRadius = CornerRadius.Empty();
isEmpty = rect.CornerRadius.IsEmpty; // True
Radius Limits
One thing to note is that there are internal limits to the radius values, which are as follows:
- The minimum value is 0. Any values below 0 will be set to 0.
- The maximum value is always limited to half of the smallest width or height of the rectangle that the radius is affecting.
Using values larger than the smallest half-width or height or values smaller than 0 is okay.
The rectangle will be rendered at the minimum or maximum value. This is all taken care of for you.
Let's give a quick example. If the rectangle's width is 100 and the height is 200. The maximum value for the radius will be 50.
If you want to update the radius values to scale proportionally as the width or height of the rectangle changes, you have to implement this on your own.
Color Gradients
You can apply color gradients to the rectangle, which can come in two types.
Apply the gradient type by setting the GradientType
property to either GradientType.Horizontal
or GradientType.Vertical
.
These gradients will transition from one color to another using the GradientStart
and GradientStop
properties.
The code below shows you how you could have a horizontal color gradient that would transition from
Color.MediumSeaGreen to Color.MediumPurple,
and a vertical color gradient that would transition from Color.Teal to Color.DarkOrange.
var hGradRect = new RectShape();
// Horizontal gradient rectangle
hGradRect.GradientType = GradientType.Horizontal;
hGradRect.GradientStart = Color.MediumSeaGreen;
hGradRect.GradientStop = Color.MediumPurple;
// Vertical gradient rectangle
var vGradRect = new RectShape();
vGradRect.GradientType = GradientType.Vertical;
vGradRect.GradientStart = Color.Teal;
vGradRect.GradientStop = Color.DarkOrange;
This would end with the result shown below.
Even if you have the GradientStart
and GradientStop
properties set, if the GradientType
is set to GradientType.None
,
the gradient will not be rendered, and the rectangle will be rendered using the Color
property.
Vector Containment
You can quickly check if the rectangle contains a Vector2
in 2D space. Checking if a RectShape contains a Vector2 is done using the Contains()
method.
var rect = new RectShape();
rect.Position = new Vector2(50, 50);
rect.Width = 100;
rect.Height = 100;
var vector = new Vector2(10, 10);
var isNotContained = rect.Contains(vector); // False
vector = new Vector2(60, 60);
var isContained = rect.Contains(vector); // True