Jump to content

Creating collision polygons on tiles in Tiled mapeditor


locohost
 Share

Recommended Posts

My game is top-down with the player fixed in the middle. I do have a Tiled JSON data file loading fine in my game and I have a "player" sprite moving around and colliding with the tiles, but it's colliding with the clear areas around the walls, not the actual solid bits.

 

Can someone point me to a tutorial that shows how to create collision polygons in Tiled Map Editor? I've been fiddling with an Object Layer and the Collision Editor but nothing actually happens. Meaning, I can "fiddle" with the collision editor but see no way to save the polygons I'm drawing around the tiles so I can export the data into a Tiled JSON file.

 

Then how do I define a collision polygon for my player? It's not a square and has a lot of clear bits too.

 

My searching has been pretty unproductive so far :-/

 

Thanks a lot for helping :-) 

 

 

Link to comment
Share on other sites

@valueerror Thanks for posting. I think I saw your old post. However I didn't get that zip file. I'll try that shortly.

 

I think I have everything setup and (mostly) working as expected. All but the tile collisions. Here is my code that I believe exactly matches your example...

create: function () {        this.game.stage.backgroundColor = '#EAEAEA';                var map = this.game.add.tilemap('WallsTileMap'); // Preloaded tilemap        map.addTilesetImage('OfficeWalls', 'WallsTilesetImg'); // Preloaded tileset        this.game.physics.startSystem(Phaser.Physics.P2JS);        // If you use 'collide' function with the layer, then the tiles from the first (ID 0) tile till         // the 100th element will collide with the other sprite                //this.map.setCollisionBetween(0, 100);         ball = this.game.add.sprite((SCREEN_WIDTH / 2) + 250, (SCREEN_HEIGHT / 2), 'blueBall');        ball.frameName = "00-ball-blue-up.png";        this.game.physics.p2.enable(ball);        // This is the default name of the first layer in Tiled        var layer = map.createLayer('WallTiles');         var mapObs = this.game.physics.p2.convertCollisionObjects(map, "WallObjects");        console.log('mapObs = ', mapObs);        // Sets the world size to match the size of this layer.        layer.resizeWorld();         // The camera will follow the player in the world        this.game.camera.follow(ball, Phaser.Camera.FOLLOW_TOPDOWN);        cursors = this.input.keyboard.createCursorKeys();},

I used the polyline tool in Tiled to trace around my wall tiles and saved/exported as JSON. The JSON file loads and the walls display and the player moves around but the tile collisions don't happen. At the console.log line above, mapObs = []. So I guess this means p2.convertCollisionObjects is failing and Tiled collision objects aren't loading. The Tiled objects layer is definitely called "WallObjects". I do see all the data exported in the JSON file so I'm pretty stumped here.

 

I think in one of your other posts you or another poster mentions completing/connecting the end of the polyline "exactly" or "precisely". I tried as best I could to exactly connect the ends of the polylines but this is pretty tiny on the screen even way magnified. Could this be my issue?

 

Thank you very much for any advice :-)

 

Mark

 

Link to comment
Share on other sites

Well, it's better, but still not fully working. I edited my code so it matches what you have in the zip file. Collisions with the tiles do happen, but at the full outer edge of each tile, not at the polyline edge. Not sure what I'm missing. Here is the new code...

