gale.tilemap.collision module

This file contains platformer collision helpers for TileMap: an optional, opt-in layer on top of it, not a required part of using TileMap at all. It never touches gale.physics/Box2D — this is plain AABB-against-a-grid, the same kind of hand-rolled collision most 2D platformers actually use, in or out of a physics engine.

Author: Alejandro Mujica (aledrums@gmail.com)

class gale.tilemap.collision.CollisionType[source]

Bases: object

The two kinds of blocking tile move_and_collide understands, read from a tile’s custom property (see collision_type_at). Everything else — slopes, conveyor belts, ladders, hazards — is deliberately left out: define your own property (e.g. “damage”) and read it with TileMap.properties_of_gid/get_gid yourself, the same way these two are read.

NONE: str = 'none'
SOLID: str = 'solid'
PLATFORM: str = 'platform'
gale.tilemap.collision.collision_type_at(tilemap, layer_name, row, col, collision_property='collision')[source]
Parameters:
  • tilemap (TileMap) – The map to check.

  • layer_name (str) – Which of its layers to check.

  • row (int) – A tile row.

  • col (int) – A tile column.

  • collision_property (str) – The custom tile property (set in Tiled’s tileset editor) collision-checking reads. The default value is “collision”.

Returns:

One of the CollisionType constants: CollisionType.NONE for an empty cell, an out-of-bounds cell, or a tile whose collision_property isn’t “solid”/”platform”.

Return type:

str

gale.tilemap.collision.move_and_collide(tilemap, layer_name, x, y, width, height, dx, dy, collision_property='collision')[source]

Moves an entity’s top-left corner by (dx, dy), one axis at a time (x, then y — the usual order for a 2D platformer, so a corner case sliding along a wall still gets stopped by the wall rather than a floor first), snapping it flush against whatever it runs into instead of leaving a gap.

Works entirely in floats, and never rounds x/y to whole pixels anywhere internally — including for the tile-overlap test itself, not just for the position you get back. Rounding either one is enough to reintroduce the bug this is written to avoid: at a typical frame rate, one frame’s movement under gravity near the ground is a fraction of a pixel, so an entity resting on solid ground keeps re-falling that fraction and re-colliding every frame — which reads as the ground-check flickering on and off, since a rounded position can stay numerically unchanged call after call while the real, unrounded one keeps drifting down into the floor. Round only when you need a pygame.Rect for rendering/hit testing elsewhere (e.g. pygame.Rect(round(x), round(y), width, height)).

A “solid” tile blocks in every direction. A “platform” tile only blocks downward movement, and only if the entity was already at or above the platform’s top edge before this call — never from below (walking/jumping up through it) or from the sides (walking through it at the same height).

Parameters:
  • tilemap (TileMap) – The map to collide against.

  • layer_name (str) – Which of its layers to collide against.

  • x (float) – The entity’s current x position (top-left corner), before this move.

  • y (float) – The entity’s current y position (top-left corner), before this move.

  • width (float) – The entity’s width.

  • height (float) – The entity’s height.

  • dx (float) – Horizontal movement this call, in pixels (e.g. vx * dt).

  • dy (float) – Vertical movement this call, in pixels (e.g. vy * dt).

  • collision_property (str) – Forwarded to collision_type_at.

Returns:

(new_x, new_y, collided_x, collided_y) — the resulting position, and whether it was stopped short on each axis.

Return type:

Tuple[float, float, bool, bool]