encompass-cs-docs/content/concepts/renderer.md

109 lines
3.7 KiB
Markdown
Raw Normal View History

2019-05-22 21:22:29 +00:00
---
title: "Renderer"
date: 2019-05-22T14:16:06-07:00
weight: 30
---
A Renderer is responsible for reading the game state and telling the game engine what to draw to the screen.
{{% notice note %}}
Remember: Encompass isn't a game engine and it doesn't have a rendering system. So Renderers aren't actually doing the rendering, it is just a way of structuring how we tell the game engine what to render.
2019-05-22 21:22:29 +00:00
{{% /notice %}}
2019-12-01 21:43:31 +00:00
There are two kinds of renderers: GeneralRenderers and OrderedRenderers.
2019-05-22 21:22:29 +00:00
2020-07-11 00:06:40 +00:00
A GeneralRenderer is a Renderer which reads the game state in order to draw elements to the screen. It also requires a layer, which represents the order in which the Draw method will execute in relation to other Renderers.
2019-05-22 21:22:29 +00:00
If you were using FNA, a GeneralRenderer might look like this:
2019-12-01 21:43:31 +00:00
```cs
using System;
using Encompass;
using Microsoft.Xna.Framework;
2020-07-11 00:06:40 +00:00
using MyGame.Components;
using MyGame.Messages;
2019-06-13 17:43:08 +00:00
2020-07-11 00:06:40 +00:00
namespace MyGame.Renderers
2019-12-01 21:43:31 +00:00
{
public class GridRenderer : GeneralRenderer
{
private int gridSize;
private PrimitiveDrawer primitiveDrawer;
2019-06-13 17:43:08 +00:00
2019-12-01 21:43:31 +00:00
public GridRenderer(PrimitiveDrawer primitiveDrawer)
{
this.primitiveDrawer = primitiveDrawer;
this.gridSize = 16;
}
2019-06-13 17:43:08 +00:00
2019-12-01 21:43:31 +00:00
public override void Render()
{
if (SomeComponent<EditorModeComponent>() && SomeComponent<MouseComponent>())
{
var entity = ReadEntity<MouseComponent>();
var transformComponent = GetComponent<TransformComponent>(entity);
Rectangle rectangle = new Rectangle
{
X = (transformComponent.Position.X / gridSize) * gridSize,
Y = (transformComponent.Position.Y / gridSize) * gridSize,
Width = gridSize,
Height = gridSize
};
primitiveDrawer.DrawBorder(rectangle, 0, new System.Numerics.Vector2(1, 1), Color.White, 1);
}
}
2019-06-13 17:43:08 +00:00
}
}
```
2020-07-11 00:06:40 +00:00
This GeneralRenderer will draw a rectangle at the position of the mouse on the screen if an `EditorModeComponent` exists in the world.
GeneralRenderers are great for things like a heads-up display, where we always want a group of particular elements to be drawn at a specific layer regardless of the specifics of the game state.
2019-12-01 21:43:31 +00:00
An OrderedRenderer provides a structure for the common pattern of wanting to draw an individual Component at a specific layer. OrderedRenderers must specify a component that implements IDrawableComponent.
If you were using FNA, an OrderedRenderer might look like this:
2019-12-01 21:43:31 +00:00
```cs
using Encompass;
using Microsoft.Xna.Framework.Graphics;
2020-07-11 00:06:40 +00:00
using MyGame.Components;
using MyGame.Extensions;
2019-12-01 21:43:31 +00:00
using System;
using System.Numerics;
2019-05-22 21:22:29 +00:00
2020-07-11 00:06:40 +00:00
namespace MyGame.Renderers
2019-12-01 21:43:31 +00:00
{
public class Texture2DRenderer : OrderedRenderer<Texture2DComponent>
{
private SpriteBatch spriteBatch;
2019-06-13 17:43:08 +00:00
2019-12-01 21:43:31 +00:00
public Texture2DRenderer(SpriteBatch spriteBatch)
{
this.spriteBatch = spriteBatch;
}
2019-06-13 17:43:08 +00:00
2019-12-01 21:43:31 +00:00
public override void Render(Entity entity, Texture2DComponent textureComponent)
{
var transformComponent = GetComponent<TransformComponent>(entity);
2019-06-13 17:43:08 +00:00
spriteBatch.Draw(
textureComponent.Texture,
transformComponent.Position,
null,
textureComponent.Color,
transformComponent.Rotation,
textureComponent.Origin,
transformComponent.Scale,
SpriteEffects.None,
0
);
2019-12-01 21:43:31 +00:00
}
2019-06-13 17:43:08 +00:00
}
}
```
2019-12-01 21:43:31 +00:00
For 2D games, you will need to use layers to be specific about the order in which elements are drawn to the screen. For a 3D game you will probably end up delegating most of the rendering to some kind of scene/camera system.