using breakable body

Topics: Developer Forum, Project Management Forum, User Forum
Oct 18, 2010 at 7:27 AM

Hi there.

Vertices vtx = PolygonTools.CreateCircle(1, 100);
brkBody = FixtureFactory.CreateBreakableBody(_world, vtx, 1, new Vector2(5, 10));

in this case, I can use breakable body.

but it devided a vertices in serveral triangle parts  automatically.

I want to devide a vertices in serveral parts as i want.

How can I do?

I mean how I can make vertices list well.

Thank you in advance.

Oct 19, 2010 at 2:30 AM
Edited Oct 19, 2010 at 3:04 AM

Here's some code showing how to create a breakable body with custom shapes. You can also see how it works by opening Fixturefactory.cs and looking at the code for CreateBreakableBody.

 

//This code creates a breakable body in the shape of a house,
//with a rectangle for the house itself and a triangle shape for the roof.
//When the body breaks the triangle and rectangle will become separate bodies.

//This is the list of pieces that make up the breakable body
//When the body breaks these pieces will separate into their own bodies
List<Vertices> pieces = new List<Vertices>();

//create vertices for a rectangle
Vertices rectangle = PolygonTools.CreateRectangle(1, 1);

//create vertices for a triangle
//position it so it sits above the rectangle
Vertices triangle = new Vertices();
triangle.Add(new Vector2(0, 2f));
triangle.Add(new Vector2(-1, 1f));
triangle.Add(new Vector2(1, 1f));

//Add the vertices to the list
pieces.Add(rectangle);
pieces.Add(triangle);

//Create the breakable body and add it to the world
BreakableBody breakableBody = new BreakableBody(pieces, world, density);
world.AddBreakableBody(breakableBody);

 

EDIT: I haven't tested it, but I think it will work. Let me know if you have any problems!

Oct 19, 2010 at 3:10 AM

Actually, heres a SimpleSample for you! Just add it to the SimpleSamplesXNA project and edit FarseerPhysicsGame.cs, and you'll be able to see it working! Let me know if you have problems!

using System.Text;
using FarseerPhysics.DemoBaseXNA;
using FarseerPhysics.DemoBaseXNA.ScreenSystem;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using FarseerPhysics.Common;
using System.Collections.Generic;

namespace FarseerPhysics.SimpleSamplesXNA
{
    internal class Demo8Screen : GameScreen, IDemoScreen
    {

		BreakableBody _breakablebody;

        #region IDemoScreen Members

        public string GetTitle()
        {
            return "Demo8: Breakable Body";
        }

        public string GetDetails()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("This demo shows a breakable body.");
            sb.AppendLine("A fixture is a combination of a body and a shape.");
            sb.AppendLine(string.Empty);
            sb.AppendLine("GamePad:");
            sb.AppendLine("  -Rotate: left and right triggers");
            sb.AppendLine("  -Move: left thumbstick");
            sb.AppendLine(string.Empty);
            sb.AppendLine("Keyboard:");
            sb.AppendLine("  -Rotate: left and right arrows");
            sb.AppendLine("  -Move: A,S,D,W");
            return sb.ToString();
        }

        #endregion

        public override void Initialize()
        {
            World = new World(new Vector2(0, -20));

            base.Initialize();
        }

        public override void LoadContent()
        {
			//This code creates a breakable body in the shape of a house,
			//with a rectangle for the house itself and a triangle shape for the roof.
			//When the body breaks the triangle and rectangle will become separate bodies.

			//This is the list of pieces that make up the breakable body
			//When the body breaks these pieces will separate into their own bodies
			List<Vertices> pieces = new List<Vertices>();

			//create vertices for a rectangle
			Vertices rectangle = PolygonTools.CreateRectangle(1, 1);

			//create vertices for a triangle
			//position it so it sits above the rectangle
			Vertices triangle = new Vertices();
			triangle.Add(new Vector2(0, 2f));
			triangle.Add(new Vector2(-1, 1f));
			triangle.Add(new Vector2(1, 1f));

			//Add the vertices to the list
			pieces.Add(rectangle);
			pieces.Add(triangle);

			//Create the breakable body and add it to the world
			_breakablebody = new BreakableBody(pieces, World, 1);
			_breakablebody.Strength = 100; //This is how easy the body is to break
			World.AddBreakableBody(_breakablebody);

			//_rectangle = FixtureFactory.CreateRectangle(World, 5, 5, 1);
			//_rectangle.Body.BodyType = BodyType.Dynamic;

			base.LoadContent();
        }

