Designing a multiplayer game with Python and cocos2d, part 2 -- Building a scrollable map


Skip to: Part 1, Part 2.

In part 1, we set up the basics of a cocos2d game and created a movable player object. In part 2, we'll create a scrollable map using the cocos.tiles module.

1. Creating a tile map

In cocos2d, a tile map needs at least three files:

  • a spritesheet containing the underlying tiles that will make up the map.
  • a tile definition file that defines the borders of each sprite in the spritesheet, and assigns those sprites to a set of tiles.
  • a map definition file that arranges tiles into a map.

In the repository for this tutorial, we've placed each of these files (tilemap.png, tiles.xml, and map.xml) in the tiles directory.

I created a custom spritesheet using GIMP, but you can easily find freely available spritesheets online. Sprite Database is a great place to get started.

The definition files can be in one of two formats: TMX, or the cocos2d XML file specification. I used the latter and created the XML files manually, but TMX is also a fine choice. There are many free tile map editors available, including Tiled, which creates maps in the TMX format.

2. Creating the map layer and scroller object

Before we do anything, we'll first want to import the tiles module:

from cocos import tiles

Next, we'll create a map layer. In Part 1, we created a layer object called player_layer and added one object: the player sprite (called me). To put our player on a map, we'll want to create a second layer object for our map. We'll use the tiles module to automatically populate this layer with tiles (as defined in our .xml files), using sprites from our map spritesheet.

map_layer = tiles.load('tiles/map.xml')['map0']

In map.xml, you can create multiple map definitions, each with a unique ID. In our example map.xml, we created just one and gave it the ID 'map0', so we use that ID as the index when creating the map layer.

Note that we only need to reference map.xml, not tiles.xml or tilemap.png, within our python code. map.xml provides the reference to tiles.xml in the first line -- <resource><requires file="tiles.xml" /> -- and tiles.xml provides the reference to tilemap.png in the third line -- <imageatlas size="32x32" file="tilemap.png">

Next, we'll create a ScrollingManager object.

global scroller

scroller = layer.ScrollingManager()

The ScrollingManager manages layers for us -- it allows us to convert 'world' coordinates to 'screen' coordinates. Consider 'world' coordinates relative to the map, such that the top left corner of the map is at World(0,0). The 'screen' coordinates are relative to what's actually being displayed on the screen, such that the top left corner of the game window is always at Screen(0,0). If our game starts out at the top-left corner of the map, then Screen(0,0) and World(0,0) will refer to the same point. However, as the player moves around, the world will shift such that a different portion of the map appears at Screen(0,0).

Once our scroller object has been created, we'll add our map and player layers to it. We'll also modify our main_scene object to set the initial layer to the scroller object.

# Add map and player layers.
scroller.add(map_layer)
scroller.add(player_layer)

# Create a scene and set its initial layer.
main_scene = scene.Scene(scroller)

One last thing to do. In our step function within our player class, Me, we'll add a call to the set_focus method of our ScrollingManager object. This call tells the ScrollingManager to scroll all layers to "center" around the point to which the player is moving, to the extent that the map boundaries allow.

scroller.set_focus(self.target.x, self.target.y)

That's it! If all works out, we should see the map appear underneath the player sprite. We should be able to move around and have the map and player layers scroll accordingly.

Output of main.py

3. Full code