An Entity2D representing a static rectangular interior obstacle in the arena. It stores position/size/depth, a glass flag that alters collision semantics for players, provides Setup to initialize transform, and CreateVisuals to add a sprite layer for rendering.
namespace BlockParty;
/// <summary>
/// A static solid rectangle inside the arena (an interior "wall" region a level can place —
/// e.g. a block in the centre, or the filled bottom-middle of a C-shaped arena). Being an
/// <see cref="Entity2D"/> means the shared collision helpers (<see cref="Entity2D.DoesPenetrate"/>,
/// <see cref="Entity2D.Unpenetrate"/>, the directional <c>other.X > X</c> filters) treat it as a
/// solid exactly like a block — so the player lands on / wall-jumps off / is crushed against it and
/// moving blocks bounce off it, all through the existing block-collision paths.
///
/// Obstacles never move and never <see cref="Entity2D.Tick"/>; they are NOT added to the stage's
/// <c>Blocks</c> list (so they don't count toward the win condition or score). Their solidity is
/// gated for the player by <see cref="CharacterAbilities.CollidesWithArenaWalls"/>, matching the
/// outer arena walls: a phasing/wrap character passes through them (and wraps across — see
/// <see cref="WrapArenaEdgesAbility"/>).
/// </summary>
public sealed class Obstacle : Entity2D
{
/// <summary>True for a GLASS panel: an obstacle solid ONLY to players — every character collides
/// with it, including wall-phasing/wrap ones (see <c>Player.ObstacleSolidToUs</c>), while blocks,
/// hazards, lasers and fields all pass straight through. Glass lives in the stage's normal
/// obstacle list so every player collision/crush/spike path treats it like an interior wall for
/// free; the block/hazard views skip flagged entries instead (see
/// <c>GameStage.GetSolidObstacles</c>). Authored spikes on its faces are player-lethal like any
/// obstacle face.</summary>
public bool IsGlass { get; set; }
/// <summary>Position + size in logical pixels; the parent GameObject is placed at the arena
/// wall depth. Renders as a single solid fill quad (spikes on its faces are drawn separately
/// by the stage's wall-face system).</summary>
public void Setup( Vector2 center, Vector2 size )
{
Pos = center;
Size = size;
Depth = Globals.DEPTH_WALL;
}
public void CreateVisuals( Color fillColor, Vector2? visualCenter = null, Vector2? visualSize = null )
{
var sr = SpriteLayer.Add( GameObject, "sprites/pixel.sprite", visualSize ?? Size, "idle" );
sr.Opaque = true;
sr.Color = fillColor;
if ( visualCenter is Vector2 center )
{
var local = sr.GameObject.LocalPosition;
sr.GameObject.LocalPosition = new Vector3( center.x - Pos.x, center.y - Pos.y, local.z );
}
SyncTransform();
}
}