Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,12 @@ jobs:
strategy:
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12']
dependencies:
- pygame pyglet
- pygame
- pyglet
- "null"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Requirements
if: ${{ matrix.dependencies != 'null' }}
run: pip install ${{ matrix.dependencies }}
run: pip install pygame pyglet
- name: Run Tests
run: python -m unittest tests/pytmx/test_pytmx.py
run: python -m unittest discover -s tests/pytmx -p "test_*.py"
54 changes: 30 additions & 24 deletions apps/pygame_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"""

import logging
from pathlib import Path

import pygame
from pygame.locals import *
Expand All @@ -27,27 +28,27 @@
logger = logging.getLogger(__name__)


def init_screen(width, height):
def init_screen(width: int, height: int) -> pygame.Surface:
"""Set the screen mode
This function is used to handle window resize events
"""
return pygame.display.set_mode((width, height), pygame.RESIZABLE)


class TiledRenderer(object):
class TiledRenderer:
"""
Super simple way to render a tiled map
"""

def __init__(self, filename) -> None:
tm = load_pygame(filename)
def __init__(self, filename: Path) -> None:
tm = load_pygame(filename.as_posix())

# self.size will be the pixel size of the map
# this value is used later to render the entire map to a pygame surface
self.pixel_size = tm.width * tm.tilewidth, tm.height * tm.tileheight
self.tmx_data = tm

def render_map(self, surface) -> None:
def render_map(self, surface: pygame.Surface) -> None:
"""Render our map to a pygame surface

Feel free to use this as a starting point for your pygame app.
Expand Down Expand Up @@ -76,7 +77,7 @@ def render_map(self, surface) -> None:
elif isinstance(layer, TiledImageLayer):
self.render_image_layer(surface, layer)

def render_tile_layer(self, surface, layer) -> None:
def render_tile_layer(self, surface: pygame.Surface, layer: TiledTileLayer) -> None:
"""Render all TiledTiles in this layer"""
# deref these heavily used references for speed
tw = self.tmx_data.tilewidth
Expand All @@ -96,7 +97,9 @@ def render_tile_layer(self, surface, layer) -> None:
sy = x * th2 + y * th2
surface_blit(image, (sx + ox, sy))

def render_object_layer(self, surface, layer) -> None:
def render_object_layer(
self, surface: pygame.Surface, layer: TiledObjectGroup
) -> None:
"""Render all TiledObjects contained in this layer"""
# deref these heavily used references for speed
draw_lines = pygame.draw.lines
Expand All @@ -122,30 +125,31 @@ def render_object_layer(self, surface, layer) -> None:
surface, rect_color, obj.closed, obj.apply_transformations(), 3
)

def render_image_layer(self, surface, layer) -> None:
def render_image_layer(
self, surface: pygame.Surface, layer: TiledImageLayer
) -> None:
if layer.image:
surface.blit(layer.image, (0, 0))


class SimpleTest(object):
class SimpleTest:
"""Basic app to display a rendered Tiled map"""

def __init__(self, filename) -> None:
def __init__(self, filename: Path) -> None:
self.renderer = None
self.running = False
self.dirty = False
self.exit_status = 0
self.load_map(filename)

def load_map(self, filename) -> None:
def load_map(self, filename: Path) -> None:
"""Create a renderer, load data, and print some debug info"""
self.renderer = TiledRenderer(filename)

logger.info("Objects in map:")
for obj in self.renderer.tmx_data.objects:
logger.info(obj)
for k, v in obj.properties.items():
logger.info("%s\t%s", k, v)
logger.info("Object: %s", obj)
logger.debug("Properties: %s", vars(obj))

logger.info("GID (tile) properties:")
for k, v in self.renderer.tmx_data.tile_properties.items():
Expand All @@ -155,7 +159,7 @@ def load_map(self, filename) -> None:
for k, v in self.renderer.tmx_data.get_tile_colliders():
logger.info("%s\t%s", k, list(v))

def draw(self, surface) -> None:
def draw(self, surface: pygame.Surface) -> None:
"""Draw our map to some surface (probably the display)"""
# first we make a temporary surface that will accommodate the entire
# size of the map.
Expand Down Expand Up @@ -198,8 +202,13 @@ def handle_input(self) -> None:
self.exit_status = 0
self.running = False

def run(self):
"""This is our app main loop"""
def run(self) -> int:
"""
Main loop of the app.

Returns:
int: Exit status (0 = success, 1 = error)
"""
self.dirty = True
self.running = True
self.exit_status = 1
Expand All @@ -219,9 +228,6 @@ def run(self):


if __name__ == "__main__":
import glob
import os.path

pygame.init()
pygame.font.init()
screen = init_screen(600, 600)
Expand All @@ -232,11 +238,11 @@ def run(self):

# loop through a bunch of maps in the maps folder
try:
here = os.path.dirname(os.path.abspath(__file__))
for filename in glob.glob(os.path.join(here, "data", "*.tmx")):
logger.info("Testing %s", filename)
for filename in Path("apps/data").glob("*.tmx"):
logger.info("Testing %s", filename.as_posix())
if not SimpleTest(filename).run():
break
except:
except Exception as e:
logger.exception("Unhandled exception: %s", e)
pygame.quit()
raise
Loading