Working with Shapes in FlatRedBall2
All shape types and TileShapes are in the FlatRedBall2.Collision namespace — add using FlatRedBall2.Collision; in any file that uses them.
FlatRedBall2 has three built-in shape types: AARect, Circle, and Polygon. All shapes implement both IRenderable and ICollidable, so they handle both drawing and collision.
Shape Types
| Type | Key Properties | Notes |
|---|---|---|
AARect |
Width, Height |
Cannot rotate |
Circle |
Radius |
|
Polygon |
Points, Rotation |
Use factory methods to create |
Exposing a shape from an Entity: make the field a public auto-property (
public Circle Circle { get; private set; }) and let callers writeentity.Circle.Color = ...directly. Do not wrap it in a forwarding property likeFillColor— that pattern silently fails when assigned afterCustomInitialize. Seeentities-and-factories→references/reactive-properties.md.
Step 1: Create a Shape
var rect = new AARect { X = 0, Y = 0, Width = 64, Height = 64 };
var circle = new Circle { X = 100, Y = 0, Radius = 32 };
// Polygon factory methods:
var poly = Polygon.CreateRectangle(64, 64); // rotatable rectangle
var custom = Polygon.FromPoints(new[] {
new Vector2(0, 0), new Vector2(50, 0), new Vector2(25, 40),
});
// Concave polygons are fully supported for both rendering and collision.
// FromPoints automatically decomposes concave shapes into convex parts (Hertel-Mehlhorn)
// for correct collision — no manual decomposition needed.
Step 2: Make the Shape Visible
Shapes default to IsVisible = false. Always set IsVisible = true or the shape won't render.
Step 3: Add to the Render Pipeline
Option A — Directly on the Screen: Call Add in CustomInitialize:
Add(rect);
Option B — Attached to an Entity: entity.Add(shape) auto-adds to the render pipeline (as long as Engine is set).
Note:
entity.Add(child)only auto-registers if the entity already has anEnginereference (viaFactoryorScreen.Register).
Visual Properties
var rect = new AARect
{
Color = new Color(220, 60, 60, 200), // RGBA
IsFilled = false, // true = solid fill, false = outline
OutlineThickness = 3f, // line width in pixels
IsVisible = true,
};
Polygon fill:
IsFilled = trueear-clip triangulates and fills the interior (works for concave polygons).IsFilled = falserenders outline only. SetOutlineThickness = 0to suppress the border when filled.
Dashed/dotted outlines, gradients, drop shadows: FRB shapes render solid outlines only. For richer visualization, drop into Gum's
RectangleRuntime— Gum ships with every FRB2 game, so there's nothing to add (seegum-integration). Docs: https://docs.flatredball.com/gum/code/standard-visuals/rectangleruntime
Cleanup
rect.Destroy(); // removes from parent entity and clears references
For shapes added directly to the screen (not via entity.Add), also call Remove(rect).
Common Pitfalls
- Shape is invisible — forgot
IsVisible = true. Default isfalse. - Shape is not drawn — forgot
Add(shape)on screen, orentity.Add(shape)before entity was registered. - Shape position looks wrong — Y+ is up (see
physics-and-movement). In platformers, entity origin = feet, so offset shapes upward byHeight/2(seeplatformer-movementskill). - Polygon not rotating — use
Polygon, notAARect.
TileShapes
TileShapes is a grid-based static collision structure for tile maps. Set X, Y, and GridSize before adding tiles — positions are computed at insertion time and not updated if those properties change later.
var tiles = new TileShapes { X = 0f, Y = 0f, GridSize = 16f };
// X, Y are the world position of the bottom-left corner of cell (0, 0)
tiles.AddTileAtCell(int col, int row); // by grid index
tiles.AddTileAtWorld(float x, float y); // snapped to nearest cell
tiles.RemoveTileAtCell(col, row);
tiles.GetTileAtCell(col, row); // returns AARect? for inspection
tiles.IsVisible = true; // debug visualization
SolidSides are maintained automatically on every add/remove — interior shared edges between adjacent tiles are cleared to prevent seam snagging. No manual refresh needed.
Integrates with AddCollisionRelationship — see collision-relationships skill.
SolidSides (AARect only)
Controls which sides of a rectangle act as solid collision surfaces. Use for one-way platforms (SolidSides.Up = only top is solid) and removing interior sides from adjacent tiles to prevent seam snagging.
Default is SolidSides.All. Values combine with | and &= ~.
For detailed usage and dynamic tile grids, see:
references/reposition-directions.md— Full examples, dynamic grids, Gum naming conflict workaround
Debug overlay
Overlay.DrawSolidSides visualizes RD state on the set of rectangles you ask about: each active face shows a small green triangle inside the rect pointing toward that face; suppressed faces show nothing. Pass a Factory<T> to inspect every entity's first AARect child, or a TileShapes to inspect every tile. There is no parameterless overload — the caller always specifies what to see.
public override void CustomActivity(FrameTime time)
{
Overlay.DrawSolidSides(_brickFactory);
Overlay.DrawSolidSides(_solidTiles);
}