# Renderable

{% hint style="warning" %}
Quick Reference can help with simple issues or give you a basic understanding of the methods available, but it can never replace full documentation which is available [here](https://pydraw.graphics/api).
{% endhint %}

## Initialization

We can initialize the default 3 shapes by calling their respective constructors:

```python
rectangle = Rectangle(screen, x, y, width, height)
oval = Oval(screen, x, y, width, height)
triangle = Triangle(screen, x, y, width, height)
```

The constructor has more arguments that are optional:

```python
Renderable(screen, x, y, width, height, color, border, fill, rotation, visible)
```

{% hint style="info" %}
It's crucial to note that all Renderables are rendered from the top-left. So the passed (x, y) for a Rectangle would be its top left corner.
{% endhint %}

## Types

There are a few different Renderables that can be created:

```python
rectangle = Rectangle(screen, x, y, width, height)
oval = Oval(screen, x, y, width, height)
triangle = Triangle(screen, x, y, width, height)

# Note that for Polygon we specify num_sides before (x, y)
polygon = Polygon(screen, num_sides, x, y, width, height)

# We can create an irregular polygon by specifying vertices
irregular = CustomPolygon(screen, vertices, color, border, fill, rotation, visible)
```

{% hint style="info" %}
Although Text is classified as a Renderable, it is not directly resizable and has specific methods unique to Text: [Reference](https://docs.pydraw.graphics/quick-reference/text).
{% endhint %}

## Movement

Moving any Renderable is alike to moving a Location:

```python
renderable.x(new_x)  # Get or set the x-coordinate
renderable.y(new_y)  # Get or set the y-coordinate

renderable.move(dx, dy)  # Move by (dx, dy)
renderable.move((dx, dy))  # Tuple representation of (dx, dy)
renderable.move(dx=100)  # Move the x-coordinate by +100

renderable.moveto(x, y)  # Move to (x, y)
renderable.moveto((x, y))  # Tuple representation of (x, y)
renderable.moveto(y=100)  # Move the y-coordinate to +100
```

We can also make a Renderable move forward at its current heading/angle via:

```python
renderable.forward(distance)  # Move forward at current angle by distance
renderable.backward(distance)  # Move backward at current angle by distance
```

{% hint style="info" %}
Note that these methods utilize the Renderables [rotation](#rotation).
{% endhint %}

## Location

You can also retrieve the Location with:

```python
renderable.location()
```

## Center

You can get the Location of the center of any Renderable:

```python
renderable.center()
```

{% hint style="info" %}
Note: This calculates the center by default (except for CustomPolygons), but you can get the [*centroid*](https://en.wikipedia.org/wiki/Centroid) of the shape by setting `centroid=True` in the method arguments.
{% endhint %}

You can also use this method to move the Renderable to place its center in a certain location:

```python
renderable.center(x, y)
renderable.center(location)
renderable.center((x, y))
```

## Rotation

You can get or modify the rotation of a Renderable like so:

```python
renderable.rotation()  # Get the current angle
renderable.rotation(angle)  # Set a new angle of rotation

renderable.rotate(angle_change)  # Change the angle by a specified argument
```

You can also just make a Renderable look at a Location or Renderable:

```python
renderable.lookat(other)  # Look at another Renderable
renderable.lookat(location)  # Look at a Location
```

You can also check the angle of the Renderable against any Object or Location:

```python
renderable.angleto(obj)
renderable.angleto(location)
renderable.angleto((x, y))
```

## Size

You can retrieve or modify the size of the Renderable like so:

```python
renderable.width()  # Get the current width
renderable.width(width)  # Modify the width
renderable.width(width, ratio=True)  # Maintain the ratio of the Renderable

erable.height()  # Get the current height
renderable.height(height)  # Modify the height
renderable.height(height, ratio=True)  # Maintain the ratio of the Renderable
```

{% hint style="info" %}
Note: Width and Height refer to the width and height of the original shape, regardless of rotation.
{% endhint %}

## Color

All Renderables have a default Color of black; the color can be retrieved or set via:

```python
renderable.color()  # Get the color
renderable.color(color)  # Set a new color
```

## Border and Fill

Renderables also have an optional border that is set to Color.NONE by default. You can set or retrieve the border like so:

```python
renderable.border()  # Get the border's color. If none is set, returns Color.NONE
renderable.border(color)  # Set a new color for the border
renderable.border(color, width=5)  # Set a new color and a borderwidth
renderable.border(color, fill=False)  # Set a new color and disable the fill
```

You can get or set the `border_width` seperately with:

```python
renderable.border_width()  # returns border width
renderable.border_width(5)  # sets to 5
```

Fill exists (as seen above) to create Framed Renderables with ease. Fill can be toggled without calling the `border()` method like so:

```python
renderable.fill(False)  # Change the fill to False.
```

## Visibility

You can make any Object in pyDraw invisible with:

```python
renderable.visible(False)  # Make the Object invisible
```

## Ordering

You can move objects to the front or back of layers with:

```python
renderable.front()  # Move to the front
renderable.back()  # Move to the back
```

## Distance

You can get the distance between a Renderable and another Renderable, or Location like so:

```python
renderable.distance(other)  # Pass in another renderable
renderable.distance(location)  # Pass in a Location
```

## Transform and Cloning

A transform is a data structure that represents the width, height, and rotation. You can copy the transform of a Renderable and set it to another transform:

```python
renderable.transform()  # Retrieve the transform
renderable.transform(transform)  # Set a new transform
```

{% hint style="warning" %}
You should only set the transform to other transforms retrieved from Renderables, however, it is possible to create one yourself:

```python
transform = (width, height, angle);
```

{% endhint %}

You can also clone a Renderable by calling the aptly named:

```python
renderable.clone()
```

## Vertices

For those who want to perform more advanced mathematics with their shapes, you can retrieve a (copy) list of vertices:

```python
renderable.vertices()
```

{% hint style="info" %}
Vertices usually will begin at the top left and work clockwise.
{% endhint %}

## Bounds

You can get the location and dimensions of a bounding box calculated by pyDraw around any Renderable:

```python
renderable.bounds()  # returns (Location, width, height)
```

## Contains and Overlaps

You can check if a point is contained in any Renderable like so:

```python
renderable.contains(location)  # Pass in a normal location
renderable.contains(x, y)  # Or you can specify x and y
renderable.contains((x, y))  # Or you can pass in a tuple
```

Or you can check if two Renderables are overlapping:

```python
renderable.overlaps(other)
```