        public override void HandleInput(InputState input)
        {
            if (input.CurrentGamePadState.IsConnected)
            {
                HandleGamePadInput(input);
            }
            else
            {
                HandleKeyboardInput(input);
            }

            base.HandleInput(input);
        }

        private void HandleGamePadInput(InputState input)
        {
            Vector2 force = 50 * input.CurrentGamePadState.ThumbSticks.Left;
			_breakablebody.MainBody.ApplyForce(force);

            float rotation = 40 * input.CurrentGamePadState.Triggers.Left;
			_breakablebody.MainBody.ApplyTorque(rotation);

            rotation = -40 * input.CurrentGamePadState.Triggers.Right;
			_breakablebody.MainBody.ApplyTorque(rotation);
        }

        private void HandleKeyboardInput(InputState input)
        {
            const float forceAmount = 60;
            Vector2 force = Vector2.Zero;
            force.Y = -force.Y;

            if (input.CurrentKeyboardState.IsKeyDown(Keys.A))
            {
                force += new Vector2(-forceAmount, 0);
            }
            if (input.CurrentKeyboardState.IsKeyDown(Keys.S))
            {
                force += new Vector2(0, -forceAmount);
            }
            if (input.CurrentKeyboardState.IsKeyDown(Keys.D))
            {
                force += new Vector2(forceAmount, 0);
            }
            if (input.CurrentKeyboardState.IsKeyDown(Keys.W))
            {
                force += new Vector2(0, forceAmount);
            }

			_breakablebody.MainBody.ApplyForce(force);

            const float torqueAmount = 40;
            float torque = 0;

            if (input.CurrentKeyboardState.IsKeyDown(Keys.Left))
            {
                torque += torqueAmount;
            }
            if (input.CurrentKeyboardState.IsKeyDown(Keys.Right))
            {
                torque -= torqueAmount;
            }

			_breakablebody.MainBody.ApplyTorque(torque);
        }
    }
}

Oct 19, 2010 at 3:41 AM

Thanks.

But look at below.

            Vertices rec1, rectangle = PolygonTools.CreateRectangle(1, 1);
            rec1 = new Vertices();
            rec1.Add(new Vector2(1, 1));
            rec1.Add(new Vector2(3, 1));
            rec1.Add(new Vector2(3, -1));
            rec1.Add(new Vector2(1, -1));
            //create vertices for a triangle
            //position it so it sits above the rectangle
            Vertices triangle = new Vertices();
            triangle.Add(new Vector2(0, 2f));
            triangle.Add(new Vector2(-1, 1f));
            triangle.Add(new Vector2(1, 1f));

            vetcs.Add(rectangle);
            vetcs.Add(triangle);
            vetcs.Add(rec1);

            //Create the breakable body
            brkBody = new BreakableBody(vetcs, _world, 1);
            brkBody.MainBody.Position = new Vector2(5, 20);

            //Vertices vtx = PolygonTools.CreateCircle(1, 100);
            ////vtx = PolygonTools.CreateRectangle(1, 1);
            //brkBody = FixtureFactory.CreateBreakableBody(_world, vtx, 1, new Vector2(5, 10));
            brkBody.Strength = 0.000000f;
          _world.AddBreakableBody(brkBody);

In this case, I can see the error message box.

What's wrong?

I have only added another rectangle.

Oct 19, 2010 at 9:35 AM

If you follow the error you will see that it happens when "Your polygon is non-convex (it has an indentation) or has colinear edges" (PolygonShape.cs).

This is because in Farseer polygon shapes have to be convex and in counter-clockwise order. So you just have to add the points in the reverse order, and it will work.

Oct 19, 2010 at 1:32 PM

