Tiled Maps & Tile Based Movement - darkopevec/kivy GitHub Wiki

What are we trying to do?

The first thing I always like to do when using a new framework is load a Tiled .tmx file and display the map in the framework, and get tile-based movement for characters up and running.

  • Create a class that loads Kivy-compatible images from Tiled map tile sets
  • Create a Kivy Widget that displays a loaded map
  • Create a Character widget that can walk around the map with user input

Prerequisites

Install PyTMX. The plan is to create a class that loads images that Kivy can use while leveraging the existing PyTMX code.

Loading Tiled Maps (KivyTiledMap.py)

The key things that need to be done to override the PyTMX class are:

  • Override loadTileImages() on TiledMap
  • Actually call loadTileImages() before it's time to display them

The class to use for loading a tile set image is:

from kivy.core.image import Image

And you can easily get the texture in the image via:

image = Image(filepath)
texture = image.texture

The most important concept is that we want to grab each tile out of the tile set's source image file with that texture's get_region() capability:

tile = texture.get_region(x, y, tileset.tilewidth, tileset.tileheight)

Displaying Tiled Maps (TiledGrid.py)

The best idea I had for displaying Tiled information was, conceptually:

  • Create a Widget inheriting from GridLayout
  • Load a KivyTiledMap and set the number of rows/columns to the tile map width and height
  • Go through the map and add from kivy.uix.image import Image widgets to the grid

This solution, however, has a couple of problems - it doesn't handle multiple layers, and it doesn't handle disabling the drawing of tiles off the screen. It shouldn't be too bad to extend this class to fit those needs, hopefully.

Creating a Moving Character (Character.py)

One important Kivy aid to know about is from kivy.animation import Animation. Coupled with TiledGrid, it allows calls like this to "just work":

coords = self.map_grid.get_tile_position(self.current_tile.x, self.current_tile.y)
anim = Animation(x=coords[0], y=coords[1])
anim.start(self)

The way this Character widget works is by checking input for keyboard arrow inputs, and then asking the TiledGrid if the move is valid. If it is, then it gets the true screen coordinates of the tile's position and starts an Animation moving to those coordinates.