I'm working on a Silverlight game with Asteroids that break apart, kind of like... well I can't think of the name right now.
I'm trying to figure out the best strategy to do the most realistic asteroid breaking apart action out there. I've come up with a couple of ideas and was hoping people might discuss these or come up with their own.
Strategy 1: A Bunch of Circles.
- An asteroid would be a bunch of joined Circles.
- A method would generate a path the aproximates the outline of Circles.
- A method would generate the Circles so that:
- Circles are uniform in size
- A Circle must be joined to a Circle it touches.
- There would not exist any Circle that do not initially touch at least one other Circle
- That each Circle must touch at least one Circle that at touching Circle is touching to keep things grouped
- After a Collision:
- The collided with circle(s) is removed
- Somehow it must be determined if two seperate parts are created by the collision.
- If so, two new paths are created with same method that initially created the path, otherwise the initial path is updated by that method.
I know I can do 4.2, but there would be possibly a lot of looping, and we're also talking about a lot of vertices here and objects. Basically I am afraid this approach will be slow, but I know I can pull it off pretty easily.
Strategy 2: One Polygon Body
- An Asteroid will be one Polygon Body
- A method will create a Path that will exactly match the vertices of the Body.
- A method will create the Body so that it has generally uniform distributed points.
- After a Collision:
- A Vertex is created that represents the penetraion of the collided object
- If the Created Vertex happens to be outside the Body then it should be split
- Two new Bodies are Created through some genius method
- If the Vertex is within then it replaces the nearest Vertex to the collision?
- The Body(ies) have their Path(s) updated
I like this Strategy better, it will be more realistic, probably faster, and I've already got 1-3 done. But handling Collsions (4) feels beyond me. I don't know how to really tackle 4.1 or 4.2, and it seems like 4.3 might get unrealistic if my points
vary to much from the average radius of the asteroid.
1) Start by randomly or manually creating an polygonal asteroid outline (probably better if it were convex). Calculate the area of the polygon, assign a proportionate mass, and calculate the center of mass to set your geometry offset.
Related links: Orion's Standard Library (explicitly public domain): http://lawlor.cs.uaf.edu/~olawlor/ref/osl/index.html, look at polygon.cpp/h for center of mass/area.
2) randomly or manually partition your asteroid outline into smaller, semi evenly spaced polygons. Easy way is to start with a grid of verticies. For each one, randomly offset it by some random small vector, then determine if it is inside the polygon. Then,
for each of the inside verticies, use your favorite randomly varying straight walk algorithm (I made that name up) to connect each inside vertex with its neighbors using however many edges you want. If the neighbor is outside the original polygon, connect
it to the point of intersection with the original outline. (Hint: you can make it easy and just use straight lines rather than random walks, to avoid internal intersections). You should now have an asteroid with a polygonal boundry, with perfectly fitting
pieces of varying size and shape inside.
3) For each of the internal "pieces" pre-calculate the area and center of mass as if it were its own body, just as you did with the asteroid as a whole. Calculate its offset from the asteroid's center of mass.
4) Create one body for the asteroid, but give it multiple geometries, one for each of the individual pieces.
5) Add a collision handler for each of the individual piece geometries. If there is a collision, create a new body with the mass and geometry of the piece that was hit and attach the geometry that was hit to the new body. Then remove the geometry from the original
asteroid and recalculate its center of mass (not sure about this one, could be easy, just use the average of the remaining pieces' centers of mass, not sure if that is correct though). You may also stipulate that the collision is from a specific geometry,
say a bullet geometry for example. If you want the asteroid pieces to collide and break each other apart, then I would recommend a small timer after a piece breaks away in which no more pieces can break away, otherwise it might break all the pieces off in
one shot every time as it self collides.
6) If you like, you can add a random impulse to the break away piece to add that explosion look.
Hey JeroMiya I'm interested in the strategy you discussed. I'm pretty new to farseer, and I have a few questions?
What's with all the offset calculating? Doesn't Farseer do all that, like Center of Mass. I use Vertices.GetCentroid() for several applications.
In step 4 you say to create multiple Geometries for the one body. Does Farseer keep them in sync, if they're right next each other won't they just collide and break apart, or does making them part of one body keep them together and prevent them from colliding.
For 5 I already have a Bullet Geometry ready to go, so I don't think I need to worry about setting up a timer or anything like that, because breakups will only come from Bullets. Would you agree?
In case you're interested I started Strategy two, with a triangle that represents the exploded region. It's gone okay (my math is off). One problem I've had is that when I update my object after a bullet hits my new asteroid object is a step behind. It's
as though I have to get the event and say after the simulation is updated to do the work related to the collision after the update and update again. I seem to need an after collision processed event...