For Python 3.10+ and pygame‑ce 2.5.6+
pygame‑ce is supported
A simple and fast module for animated scrolling maps for your new or existing game.
If you find this useful, please consider making a donation to help support development:
pyscroll‑ce is a maintained fork of the original pyscroll project.
The old repository has been inactive, with pull requests left unmerged for over a year, so this new repo was created to keep the project alive and compatible with modern Python and pygame‑ce.
pyscroll‑ce is a generic module for fast scrolling images with pygame. It uses clever optimizations to achieve high frame rates. Its sole purpose is to draw maps — it does not load images or data, so you can integrate it with your own data structures, tile storage, and rendering logic.
It is fully compatible with pytmx, allowing you to use maps created with the Tiled Map Editor. It also has out‑of‑the‑box support for pygame sprites.
- Reload map tiles and data without restarting the game
- Draw sprites or plain surfaces in layers
- Support for animated tiles
- Zoom in and out
- Optional drop‑in replacement for
pygame.LayeredGroup - Pixel alpha and colorkey tilesets supported
- Draw and scroll shapes
- Fast and lightweight footprint
- Performance is independent of map size
- Direct support for pytmx‑loaded maps from Tiled
- Camera system with smooth follow, zoom, bounds clamping, rails, cutscenes, and transitions
pyscroll‑ce includes a pygame sprite group that renders all sprites on the map and correctly draws them above or below tiles. Sprites can use their rect in world coordinates, and the group acts like a camera, translating world coordinates to screen coordinates while rendering sprites and map layers.
This makes it easy to implement minimaps or chunky retro‑style graphics.
| Class | Description |
|---|---|
BasicCamera |
Simple smooth follow |
FollowCamera |
Smooth follow with optional deadzone |
PlatformerCamera |
Directional vertical deadzone for platformers |
ZoomCamera |
Wraps any camera, adds smooth zoom |
BoundsCamera |
Wraps any camera, clamps to world bounds |
CutsceneCamera |
Autonomous movement along waypoints, linear or Catmull-Rom |
SplitFollowCamera |
Follows midpoint of multiple targets, zooms with separation |
RailCamera |
Constrained to a polyline rail |
DebugFlyCamera |
Free movement via input, for development |
Use CameraManager to smoothly transition between any two cameras with a configurable duration.
Install from pip:
pip install pyscroll-ce # not yet published to PyPIOr install from source (inside the project folder):
pip install .For development (editable install):
pip install -e .For a gentle introduction, open apps/tutorial/quest.py. It demonstrates how to use PyscrollGroup for efficient rendering.
The Quest demo shows how to draw maps with pytmx, render layers quickly, and handle sprite layering (e.g., the Hero being covered when moving under certain tiles).
import pygame
from pytmx.util_pygame import load_pygame
import pyscroll
from pyscroll.camera import FollowCamera
class Sprite(pygame.sprite.Sprite):
def __init__(self, surface) -> None:
super().__init__()
self.image = surface
self.rect = surface.get_rect()
class Game:
def __init__(self, screen: pygame.Surface) -> None:
self.screen = screen
# Load TMX
tmx_data = load_pygame("desert.tmx")
# Create map renderer
map_data = pyscroll.TiledMapData(tmx_data)
map_layer = pyscroll.BufferedRenderer(map_data, screen.get_size())
# Create group with map
self.group = pyscroll.PyscrollGroup(map_layer=map_layer)
# Camera
self.camera = FollowCamera()
# Add a sprite
surface = pygame.image.load("my_surface.png").convert_alpha()
self.hero = Sprite(surface)
self.group.add(self.hero)
def update(self, dt: float) -> None:
self.group.update(dt)
new_center = self.camera.update(self.group.view, self.hero.rect, dt)
self.group.center(new_center)
def draw(self) -> None:
self.group.draw(self.screen)pyscroll‑ce can be integrated with existing map data. You may need to create an adapter class or adjust your data handler to match the TiledMapData API.
Example: rendering custom surfaces with layer positions.
map_layer = pyscroll.BufferedRenderer(map_data, map_size)
def game_engine_draw():
surfaces: list[Renderable] = []
for game_object in my_game_engine:
surfaces.append(
Renderable(
layer=game_object.layer,
rect=game_object.get_screen_rect(),
surface=game_object.get_surface(),
blendmode=None,
)
)
map_layer.draw(screen, screen.get_rect(), surfaces)By default, pyscroll‑ce does not handle maps with completely empty areas (no tiles in any layer).
Solutions:
- Fill empty areas with a background tile in Tiled or your data.
- Pass
alpha=TruetoBufferedRendererto enable per‑pixel alpha buffers (slower, ~33% performance reduction).
Streaks are caused by missing tiles. See above for solutions.
Yes, but performance will be reduced. Options:
- Pass
alpha=Trueto the constructor. - Use a colorkey (
colorkey=yourColor).
Yes, for tiles. For transparency under the map, use alpha or colorkey as described above.
Not directly. You can build parallax effects by using multiple renderers with alpha=True and scrolling them at different speeds.