Jump to content

Phaser Tilemap: Make some layers collide on all sides, others only on the top


praine
 Share

Recommended Posts

I'm a newbie with Phaser tile maps. I've created a simple Mario-esque platform game where the player can jump around and land on platforms. This all works fine, but now I'm trying to add some "walls" to the level which the player should not be able to pass through horizontally, and can't figure out how to get this behavior working (see attached illustration for better explanation)

Here's the code I'm using to read the tilemap data and set up collision:

pf.map = pf.game.add.tilemap('level2');

	    //the first parameter is the tileset name as specified in Tiled, the second is the key to the asset
	    pf.map.addTilesetImage('tiles_spritesheet', 'gameTiles');

	    //create layers
	    pf.blockedLayer = pf.map.createLayer('blockedLayer');
	    pf.walls = pf.map.createLayer('walls');

	    //collision on blockedLayer
	    pf.map.setCollisionBetween(1, 5000, true, 'blockedLayer');
	    pf.map.setCollisionBetween(1, 5000, true, 'walls');

The "walls" layer should collide with the player on all sides, and the "blocked" layer should only collide on the top. Currently both the "walls" layer and the "blocked" layer are colliding with the player only on the top.

Any help or advice very much appreciated!

 

Screen_Shot_2017-01-24_at_7_37_39_PM.png

Link to comment
Share on other sites

Hi all, quick update.

I've partly solved the issue.. I figured out the reason the player avatar wasn't colliding with the wall was because I was directly manipulating its x coordinates rather than using velocity (as per this thread).

However, now I have the opposite problem: the player is colliding horizontally with parts of the blocked layer as well as the wall layer. I found a function that allows one-way (vertical only) collision on a specific layer, but it requires a list of tile IDs that I'm not sure how to get. I just want the player to collide ONLY vertically (down) with any non-blank tile on the blocked layer.

Thanks in advance

 

Link to comment
Share on other sites

You're not the first struggling with tile id's for collision. I set collision settings per tile in Tiled editor and update collision after loading the layers. You can select multiple tiles at once and set properties. I think this nicely wrapped as something like "implementTileProperties(layer)" would be a nice addition to Phaser 3 @rich .

This is taken directly from something I work on. I load the tilemap into "map" and the "layer" variable holds the layer I want to check for collision on. This imports all kind of properties (like alpha or whatever) so be careful or limit it to what you're interested in. "map.calculateFaces(1)" might need an explaination. It's an internal function to calculate "interesting faces" and the number 1 is the index for the layer on the map. You can check what index you have with a loop over "i" of "map.layers.name === layer.name" and calculate faces for matching i, or just do it for all layers (if it's in the create method it shouldn't be an performance issue).

        for (let y = 0; y < layer.layer.data.length; y++) {
            for (let x = 0; x < layer.layer.data[y].length; x++) {
                let tile = layer.layer.data[y][x];
                if (tile.index === -1) {
                    continue;
                }
                for (let property of Object.keys(tile.properties)) {
                    if (tile.hasOwnProperty(property)) {
                        tile[property] = tile.properties[property];
                    }
                }
                if (tile.properties.collide) {
                    for (let property of ["collideUp", "collideRight", "collideDown", "collideLeft"]) {
                        tile[property] = true;
                    }
                }
            }
        }
        map.calculateFaces(1);

 edit: An alternative method is to loop through "game.cache._cache.tilemap.map.data.tilesets[0].tileproperties" (if the map is loaded as "map" and you're interesting in the first tileset) and use Phaser API to update tiles with matching gids/ids. If I remember right the Tiled set the first tile gid to 1 while Phaser set it to 0 which can cause som confusion. 

Link to comment
Share on other sites

Hi @nkholski, thanks very much for your reply.

I figured out how to get the tile index from Tiled (see attached image) and then I figured out that this number (index) applies to ALL tiles of the same type, which makes things a lot easier, so I can target all "platform" type tiles in one go. As you said, you have to add 1 to the index reported in Tiled to make it work. However, I still can't quite figure out how to access one specific tile and change its sprite image/opacity or destroy it, etc.

Any further help greatly appreciated.

Screen_Shot_2017-01-25_at_1_46_35_PM.png

Link to comment
Share on other sites

Edit: Using getTile from the API is probably a much better idea: http://phaser.io/docs/2.4.4/Phaser.Tilemap.html#getTile

Change alpha to 0.5 on the tile at x,y on mylayer (untested, but I think it should work):

mylayer.layer.data[y][x].alpha = 0.5;

See examples.phaser.io for examples on how to put tiles and possible other cases like changing alpha/opacity.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...