2

I am currently using box2d physics engine in java in libgx, and i am facing problems with collisions. The problem is that the body stops moving, and a collision point appears while on a flat area. The way im working is i am making multiple bodies, each representing a block, and those blocks are side-by-side. Look at the collision point here:

enter image description here

the body should not collide here for the Y coordinate of the bodies is equal, and their side is equal as well.

float PPM = 100;
float side = 45;
     for (float i = start; i < end; i++) {
        /**
         * perlin noise for terrain
         */
        def.type = BodyDef.BodyType.StaticBody;
        float place = Maths.map(noise.noise(off, off), 0, 1, -10, 50);
        if (place < 10) {
            place = 0;
        } else if (place < 20) {
            place = side;
        } else if (place < 30) {
            place = side * 2;
        } else if (place < 40) {
            place = side * 3;
        } else if (place <= 50) {
            place =  side * 4;
        }


        place += side / 2;

        float posx = (i * side);
        float posy = place;
        float size = side / 2f;
        def.position.set(posx / PPM, posy / PPM);
        b = world.createBody(def);
        shape.setAsBox(size / PPM, size / PPM);
        fdef.shape = shape;
        fdef.isSensor = false;
        b.createFixture(fdef);
        off += 0.01;
        toSetLast = posx + side;

        GrassBlock grass = new GrassBlock(b, new 
        Vector2(b.getPosition().x * PPM, b.getPosition().y * PPM));
        //dirt under grass
        for (float j = (place / side) - 1; j >= -1; j--) {
            posy = j * side;

            def.position.set(posx / PPM, posy / PPM);
            b = world.createBody(def);
            shape.setAsBox(size / PPM, size / PPM);
            fdef.isSensor = false;
            fdef.shape = shape;
            b.createFixture(fdef);
            DirtBlock dirt = new DirtBlock(b, new 
            Vector2(b.getPosition().x * PPM, b.getPosition().y * PPM));
            addBlock(dirt.getLocation(), dirt);
        }
        addBlock(grass.getLocation(), grass);

    }
CraigR8806
  • 1,584
  • 13
  • 21
Liwaa
  • 35
  • 9

2 Answers2

2

I believe what you're experiencing is a known short-coming of the Box2D library.

See What could cause a sudden stop in Box2D? for another write-up of this problem. See Box2D C++ tutorials - Ghost vertices for an explanation of what's going on and what you can do to mitigate the problem...

Basically, use a chain-shape for the ground like texture instead of polygons (or over the polygons) so your moving block actually moves on top of the chain. That assumes the version of the java box2d implementation you're using has the chain shape in it that provides "ghost vertices" support.

Under the hood details...

While from the user's perspective chain shapes provide smoothing, under the hood, it's edge shapes that get used to do the smoothing. Edge shapes do this with two special extra vertices (in addition to the expected two of an edge). When the library is evaluating a contact between a chain shape and a polygon (or a circle), it does that by identifying the segment of the chain that the contact could be occurring with. It then translates that chain segment into an edge with its extra vertices set to the adjacent vertices in the chain. And then the contact is evaluated between that translated edge and the polygon (or circle). This occurs automatically with chain shapes and there's no option in chain shapes that is used to gain this behavior.

A user could achieve the same results as achieved with chain shapes by stitching together edge shapes for all the segments of the chain and setting all of the edges' extra vertices to the logically adjacent vertices. That uses significantly more memory than the chain shape however and requires the user to write more code to do (at least for chains having more than two vertices).

Louis Langholtz
  • 2,913
  • 3
  • 17
  • 40
  • I will try this tonight, and get back to you. Although, Would this still work if i kept the box2d body as a polygon, but made that polygon with a chainshape? – Liwaa Jun 01 '17 at 04:02
  • @Liwaa Chain shape is meant for arbitrary non-solid shapes. Also the chain (and edge) shapes aren't meant to be used for dynamic bodies. If you were using C++ (instead of Java) you could try out [my fork of Box2D](https://github.com/louis-langholtz/Box2D) that supports dynamic chain and edge shapes and polygons sliding over polygons. My fork isn't ported to Java though. So it's no use to you. Incidentally, I have [a write-up of this sticking problem and how I solved it in my fork](https://github.com/louis-langholtz/Box2D/blob/dev/Documentation/CollisionHandlng.md) if anyone's interested. – Louis Langholtz Jun 01 '17 at 15:00
  • @LousLangholtz it managed to work with the chain shape perfect, i first had problems with the chain shape, then they managed to work. Thanks! – Liwaa Jun 02 '17 at 06:50
