Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

How to work around ghost edges on tiled maps
Started by arman7 Oct 19 2013 09:18 AM

3 replies to this topic
[TOPIC CONTROLS]
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

arman7

[GLOBAL: userInfoPane.html]
arman7
  • Observer

  • 16 posts
  • Corona SDK

I want to share a solution to a major problem I ran into while developing a platformer game.

 

This week I decided to try my hand at making a platformer in a tiled world, and ran into a BIG issue: ghost edges. Long story short, there is a fundamental flaw in Box2D that sometimes can abruptly stop a polygon (e.g. an avatar) sliding on smooth surfaces (e.g. ground) made of several tiles. This is so bad, it's basically a game killer. It's a well known issue and you can read more about it here:

http://www.box2d.org/forum/viewtopic.php?f=8&t=3292&start=0
http://box2d.org/forum/viewtopic.php?f=3&t=3048&start=0

http://box2d.org/manual.html#_Toc258082970

 

None of the suggested solutions worked for me: cutoff corners from the polygons (still gets stuck), use edge chains (don't have them in Corona), change polygon into circle shape (my avatar is not circular and its collisions look really off with the circle shape).

 

So what finally did work was collision event.contact filtering. The idea is to test if the collision is about to happen between the corner of the avatar and the corner of the adjacent tile below, and if yes then remove the collision:

 

    function avatar:preCollision(event)
        local bottomLeftCornerGap = math.abs(self.view.x - 0.5 * self.view.width - (event.other.x + 0.5 * event.other.width))
        local bottomRightCornerGap = math.abs(self.view.x + 0.5 * self.view.width - (event.other.x - 0.5 * event.other.width))
 
        if bottomLeftCornerGap < 0.2 * self.view.width then
            event.contact.isEnabled = false
        end
        if bottomRightCornerGap < 0.2 * self.view.width then
            event.contact.isEnabled = false
        end
    end


[TOPIC: post.html]
#2

soggybag

[GLOBAL: userInfoPane.html]
soggybag
  • Contributor

  • 256 posts
  • Corona SDK

I think I ran into this problem myself. My situation is different, so using a circular body fixed the problem, to some extent. Using the a circular body caused a couple other issues, so i'm not sure if this solution will work.



[TOPIC: post.html]
#3

soggybag

[GLOBAL: userInfoPane.html]
soggybag
  • Contributor

  • 256 posts
  • Corona SDK

Just to be clear the problem I'm having is where a dynamic body gets stuck along an edge. In my case it's happening where my player object hits a ceiling. The object stops at the ceiling, it can slide along the edge until it hits another edge, but it won't drop down. 

 

Something I notice is that this only happens in some circumstance. I have a tile based environment. If the player is jumping and hits a tile that's three tiles above, there's no problem. If the tile is two tiles above then the problem occurs and the player is stuck to the ceiling. 

 

This is giving me the idea that the problem is effected by the velocity. I'm guessing that if the object moves fast enough so the objects overlap, internally to physics, then there's a problem. If physics moves the objects so that they don't quite meet then there's no problem.

 

Hopefully this all makes sense, here's a couple pictures. In the first picture you can see the orange "player" object stuck to the tile above. In the second image the player object is not getting stuck to the wall above it. Notice the difference in distance. When the distance is two tiles problem, three tiles no problem. I suspect that the problem might occur or not occur at different distances depending on other physics settings.  

 

Screen-Shot-2013-12-29-at-5.38.09-PM.png

Screen-Shot-2013-12-29-at-5.37.57-PM.png



[TOPIC: post.html]
#4

RagdogStudios

[GLOBAL: userInfoPane.html]
RagdogStudios
  • Contributor

  • 144 posts
  • Corona SDK

You can also (if you use a grid system, keeping tables with all your tiles) work it out so that only one physic body is automatically created for a set of tiles. So for example a long row of tiles will end up being just one physic body, with no edges at all.
This should also improve performance a bit.

The preCollision system works, but it might hinder performance a bit, since preCollision events keep on firing for several time at each upcoming collision.

As soon as I get some time I'll probably do a more in-depth tutorial, but basically you can cycle through your tiles, keeping going as long as the next tile is of the same type as the first, and then use the first tile and the last tile x/y positions to create a single shape for a single physic body.
You can see it in action here: 




[topic_controls]
[/topic_controls]