Circular or Other Shaped Borders

Topics: Developer Forum, Project Management Forum, User Forum
Apr 17, 2008 at 12:40 AM
I'm very new to Farseer, but I've my code for a game that will place objects on a map and move them. What I want to know is, is it possible to create a border that is a circle or even another shape. The demos show creating a rectangle border by creating 4 rectangles around the area. Obviously this isn't really possible with a circle. My thoughts are to declare a polygon in reverse order so the inside is usable, but I bet there is easier way. Is there some function that makes the body or geom of a circle that is static hollow? Thus making it so the edge of the circle is where collision occurs. Thanks in advance.
Apr 17, 2008 at 6:15 AM
Edited Apr 17, 2008 at 6:16 AM
Haven't tried it, but a nice bet is that GeomFactory.Instance.CreateCircleGeom() is creating a hollow circle the same way as a polygon shape (CreatePolygonGeom) is just a bunch of points with lines between each other.
Apr 17, 2008 at 9:31 PM
Yeah, I thought that too, but when I try to position some stuff inside the circle it gets pushed to the outside edge with CreateCircleGeom.
Coordinator
Apr 18, 2008 at 4:36 PM
polygons and circles are not "hollow" they are solid and will push objects out. To do what you want you sould need to create a circle like you would create, for instance, the letter C except you would need to close the open part.

Apr 18, 2008 at 8:36 PM
Edited Apr 18, 2008 at 8:45 PM
Hey, you would have to simulate a hollow object using other bodies as the border, similar to the Border class. For a circle, this is easy, as you can create two concave semi-circle polygons that mirror each other to form the circle.

As a quick example, the following class will roughly define a concave semi-circle point list.


public class BoundsExample
{
/// <summary>
/// Create a concave semi-circle list of points.
/// </summary>
/// <param name="radius">Radius of the semi-circle.</param>
/// <param name="numberOfEdges">Number of semi-circular edges (circle smoothness)</param>
/// <returns>In order collection of polygon vertices.</returns>
public static Vertices CreateConcaveSemiCircle(float radius, int numberOfEdges)
{
float stepSize = (float)Math.PI / (float)numberOfEdges;

Vertices points = new Vertices();
points.Add(new Vector2(radius, 0));

for(int i = 1; i < numberOfEdges + 1; i++)
{
points.Add(new Vector2(radius * Calculator.Cos(stepSize * i), -radius * Calculator.Sin(stepSize * i)));
}

points.Add(new Vector2(-radius, -radius));
points.Add(new Vector2(radius, -radius));
points.Add(new Vector2(radius, 0));

return points;
}
}


If you add the following code into one of the demo screen Load methods you will create two polygons based on the semi circle points rotated in different directions. You should get close enough to what you want. You'll have to play with positioning and such, I was just testing the theory myself, not trying to be accurate. Note that you won't see the bounds unless in debug mode as there is no drawing code included.


Body bodyLeft, bodyRight;
Geom geomLeft, geomRight;

// determine the maximum circle radius based on the screen
// width and height
float radius = (float)(Math.Min(ScreenManager.ScreenHeight, ScreenManager.ScreenHeight) - 10) / 2f;

// generate a semi-circle point list that fits on the screen
Vertices points = BoundsExample.CreateConcaveSemiCircle(radius, 32);

// create a body and geometry for the left bounds
bodyLeft = BodyFactory.Instance.CreatePolygonBody(physicsSimulator, points, 1f);
bodyLeft.IsStatic = true;

// rotate it so the concave portion is directed toward the
// screen center
bodyLeft.Rotation = (float)Math.PI/-2;

bodyLeft.Position = new Vector2(ScreenManager.ScreenWidth - (radius * 2), ScreenManager.ScreenHeight / 2);

geomLeft = GeomFactory.Instance.CreatePolygonGeom(physicsSimulator, bodyLeft, points, 5f);

// create a body and geometry for the right bounds
bodyRight = BodyFactory.Instance.CreatePolygonBody(physicsSimulator, points, 1f);
bodyRight.IsStatic = true;

// rotate it so the concave portion is directed toward the
// screen center
bodyRight.Rotation = (float)Math.PI/2;
bodyRight.Position = new Vector2(ScreenManager.ScreenWidth - radius, ScreenManager.ScreenHeight / 2);

geomRight = GeomFactory.Instance.CreatePolygonGeom(physicsSimulator, bodyRight, points, 5f);
Apr 18, 2008 at 9:25 PM
Thanks, this was what I was thinking, but I didn't know what way was the best. Thanks again for the demo code.
Apr 23, 2009 at 8:04 PM
Has anyone got this to work properly? It seems like the donuts don't fully close together, I'd like to see some code of someone who impemented this? I'm assuming the code posted was just thought out rather than impemented.

Thanks!
Apr 23, 2009 at 8:27 PM
The code posted was from a working demo, but it was on an older version of Farseer so things could have changed since then. I can try to dig up the actual files I used, but it could take a while.
Apr 23, 2009 at 9:57 PM
That would be really helpful! Thanks man!
Feb 22, 2011 at 9:46 PM

That doesn't work in 3.2 version. Help!