2

Although Louis Langholtz's answer is already good, I have more to add.

Chain or Ghost vertices are generally recommended approaches but :-

  • It is hard to use in practice.
  • It requires coder to manually joint those edges/corners together.
    (tedious in some scenario)

I recommend beveling the box instead :-

enter image description here

I have tested (jbox2d) - it can reduce the effect from the glitch significantly.
The disadvantage of this approach is that it demands additional vertices.
(e.g. 4 vertices -> 8 vertices )

Thus, it demands more computational power.

Therefore, in practices, I generally divide all bodies into 2 groups :-

  • OK to have glitch (e.g. debris) -> don't modify (cheap)
  • Can't have glitch (e.g. character) -> use beveling approach (more expensive)

Personally, I hope there is an easy way to use chain/ghost as Louis Langholtz recommend, though.

javaLover
  • 6,347
  • 2
  • 22
  • 67
  • i understand that i should make the edges curved of the polygon? how can i do that with polygon shape? @javaLover – Liwaa Jun 01 '17 at 10:55
  • @Liwaa Yes. It is not particularly hard. You may need some time to ponder about it. Here are some similar thingy that may give you some rough ideas. https://www.youtube.com/watch?v=3qMNuoTHNHs and http://doc.cgal.org/latest/Straight_skeleton_2/index.html – javaLover Jun 01 '17 at 11:05
  • Thanks for all the help, i appreciate it :) – Liwaa Jun 01 '17 at 12:05
  • @javaLover Yes, I agree, adding beveling is also a mitigating option. The tutorial I linked calls that "clipping polygon corners". Not sure what the java port you're using looks like w.r.t. chain shape support but the underlying Box2D C++ code for chain shapes (at least in Box2D 2.3.2) handles the ghost vertices for the user. If one were to stitch Edge shapes together however then the user would have to setup the extra vertices manually then (but not for chain shapes, just edge shapes). – Louis Langholtz Jun 01 '17 at 15:06
  • Incidentally, in terms of the chain-shape-as-the-ground vs. beveling-the-box, I've found that sliding is smoother with the chain-shape. Personally though, while the chain-shape solution seems to slide better, I dislike the use of the extra vertices in both solutions and the use in chain/edge shapes does philosophically seem more contrived than in the beveling option. In my solution to this problem (in my fork) I chose to eliminate it entirely at the collision manifold level where whats returned for overlapping shapes was already acknowledged to be part artfulness anyway. – Louis Langholtz Jun 01 '17 at 15:24
  • @LouisLangholtz The problem was fixed by creating the blocks with a chain shape . – Liwaa Jun 02 '17 at 06:48
  • @Louis Langholtz I am appreciated your knowledge and experience, and thank for sharing. I agree with everything, but still has a few questions :- 1. Does your fork create (hacky) chain automatically? If not, the user has to specify mode of a certain chain whether it iss just-for-hack or a normal chain, correct? 2. "eliminate it entirely", does "it" mean the (hacky) chain-edge? – javaLover Jun 02 '17 at 10:38
  • @Liwaa Nice to hear that. Is it easy for you? It is a subjective question. If you say yes, I will give it another try. I actually feel a little bad about adding more vertices. XD – javaLover Jun 02 '17 at 10:45
  • @javaLover i found it easy creating the chain shape, i didn't add more vertices, it was a chain shape with 4 vertices to be just like a polygon shape set as a box – Liwaa Jun 02 '17 at 19:47
  • 1
    @javaLover It sounds like there may be some confusion. Sorry about that. I've updated my answer in the hopes that the edit makes matters clearer. As for my fork of the Box2D library, I changed how the contact was being evaluated so that smooth sliding can occur between any two kinds of shapes and without any need of extra vertices from edge shapes or any other shapes. Since there's no longer need of extra vertices, I removed those from the edge and chain shapes to cut down on the memory usage. Whether what I did is more or less of a hack you'll have to decide, but I do like the change better. – Louis Langholtz Jun 04 '17 at 21:56