create: function () {        this.game.physics.startSystem(Phaser.Physics.P2JS);        this.game.stage.backgroundColor = '#EAEAEA';                var map = this.game.add.tilemap('WallsTileMap'); // Preloaded tilemap        map.addTilesetImage('OfficeWalls', 'WallsTilesetImg'); // Preloaded tileset        // This is the main layer in Tiled        var layerWalls = map.createLayer('WallTiles');         // Sets the world size to match the size of this layer.        layerWalls.resizeWorld();         // Here we use a different approach - we activate the potential collision for all                 // The camera will follow the player in the world        map.setCollisionBetween(0, 14, true, 'WallTiles');        // In p2 physics you will have to create physics bodies out of the tiles..          // tiles that touch each other will create one big physics body instead of several small ones         // convertTilemap will create an array of all physics bodies         var lyrWalls = this.game.physics.p2.convertTilemap(map, layerWalls);                  // This converts the polylines of the tiled - object layer into physics bodies.. make sure to use the         // "polyline" tool and not the "polygon" tool - otherwise it will not work!!        // these polyline physics bodies will not be visible - so make sure you paint your hills and slanted         // tiles on a layer that acts as background (without collision enabled)        var collsnObs = this.game.physics.p2.convertCollisionObjects(map, "WallObjects");           // Create the player sprite        ball = this.game.add.sprite((SCREEN_WIDTH / 2) + 250, (SCREEN_HEIGHT / 2), 'blueBall');        ball.frameName = "00-ball-blue-up.png";        this.game.physics.p2.enable(ball);        this.game.camera.follow(ball, Phaser.Camera.FOLLOW_TOPDOWN);        cursors = this.input.keyboard.createCursorKeys();},

Can you see my mistake?

 

NOTE: In my JSON, most the X/Y and Size values are decimals. Like 0.02222 or 15.9777 and so on. I noticed in your JSON they are all integers. Did you hand edit them all to be integers and does this even matter?

 

Thanks again  :)

Link to comment
Share on other sites

Well, this appears to working decent right now. I ran into some problems with how Phaser was handling collisions between the player and walls. My original walls tiles were thin graphic lines within large 32x32 pixel tles. The collisions would work correctly in some locations at some tiles and then completely different at the exact same tiles in other locations. The player would collide with completely empty space! This, of course, made zero sense. I'm going to assume this is a bug in Phaser code p2.convertCollsionObjects() that builds the collision polygons.

 

To work around this, I rebuilt the tileset with much smaller, 8x8 pixel wall tiles. Now there is very little (just 1 pixel) clear space between tile edge and the actual wall graphic. So far, this seems to be working well. Here is the new code...

    create: function () {        this.game.physics.startSystem(Phaser.Physics.P2JS);        this.game.stage.backgroundColor = '#EAEAEA';                var map = this.game.add.tilemap('WallsTileMap');        map.addTilesetImage('walls', 'WallsTilesetImg');        // This is the main layer in Tiled        var layerWalls = map.createLayer('WallTiles');         // Sets the world size to match the size of this layer.        layerWalls.resizeWorld();         // Here we use a different approach - we activate the potential collision for all                 map.setCollisionBetween(0, 14, true, 'WallTiles');        // In p2 physics you will have to create physics bodies out of the tiles..          // tiles that touch each other will create one big physics body instead of several small ones         // convertTilemap will create an array of all physics bodies         var lyrWalls = this.game.physics.p2.convertTilemap(map, layerWalls);                  // This converts the polylines of the tiled - object layer into physics bodies.. make sure to use the         // "polyline" tool and not the "polygon" tool - otherwise it will not work!!        // these polyline physics bodies will not be visible - so make sure you paint your hills and slanted         // tiles on a layer that acts as background (without collision enabled)        //var collsnObs = this.game.physics.p2.convertCollisionObjects(map, "WallObjects");           // Create the player sprite        ball = this.game.add.sprite((SCREEN_WIDTH / 2) + 0, (SCREEN_HEIGHT / 2), 'blueBall');        // Must enable physics on the ball immediately after creating it        this.game.physics.p2.enable(ball);        ball.frameName = "00-ball-blue-up.png";        //ball.body.clearShapes();        // The second param in body.loadPolygon must match name in the physics JSON file        //ball.body.loadPolygon('ballPhysicsData', 'ball-blue');        ball.anchor.setTo(0.5,0.5); // set the anchor to the exact middle of the player (good for flipping the image on the same place)        this.game.camera.follow(ball, Phaser.Camera.FOLLOW_TOPDOWN);        ball.body.setCircle(31,0,0);  // instead of a rectangle i want a circle (radius, offsetX, offsetY)        ball.body.fixedRotation = true;  // in p2 rotation is possible.. i don't want this on my player         cursors = this.input.keyboard.createCursorKeys();    },

This new tileset has no collision objects layer. Note the physics.p2.convertCollisionObjects(...) line above is not even used in the new code and tileset.

 

What are you thoughts on my bug mentioned above?

 

Link to comment
Share on other sites

you are clearly not using convertcollisionobjects anymore and therefore no polylines at all..  actually i do not get what you are doing here..  i thought you need polylines because you want to get rid of the square tile collision areas...

but if it works for you now.. good...  if you don't need slanted tiles everything should be fine...

 

i never experienced a bug with polylines..  in my current game i use tiled only to create the world with all the tiles from my tileset but i never actually activate collision on any of these tilelayers.. they act as background only..  collision is handled entirely through an object layer with the weirdest shapes painted with polylines.. and all of them work - thin or thick...   

 

do you have a working example online to see what you are actually on?

Link to comment
Share on other sites

i created one normal tilemap layer and "painted" my gameworld with all the different tiles (slanted, rectangular, etc) on it (placed the tiles on the raster) - this tilemap layer is displayed in my game but no collision on any tiles is activated. it acts as background only.. if i would activate collision on it all collision areas would be rectangles and tiles that don't fill up the entire rectangle would have collision areas that don't fit at all

 

then i created an object layer in tiled and painted polylines around those areas of my gameworld which should collide (as you can see in the example in the zip file i provided)

 

in the example i actually activated collisions on 2 of the 3 tilemap layers but i don't do this anymore because my tiles are not squares most of the time

Link to comment
Share on other sites

i guess you have tiles that look a little bit like this:  (where the # hashtag would be the wall and the rest is transparent ? 

|------#----------|

|       #            |

|       #            |

|       #            |

|------#----------|

 

 

if so.. aren't you afraid that your player will occasionally "slip" through the wall?    i had slipthroughs with walls that are 32px in size (if the speed of the object was high enough)

Link to comment
Share on other sites

You are wise indeed my friend  :)

 

Yes that's exactly what my "wall-vert" tile looks like. I had 32x32 tiles basically working at one point but then I started getting some erratic collisions. Including bouncing off invisible walls in the middle of a room where no wall existed and also... "slip throughs" exactly like you mention above.

 

Do you have any thoughts on these issues? Are they Phaser bugs then? I'm guessing there is one or more bugs in physics.p2.convertCollisionObjects(...).

Link to comment
Share on other sites

this isn't a bug in convertCollisionObjects.. this functions works as expected (at least i didn't find a bug yet)

 

 in fact .. this isn't a bug at all..   

 

 

