Player geom 'tripping' over tile geoms

Topics: Developer Forum, User Forum
Nov 25, 2009 at 8:11 AM

Hello, I have an issue similar to http://farseerphysics.codeplex.com/Thread/View.aspx?ThreadId=72364

 

I have a rectangle player geom, and many rectangle tile geoms lined up next to each other.

 

Occasionally when the player geom is crossing between them he seems to clip onto the corners of the tile geom and as a result rotate over.

 

Is there any fix for this?

Coordinator
Nov 25, 2009 at 6:10 PM
Edited Nov 25, 2009 at 6:11 PM

Enginewise there is not a lot to do about this. It is really in the nature of the engine to do stuff like that, so it is perfectly normal. However, I've tried to detect the situation and correct it, but there is not a lot that can be done. You have to remember that the engine looks at a single geometry at the time and thus it has no idea about when such a situation happens.

One solution that is guaranteed to work is to use raycasting for the transportation of your geometry along multiple geometries or reduce the problem by using a ball as the "feet" and then apply torque to the ball whenever you need to move the character.

Edit: You can also see that slapgw used the ball solution.

Nov 25, 2009 at 7:07 PM

I had a similar problem in my tile engine and fixed it by checking if there where more then one tile connected on the same row and created a long geom to cover all these tiles instead of creating a single geom for each tile.

Nov 25, 2009 at 7:40 PM
Edited Nov 25, 2009 at 11:14 PM

It's a shame I have to use a hack for this.. I really don't want to have two separate geometries for one body because I'll have so many of them  

 

As a test I made my player geom into a Circle but it still trips!

 

Ray casting is a bit much for this project

Nov 28, 2009 at 7:04 PM

I wouldn't say it's a hack. That's just how it works. In real life if a cube its and bump or crack it rotates. Anyways you don't need two separate geometries for one body. Keep everything the same but use a circle. I don't understand how your circle is tripping. The only thing I can see is that you don't have enough edges. They aren't perfect circles (though from what I've read, they will be in Farseer Physics 3.0). You have to either add more sides to it or just deal with a little tripping. 

Nov 28, 2009 at 9:57 PM
sonic4305 wrote:

I wouldn't say it's a hack. That's just how it works. In real life if a cube its and bump or crack it rotates. Anyways you don't need two separate geometries for one body. Keep everything the same but use a circle. I don't understand how your circle is tripping. The only thing I can see is that you don't have enough edges. They aren't perfect circles (though from what I've read, they will be in Farseer Physics 3.0). You have to either add more sides to it or just deal with a little tripping. 

I'm happy with making it a circle, however when I do I need that tripping to not be there! It happens frequently and interferes with gameplay (jumping etc)

Here is a screenshot with the player geom as a rectangle

 

http://notspike.com/PrototypeG/trip.png

Please let me know if there's anything missing with the circle geom, I tried it with a small number of sides to a large number

Nov 28, 2009 at 11:16 PM

Well how does it trip as a circle? A video would be helpful. You can use camstudio to get that.

Nov 28, 2009 at 11:59 PM
Edited Nov 29, 2009 at 1:37 AM
sonic4305 wrote:

Well how does it trip as a circle? A video would be helpful. You can use camstudio to get that.

Hi I used CamStudio to take a video of an occurrence of the problem using a circle with 30 points as the player geom.

 

http://www.notspike.com/PrototypeG/trip.avi

 

You see a few little 'trips' and then a big one towards the middle! Thanks for recommending the software

Nov 29, 2009 at 2:59 PM

Hi, I've got an idea!

 

Seeing as this is only a problem when a body is static, is there a way to iterate through all geoms in the geomlist marked as static and merge those geoms together? If a geom intersects another one, get them to merge into one geom but still retain the bodies so that when they are turned to isstatic = false, the individual geoms can be re-generated on the fly?

 

I had a play about but I couldn't figure it out. Also I don't know how to get the width/heigh the bodies/geoms were created with from existing body/geom objects!

I can set my geoms to be slightly larger than intended so that they intersect by one pixel to get the merging to work.

Nov 29, 2009 at 9:05 PM

As I said before, I solved this problem by creating larger geoms where my level have many tiles next to each other on the same row.

Arrows in this picture is one geom each

http://www.specop.se/superspace_editor.jpg

 

Nov 29, 2009 at 9:09 PM

That's great Panzer, but how did you detect it and how did you create larger geoms? Can you please share the code?

Nov 30, 2009 at 3:48 PM
Depending of course on how you save your level and all that but my code looks something like this:
b_level[] and g_level[] is two arrays with all the geoms and bodys for the current level, they have been created before this code.

for (int i = 1; i < world.levelSizeY - 1; i++)
{
    row = 0;
    for (int j = 1; j < world.levelSizeX - 1; j++)
    {
        if ((level[i][j] & 0x100000) == 0x100000) //Collision == True
        {
            row++;
        }
        else
        {
            if (row > 0)
            {
                b_level[total] = BodyFactory.Instance.CreateRectangleBody(Physics.physics, World.blockSize * row, World.blockSize, 1.0f);
                g_level[total] = GeomFactory.Instance.CreateRectangleGeom(Physics.physics, b_level[total], World.blockSize * row, World.blockSize);
                b_level[total].Position = new Vector2(j * World.blockSize - (16 * row) - 1, (i + 1) * World.blockSize - 16);
                row = 0;
                total++;
            }
        }
    }
    if (row > 0)
    {
        b_level[total] = BodyFactory.Instance.CreateRectangleBody(Physics.physics, World.blockSize * row, World.blockSize, 1.0f);
        g_level[total] = GeomFactory.Instance.CreateRectangleGeom(Physics.physics, b_level[total], World.blockSize * row, World.blockSize);
        b_level[total].Position = new Vector2((world.levelSizeX - 1) * World.blockSize - (16 * row) - 1, (i + 1) * World.blockSize - 16);
        row = 0;
        total++;
    }
}
total++;
}
Nov 30, 2009 at 3:53 PM
Edited Dec 2, 2009 at 12:06 PM

Hey Panzer thanks for your code I really appreciate it, I will have a chance to try implement it and see if it works for me in a day or two.

UPDATE: unfortunately your solution isn't best suited for my game panzer, I did however finish my one and it works fine.

 

 

Thanks everyone.

 

Dec 2, 2009 at 3:18 PM
Edited Dec 2, 2009 at 3:21 PM

I think I see one possible problem. I see that your character can jump at anytime which is fine if you want it like that but you have movement on the player as he is in the air to push him back if he goes off an edge. It looks to me that you are applying an impulse on the circle as well as rotating the circle. This is going to cause skips and jumps as the rotation can't keep up with the applied impulse and then when friction come in, it skips. You need to make sure that impulse on the circle doesn't occur when you are on the ground. One way of checking this is to just put a small line segment underneath the character that only can respond with telling you whether it is colliding with something or not. You can see it on my character below.

 

(Don't mind the character off center. Issue I was having that is now resolved.)

 

!!EDIT!!

Looking back at the video, it doesn't even look like you rotate the circle. Implement what I told you so you can move still in air but don't apply an impulse when on the ground. That's why it skips. You need to rotate the circle.