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


See example_split_screen.py for a simple split screen example with two player. Using WASD and Arrow keys for independent movement.

example_split_screen.png


See example_shake.py for a simple shaking camera example.

See example_static_camera.py for a static camera fixed to regions. The camera does not follow the player all the time, only when the player moves to a new region.


See example_parallax.py for a simple example of a "background view" that moves "slower" than the foreground. A traditional parallax effect.

For fun, I also added a variant that uses _sdl2 Textures: See example_parallax_sdl2.py.

example_parallax.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.4.1.tar.gz (7.3 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.4.1-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pygame_visor-0.4.1.tar.gz
  • Upload date:
  • Size: 7.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pygame_visor-0.4.1.tar.gz
Algorithm Hash digest
SHA256 c0530fba6c13ced2732297b320768ac92f04d60360df82bacdbdaffba5bb4c7b
MD5 63fa6ea532b799be75a3f90b43ce8e07
BLAKE2b-256 4a6aea2b22b316ea93805fd05a1bf41d5c745e733a48b5a4c16b7ab210013bbe

See more details on using hashes here.

Provenance

The following attestation bundles were made for pygame_visor-0.4.1.tar.gz:

Publisher: push-to-pypi.yaml on nitori/pygame-visor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: pygame_visor-0.4.1-py3-none-any.whl
  • Upload date:
  • Size: 9.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pygame_visor-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 81a3923cadb5e93713c284df282cba528fa7b4e8349394a66cac7218aa6a2b51
MD5 8d821c38560ecfa2989886b4d906c8a6
BLAKE2b-256 bd91256b49b6586ee2a7855c7d770e513e0df55fd922900df47aa78ea4c6f726

See more details on using hashes here.

Provenance

The following attestation bundles were made for pygame_visor-0.4.1-py3-none-any.whl:

Publisher: push-to-pypi.yaml on nitori/pygame-visor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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