Expand description
A scrolling viewport into a world larger than the screen. A scrolling viewport into a world larger than the screen.
Camera is pure geometry: it converts between world coordinates (cells in
some large space) and screen coordinates (cells in a Rect on the
terminal), and reports which world cells are currently visible. It holds no
rendering opinion, so it works with any drawing style and is testable
without a backend.
world space (Size) screen space (terminal cells)
+--------------------------------+
| | viewport (a Rect on screen)
| origin | +------------------+
| x----------------+ | | (vp.left, vp.top)|
| | visible_bounds | | ==> | +----------+ |
| | (clamped to | | | | drawn | |
| | the world) | | | | cells | |
| +----------------+ | | +----------+ |
| | +------------------+
+--------------------------------+
origin = world cell shown at the viewport's top-left, clamped to [0, world - viewport].
world_to_screen(w) = viewport.top_left + (w - origin), culled to visible_bounds.
screen_to_world(s) = origin + (s - viewport.top_left), culled to the world.Centering clamps to the world edges (the “scrolling map” convention): the
viewport never scrolls past [0, world), so the target stays centered
except near the edges, where it drifts toward the corner. A world smaller
than the viewport pins the origin at (0, 0), with all the slack on the
right and bottom of the given viewport rect; use
set_viewport_fitted instead of
set_viewport when a world that may be smaller
than its viewport (a fixed board, a generated map, a minimap) should be
letterboxed and centered instead.
See the 12_dungeon_scroll example for Camera in action:
https://main.retroglyph.dev/examples/12_dungeon_scroll/terminal/.
Grid::from_charmap builds a styled grid from an ASCII map or
level string, one tile per character; combined with a Camera and multi-layer compositing,
this is how a scrolling roguelike loads and follows a map larger than the screen (see the
11_sokoban example for from_charmap itself, and 15_outpost_dashboard for a Camera used
alongside a UI).
§Example
use retroglyph_core::grid::{Pos, Rect, Size};
use retroglyph_ui::Camera;
// A 10x10 viewport onto a 100x100 world.
let mut cam = Camera::new(Rect::new(0, 0, 10, 10), Size::new(100, 100));
cam.center_on(Pos::new(50, 50));
assert_eq!(cam.origin(), Pos::new(45, 45));
assert_eq!(cam.world_to_screen(Pos::new(50, 50)), Some(Pos::new(5, 5)));
// Near an edge the view clamps rather than showing past the world.
cam.center_on(Pos::new(1, 1));
assert_eq!(cam.origin(), Pos::new(0, 0));Structs§
- Camera
- A rectangular viewport onto a larger world, with world/screen conversions.