Struct Camera2
An immutable 2D camera that converts between world-space LengthPoint2 positions and screen-space Microsoft.Xna.Framework.Vector2 pixel coordinates.
public readonly record struct Camera2 : IEquatable<Camera2>
- Implements
- Inherited Members
Remarks
Camera2 is a readonly record struct. All "mutating" operations
(such as ZoomBy(double)) return a new instance. Late-bound camera state
(e.g. a camera field that is not set in a constructor) will be default, not
null — guard against Position being Origin
and Scale being zero if the camera may not yet be initialised.
The camera is centred on Position in world space. The centre of the screen always displays the camera's world position. Points to the right of the camera appear to the right on screen; points above the camera appear higher on screen (subject to the YAxis convention).
The Scale defines the zoom level: more pixels per world unit means the world appears larger on screen (zoomed in). Use ZoomBy(double) to adjust zoom and Lerp(PixelScale, PixelScale, double) to animate it smoothly.
Camera2 is stateless: it holds no mutable fields and carries no render
state. Create one per frame (or whenever the camera moves) and pass it to your render
system. For high-frequency render loops, compute screenSize once per frame and
store it as a local variable rather than recalculating it on every
WorldToScreen(LengthPoint2, Vector2) call.
// Define the camera: centred on the player, 32 pixels per metre, Y-down (MonoGame default).
var camera = new Camera2(
Position: player.Position,
Scale: PixelScale.PerMeter(32));
// In the render loop:
Vector2 screenPos = camera.WorldToScreen(enemy.Position, screenSize);
spriteBatch.Draw(enemyTexture, screenPos, Color.White);
// Smooth zoom in an update loop:
_currentScale = PixelScale.Lerp(_currentScale, _targetScale, deltaTime * smoothSpeed);
camera = camera with { Scale = _currentScale };
Constructors
Camera2(LengthPoint2, PixelScale, YAxisMode)
An immutable 2D camera that converts between world-space LengthPoint2 positions and screen-space Microsoft.Xna.Framework.Vector2 pixel coordinates.
public Camera2(LengthPoint2 Position, PixelScale Scale, YAxisMode YAxis = YAxisMode.YDown)
Parameters
PositionLengthPoint2The world-space point that maps to the centre of the screen.
ScalePixelScaleThe zoom level expressed as a PixelScale. For example,
PixelScale.PerMeter(32)means one metre occupies 32 pixels.YAxisYAxisModeWhether the screen Y axis increases downward (YDown, the MonoGame default) or upward (YUp). Defaults to YDown.
Remarks
Camera2 is a readonly record struct. All "mutating" operations
(such as ZoomBy(double)) return a new instance. Late-bound camera state
(e.g. a camera field that is not set in a constructor) will be default, not
null — guard against Position being Origin
and Scale being zero if the camera may not yet be initialised.
The camera is centred on Position in world space. The centre of the screen always displays the camera's world position. Points to the right of the camera appear to the right on screen; points above the camera appear higher on screen (subject to the YAxis convention).
The Scale defines the zoom level: more pixels per world unit means the world appears larger on screen (zoomed in). Use ZoomBy(double) to adjust zoom and Lerp(PixelScale, PixelScale, double) to animate it smoothly.
Camera2 is stateless: it holds no mutable fields and carries no render
state. Create one per frame (or whenever the camera moves) and pass it to your render
system. For high-frequency render loops, compute screenSize once per frame and
store it as a local variable rather than recalculating it on every
WorldToScreen(LengthPoint2, Vector2) call.
// Define the camera: centred on the player, 32 pixels per metre, Y-down (MonoGame default).
var camera = new Camera2(
Position: player.Position,
Scale: PixelScale.PerMeter(32));
// In the render loop:
Vector2 screenPos = camera.WorldToScreen(enemy.Position, screenSize);
spriteBatch.Draw(enemyTexture, screenPos, Color.White);
// Smooth zoom in an update loop:
_currentScale = PixelScale.Lerp(_currentScale, _targetScale, deltaTime * smoothSpeed);
camera = camera with { Scale = _currentScale };
Properties
Position
The world-space point that maps to the centre of the screen.
public LengthPoint2 Position { get; init; }
Property Value
Scale
The zoom level expressed as a PixelScale. For example,
PixelScale.PerMeter(32) means one metre occupies 32 pixels.
public PixelScale Scale { get; init; }
Property Value
YAxis
Whether the screen Y axis increases downward (YDown, the MonoGame default) or upward (YUp). Defaults to YDown.
public YAxisMode YAxis { get; init; }
Property Value
Methods
ScreenToWorld(Vector2, Vector2)
Converts a screen-space pixel coordinate back to a world-space position.
public LengthPoint2 ScreenToWorld(Vector2 screenPoint, Vector2 screenSize)
Parameters
screenPointVector2The pixel coordinate on the screen.
screenSizeVector2The size of the render target in pixels (width, height). Must match the value passed to WorldToScreen(LengthPoint2, Vector2) to get an exact inverse.
Returns
- LengthPoint2
The world-space LengthPoint2 corresponding to the screen pixel, expressed in Unit.
Examples
LengthPoint2 worldMouse = camera.ScreenToWorld(mouseState.Position.ToVector2(), screenSize);
bool hit = circle.Contains(worldMouse);
Remarks
This is the exact inverse of WorldToScreen(LengthPoint2, Vector2):
ScreenToWorld(WorldToScreen(p, size), size) ≈ p within floating-point precision.
Typical use is mouse picking — convert the cursor's screen position to a world coordinate
to test against game objects.
WorldToScreen(LengthPoint2, Vector2)
Converts a world-space position to a screen-space pixel coordinate.
public Vector2 WorldToScreen(LengthPoint2 worldPoint, Vector2 screenSize)
Parameters
worldPointLengthPoint2The position in world space to project.
screenSizeVector2The size of the render target in pixels (width, height). The screen centre is at
screenSize / 2.
Returns
- Vector2
The pixel coordinate on screen. The screen centre corresponds to Position. Values outside
[0, screenSize]are off-screen but valid — callers may clip as needed.
Examples
var camera = new Camera2(LengthPoint2.Origin, PixelScale.PerMeter(32));
Vector2 px = camera.WorldToScreen(entity.Position, new Vector2(1920, 1080));
WorldToScreenScale(Length)
Converts a world-space length (such as a shape radius) to a pixel size for rendering.
public float WorldToScreenScale(Length worldLength)
Parameters
worldLengthLengthThe length in world space to convert.
Returns
- float
The equivalent size in pixels as a float. Lengths in units other than Unit are automatically converted.
Examples
Single pixelRadius = camera.WorldToScreenScale(circle.Radius);
// Draw a circle at the projected centre with pixelRadius
Remarks
Use this when you need a scalar pixel size rather than a position — for example,
to compute the pixel radius of a Circle2 for drawing.
Y-axis mode does not affect this result; lengths are always positive.
ZoomBy(double)
public Camera2 ZoomBy(double factor)
Parameters
factordoubleThe zoom multiplier. Values greater than
1.0zoom in (more pixels per unit); values between0and1.0zoom out (fewer pixels per unit).
Returns
Examples
// Zoom in 10% each frame while a button is held
if (zoomInHeld)
camera = camera.ZoomBy(1.1);
ZoomBy(double, Vector2, Vector2)
Returns a new Camera2 zoomed by factor, adjusted so
that screenFocus remains at the same world position before and
after the zoom.
public Camera2 ZoomBy(double factor, Vector2 screenFocus, Vector2 screenSize)
Parameters
factordoubleThe zoom multiplier. Values greater than
1.0zoom in; values between0and1.0zoom out. Must be positive and non-zero.screenFocusVector2The screen-space pixel coordinate that should stay fixed during the zoom — typically the cursor position or the centre of a pinch gesture.
screenSizeVector2The size of the render target in pixels (width, height). For high-frequency render loops, compute this once per frame and pass it in rather than recalculating it on every call.
Returns
- Camera2
A new Camera2 whose Scale has been multiplied by
factorand whose Position has been adjusted so that the world point underscreenFocusis unchanged.
Examples
// Zoom in 2× toward the cursor position
camera = camera.ZoomBy(2.0, mouseState.Position.ToVector2(), screenSize);
Remarks
The adjustment formula is:
newPosition = worldFocus + (oldPosition − worldFocus) / factor,
where worldFocus = ScreenToWorld(screenFocus, screenSize) on the pre-zoom camera.
factor is a raw double multiplier rather than a
Ratio because it represents a scale change, not a fractional quantity.