i have the same problem with a game of mine where my collision areas are 32 pixels in width but if the speed of the object is to high it will just tunnel through the collision area..    think of an object with 1px diameter moving in 40px steps every frame: lets say its on pixel 125 - the object starts on pixel 128 and ends at pixel 160 - (so no collision yet) in the next step the object will be at pixel 165 and again .. no collision happened...

 

http://www.stencyl.com/help/view/continuous-collision-detection/

 

i believe there already are threads about CCD in this forum ... i have to look for myself if this is somehow possible but i guess it's very heavy on performance..

 

a possible solution that comes to my mind:

maybe it would be better to use walls >= 32px .. slower and bigger objects and maybe just scale the whole world ??

Link to comment
Share on other sites

actually..  this is something we need to investigate further..  i just made a test where i placed a 32 px wall with several 32x32 objects which i created from tiled   AND a 32 px wall with a long polygon shape i created from tiled..

 

i have a function in place that restricts the speed of the test object to 150 (this ought to be meters not pixels)  and there is no way i can get the testobject through the wall made of 32x32 px objects..  the testobject actually goes into the wall and is then corrected and pushed back out of the wall in the right direction..   i need at least a speed of 250 to tunnel through this wall and its still hard to reproduce..

 

the polygon wall on the other hand is really bad..  150 is enough to tunnel through almost every time... 

 

this sounds like we should file an issue on github ?!?

Link to comment
Share on other sites

  • 1 month later...

i did open an issue on github but it seems schteppe has nothing to say to this..

https://github.com/schteppe/p2.js/issues/136

 

i know about the tiled plugin but i don't think this will solve this problem because it uses the same p2 / phaser functions 

its nice and probably faster than the original implmentaition but the tunneling problem happens after the objects and/or polygons are created so i'm quite certain that this is a p2 issue..   

 

without continuous collision detection the problem wil ALWAYS be there.. the problem i found (objecs vs polygons) is a different one..  it should behave in the same way but it doesn't

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

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