Skip to content

Commit

Permalink
Merge branch 'main' into feature/244-render-line-guide
Browse files Browse the repository at this point in the history
  • Loading branch information
CalvinWilkinson authored May 16, 2024
2 parents 21024e9 + 47424d6 commit 57c3d49
Show file tree
Hide file tree
Showing 46 changed files with 1,881 additions and 6 deletions.
2 changes: 1 addition & 1 deletion docs/guides/guides/rendering-shapes/_category_.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
"type": "generated-index",
"description": "Guides on how to render various primitive shapes."
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Guides coming soon!!",
"position": 9,
"position": 100,
"link": {
"type": "generated-index",
"description": "New guides that are on their way. 😀"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "Rendering Shapes",
"position": 9,
"link": {
"type": "generated-index",
"description": "Guides on how to render various primitive shapes."
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,367 @@
---
sidebar_position: 1
---

import GuideLink from "@site/src/components/GuideLink";
import Link from "@docusaurus/Link";
import ClrText from "@site/src/components/ClrText";

# Rendering Rectangles

:::note Guide Source Code
Go to the <GuideLink projectName="Rectangles" version="v1.0.0-preview.36"/> 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 draws 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!


## <span className="color-step">Creating & Rendering Rectangles</span>

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.

### <span className="color-sub-step">Creating Empty Rectangle</span>

Here is an example of creating a rectangle.

```csharp showLineNumbers
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.

### <span className="color-sub-step">Size & Color</span>

Let's give the rectangle a size and a color.

```csharp showLineNumbers
var rect = new RectShape();
// highlight-add-start
rect.Width = 100;
rect.Height = 100;
// highlight-add-end
```

### <span className="color-sub-step">Rendering The Rectangle</span>

To render the rectangle, we must create an `IShapeRenderer` renderer.

```csharp showLineNumbers
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.

```csharp showLineNumbers
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.

<div className="flex flex-row space-x-10 justify-center items-center app-win">
<div className="mt-7">
![rendered-rect](./images/rendered-rect.png)
</div>
</div>

## <span className="color-step">Rectangle Size</span>

You can set the size of the rectangle using the `Width` and `Height` properties. These properties are of type `float`
for precision.


## <span className="color-step">Rectangle Position</span>

Dealing with the position of the rectangle is straightforward. You can set the position of the rectangle by using the following properties:

1. `Position`
2. `Top`
3. `Bottom`
4. `Left`
5. `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 the right 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:

```csharp showLineNumbers
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
*/
```

:::note NOTE ABOUT POSITIONING
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.


## <span className="color-step">Solid & Empty Rectangles</span>

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:

```csharp showLineNumbers
var rect = new RectShape(); // My default is solid
rect.IsSolid = false; // I am not solid
rect.IsSolid = true; // I am solid again
```

## <span className="color-step">Border Thickness</span>

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.

```csharp showLineNumbers
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.

<div className="flex flex-row space-x-10 justify-center items-center app-win">
<div className="mt-7">
![border-thickness](./images/border-thickness.png)
</div>
</div>


## <span className="color-step">Corner Radius</span>

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`.

### <span className="color-sub-step">Different Values Per Corner</span>

Create a corner radius with different values for each corner.

```csharp showLineNumbers
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.

<div className="flex flex-row space-x-10 justify-center items-center app-win h-80">
![radius-sample](./images/render-rect-radius-sample.png)
</div>

### <span className="color-sub-step">All Corners The Same</span>

If you want all radius values to be the same, use the code below.

```csharp showLineNumbers
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.

<div className="flex flex-row space-x-10 justify-center items-center app-win">
<div className="mt-7">
![all-corners-same](./images/all-corners-same.png)
</div>
</div>

### <span className="color-sub-step">One Corner At A Time</span>

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.

```csharp showLineNumbers
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);
```

### <span className="color-sub-step">Empty Radius</span>

If you want to empty the `CornerRaduis` or check if the `CornerRaduis` is empty.

```csharp showLineNumbers
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
```

### <span className="color-sub-step">Radius Limits</span>

One thing to note is that there are internal limits to the radius values, which are as follows:

1. The minimum value is **0**. Any values below **0** will be set to **0**.
2. The maximum value is always limited to half of the smallest width or height of the rectangle that the radius is affecting.

:::info VALUES LARGER THEN THE maximum
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.


## <span className="color-step">Color Gradients</span>

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
<ClrText text="Color.MediumSeaGreen" foreColor="MediumSeaGreen"/> to <ClrText text="Color.MediumPurple" foreColor="MediumPurple"/>,
and a vertical color gradient that would transition from <ClrText text="Color.Teal" foreColor="Teal"/> to <ClrText text="Color.DarkOrange" foreColor="DarkOrange"/>.

```csharp showLineNumbers
var hGradRect = new RectShape();
// Horizontal gradient rectangle
hGradRect.GradientType = GradientType.Horizontal;
hGradRect.GradientStart = Color.RoyalBlue;
hGradRect.GradientStop = Color.MediumPurple;

// Vertical gradient rectangle
var vGradRect = new RectShape();
vGradRect.GradientType = GradientType.Vertical;
vGradRect.GradientStart = Color.RoyalBlue;
vGradRect.GradientStop = Color.DarkOrange;
```

This would end with the result shown below.

<div className="flex flex-row space-x-10 justify-center items-center app-win mb-10">
<div className="mt-7">
![horizontal-gradient](./images/horizontal-gradient.png)
![vertical-gradient](./images/vertical-gradient.png)
</div>
</div>

:::note GRADIENTS WHEN SET TO NONE
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.
:::

## <span className="color-step">Vector Containment</span>

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.

```csharp showLineNumbers
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
```
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Guides coming soon!!",
"position": 9,
"position": 100,
"link": {
"type": "generated-index",
"description": "New guides that are on their way. 😀"
Expand Down
Loading

0 comments on commit 57c3d49

Please sign in to comment.