Skip to main content

Pygame Visor - a simple Camera/Viewport library

Project description

Pygame Visor

Camera/Viewport library.

Currently only works with pygame-ce, as it's using pygame.FRect in some parts.

License

MIT © 2025 Sani (https://github.com/nitori)

Install

Currently pygame-ce is required instead of pygame. If you have pygame installed, uninstall it first.

pip install pygame-visor pygame-ce

or using uv

uv add pygame-visor pygame-ce

Camera/Viewport System – Feature Overview

  • Translate between world and screen coordinates (world_to_screen, screen_to_world)
    • Needed for input mapping (e.g. screen_to_world(surface_rect, mouse_pos))
  • Support multiple view modes:
    • Fixed world area (scales with screen), with or without padding
    • Fixed zoom level (screen res affects visible area)
  • Camera movement via external control (move_to(pos))
  • Optional clamping to world bounds / limits (camera can't move past edges)
  • Multiple views supported via independent instances (multi-camera/minimap/splitscreen)
  • Support lerping/smooth movement to a target position (or perhaps have the user do it themselves?)
    • Can probably get some more love, but a basic lerp already works.
  • Expose get_bounding_box(surface_rect) for rendering logic
    • Camera "requests" world region using the bounding box method above; game provides matching surfaces
    • Accept surface size/rect for bounding box calculations (for the different view modes above)
  • Handle zooming, including fractional zoom
    • UX: Optional zoom-to-cursor behavior (maintains world point under cursor)

Optional stuff for now

  • debug helpers (draw bounding box, show mouse world pos, etc.)
  • Overscan/margin support for effects, camera shake, etc.

View/Visor Modes

1. Fixed Region (letterbox)

  • A specific world size (e.g. 400x300 units) is always shown.
  • If the screen's aspect ratio differs, black bars (letterboxing) fill the space.
  • Scaling happens to fit the screen, preserving aspect ratio.

2. Fixed Region (extended view)

  • A specific world size (e.g. 400x300) is the minimum shown.
  • If the screen is larger/wider, more of the world is revealed (i.e. expands the visible region).
  • No letterboxing; fills the screen with as much world as possible.

Basic Usage

# get a surface the view can draw on. Could also be screen directly.
surf = pygame.Surface(400, 300)

# Create a Visor instance
visor = Visor(
    VisorMode.RegionLetterbox,  # One of two modes (see above)
    screen.get_rect(),  # pass in the rect of the surface you wish to draw on.
    region=(0, 0, 400, 300),  # world region to "view"
    limits=[-2000, -2000, 2000, 2000],  # Optional min/max x,y coords to constrain the visor to.
)

while True:
    # ...

    # Get the world bounding box (it returns a pygame.FRect, indicating the area of
    # the world that is currently visible)
    # Uses the stored screen rect passed in the constructor.
    # Use update_screen(new_rect) if your screen/surface got resized.
    bbox = visor.get_bounding_box()

    # Get iterable of surfaces, that cover the bounding box
    # This you need to implement yourself!
    # Return an iterable of tuples: ((world_x, world_y), tile_surface)
    # Where tile_surface (at the moment) must have world coords width/height. Surfaces are expected to be
    # pre-rendered at world-scale (1 unit = 1 pixel in world space). The Visor system will scale them
    # appropriately based on screen resolution and visor mode.
    tiles = world.get_tiles_iterable(bbox)

    # render tiles to surface, the visor will autoscale them to the correct size.
    visor.render(surf, tiles)

    # optional (if you don't use the screen directly), blit to screen:
    screen.blit(surf, (0, 0))

    # ...

If you have a player, that needs to be rendered on top of the map. Assuming player.surf holds your players surface, and player.rect holds the players position:

while True:
    # ...

    # update visor based on player position *before* getting the bbox
    visor.move_to(player.rect.center)  # visor.lerp_to(...) is also possible
    bbox = visor.get_bounding_box()

    # ... get tiles etc.

    # render map
    visor.render(surf, tiles)

    # render the player using visor.render, so it will be scaled correctly
    visor.render(surf, [
        (player.rect.topleft, player.surf)
    ])

    # ...

Examples

See example_map.py for a full working example of a main visor and a minimap using two independent cameras.

example_map.png


See example_modes.py to demonstrate the difference between VisorMode.RegionLetterbox and VisorMode.RegionExpand.

example_modes.png


See example_zoom.py to demonstrate a simple way to zoom your visor in and out.

example_zoom.png


See example_mouse.py for a demonstration of tracking mouse screen pos to world tile position.

example_mouse.png


See example_ui.py for a simple UI example, of how to position them in the "active" area, in any VisorMode.

example_ui.png

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pygame_visor-0.2.0.tar.gz (65.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pygame_visor-0.2.0-py3-none-any.whl (7.5 kB view details)

Uploaded Python 3

File details

Details for the file pygame_visor-0.2.0.tar.gz.

File metadata

  • Download URL: pygame_visor-0.2.0.tar.gz
  • Upload date:
  • Size: 65.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.14

File hashes

Hashes for pygame_visor-0.2.0.tar.gz
Algorithm Hash digest
SHA256 69f3be769a911343496d21dbc352045deb41eec9d76f83651c906cc6fa48f6d5
MD5 95491eca8d91b12d27dfbf0264b4fe83
BLAKE2b-256 f135088ce7677396a378d8931afe4a0898c8324cba35f20ec79f794c5abbc232

See more details on using hashes here.

File details

Details for the file pygame_visor-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pygame_visor-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9ffb949ca8200dfbbf598c03c429b0fecec3138c31ac80f5ff225256f22a956d
MD5 c25b8879ef05d84170f8518240ffa115
BLAKE2b-256 e93581695cbea92f03858895a7a10a360463e36507026366289c7c8c0168ff98

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page