Thanks.

I have fixed it.

And other problems are here.

Listen to me carefully.

I am gonna to break one image.

To do so, have I to have many textures divided by one images?

if so, how to get every vertices according to every parts?

in this case, every parts will be texture.

I will look forward to your good solution.

Thanks in advance.

Oct 20, 2010 at 12:01 AM

If you are using sprites you will have to make each image by hand, which might be difficult.

An easier way is to create a vertexbuffer for each shape and render it as a triangle list. That way it will fit the shape exactly, and the same code will work for every shape. Heres what you'd have to do:

  1. Triangulate vertices
  2. Building vertex array with triangle coordinates
  3. Create VertexBuffer

You can also have a look at the DebugViewXNA, because it does the same thing (except without a vertexbuffer, it just renders straight from the vertex array, but a vertexbuffer is faster)

Developer
Oct 22, 2010 at 1:53 AM

So if I understand the question right, you want to have the single texture that your using automatically split and follow the chunks when the breakable body breaks?

Quite simply stated you will need to map each triangle into texture space. Each object that is broken off will need to know it's 3 texture space vectors. (this means you will most likely have to modify BreakableBody, thank God for open source right lol) After that it's just a matter of rendering a triangle list with the appropriate texture coordinates. It should be pretty easy to get working if you have a good understanding of how to go from local space to texture space.

Let me know how you do.

Oct 22, 2010 at 2:58 AM

Thank you for your advice.

But I have already done in other way.

I didn't use the breakable body.

I have only broken the image, and remove the body. hehe . . .

however, I have other problems.

Can you teach me about it?

I wanna create polygon from texture.

I have already get it from texture but the polygon is reflection against X-axi with the real image.

here is my code .


 

uint[] data;
                    List<Fixture> lstFixture = new List<Fixture>();
                    List<Vertices> lstVerctices = new List<Vertices>();

                    texture = conManager.Load<Texture2D>(obstName);
                    data = new uint[texture.Width * texture.Height];
                    texture.GetData(data);
                    Vertices vertices = PolygonTools.CreatePolygon(data, texture.Width, texture.Height, false);
                    
                    Vector2 scale = new Vector2(0.03333333333f, 0.033333333333f);
                    vertices.Scale(ref scale);
                    lstVerctices = BayazitDecomposer.ConvexPartition(vertices);
                    lstFixture = FixtureFactory.CreateCompundPolygon(CmnRsc.world, lstVerctices, 1);
                    //CreateBody(false, float.MaxValue, float.MaxValue, 0.4f, 0);
                    body = lstFixture[0].Body;
                    body.Position = CmnRsc.ToWorldCoordinates(position);
                    body.BodyType = BodyType.Static;
                    fixture = lstFixture[0];
                    body.Rotation = 0;

What's worng?

 

 

Developer
Oct 22, 2010 at 3:58 AM

Ok, before you scale you need to -

                Vector2 origin = new Vector2(-texture.Width / 2, -texture.Height / 2);
                item.Translate(ref origin);
                Vector2 scale = new Vector2(1, -1);
                item.Scale(ref scale);
By scaling Y by -1 we are just flipping it. Let me know if that works well for u. Also Bayazit decompser is possibly broken I would use the Earclip decomposer.

Oct 22, 2010 at 6:27 AM

Thank you.

it seems to be good.

But actually, it has error.

When I run the code above, my game has not ran.

The reason is it;

Vector2 scale = new Vector2(1, -1));

Why can't I?

Please help me.

 

Oct 22, 2010 at 8:08 AM
One too many closing brackets?
Oct 22, 2010 at 10:24 AM

WHat do you mean?

I don't undersand what you ask.

Oct 22, 2010 at 1:44 PM

He means that you added too many parenhtesis in your code. Where it says

Vector2 scale = new Vector2(1, -1));

You should put

Vector2 scale = new Vector2(1, -1);

Oct 22, 2010 at 2:05 PM

hhhhh,

it is my mistype.

But not in my real code.

I need the real way to fix my problem.

if that is a problem for me, why couldn't I fix my problem?