I have a texture which is not just a box or circle and my body needs to be the same of this shape so I was thinking to combine multiple bodies to achieve my desired shape, is it even possible? or there are better ways to do it? I'm using java with libgdx framework.
The shape of body is being defined by Fixture instance. Since body can have multiple fixtures you can combine many shapes as you wish.
To create many fixtures you jest call createFixture method many times with others FixtureDef objects like
FixtureDef fd1 = new FixtureDef();
FixtureDef fd2 = new FixtureDef();
...
fd1.shape = shape1;
fd2.shape = shape2;
...
body.createFixture(fd1);
body.createFixture(fd1);
Although please notice that Box2D supports more than circles and rectangles by providing ChainShape that allows you to create any shape you want
ChainShape weird = new ChainShape();
weird.createLoop( new float[]{vertice1x, vertice1y, vertice2x, ...});
To join bodies there is Joint (take a look here) mechanism but I guess it's not what you want here
Yes you can do so by following steps below
There is an option of PolygonShape or ChainShape which suits your work
Step 1: Define a body.
BodyDef bd = new BodyDef();
Body body = box2d.world.createBody(bd);
Step 2: Define the Shape.
ChainShape chain = new ChainShape();
Step 3: Configure the Shape.
The ChainShape object is a series of connected vertices. To create the chain, we must first specify an array of vertices (each as a Vec2 object).
To create the chain with the vertices, the array is then passed into a function called
createChain().Vec2[] vertices = new Vec2[2];
vertices[0] = box2d.coordPixelsToWorld(0,150);
vertices[1] = box2d.coordPixelsToWorld(width,150);
chain.createChain(vertices, vertices.length);
A Shape is not part of Box2D unless it is attached to a body. Even if it is a fixed boundary and never moves, it must still be attached.
FixtureDef fd = new FixtureDef();
fd.shape = chain; A fixture assigned to the ChainShape
fd.density = 1;
fd.friction = 0.3;
fd.restitution = 0.5;
body.createFixture(fd);
Polygon Shape
PolygonShape ps = new PolygonShape();
ps.setAsBox(box2dW, box2dH);
Vec2[] vertices = new Vec2[4];
vertices[0] = box2d.vectorPixelsToWorld(new Vec2(-15, 25));
vertices[1] = box2d.vectorPixelsToWorld(new Vec2(15, 0));
vertices[2] = box2d.vectorPixelsToWorld(new Vec2(20, -15));
vertices[3] = box2d.vectorPixelsToWorld(new Vec2(-10, -10));
PolygonShape ps = new PolygonShape();
ps.set(vertices, vertices.length);
Official testbed examples
I strongly recommend that you go over all the Testbed examples on the GUI until you find the effect you are looking for.
By doing so, I was able to find the following examples:
multiple fixtures per body as mentioned at https://stackoverflow.com/a/35667538/895245 :
https://github.com/erincatto/Box2D/blob/f655c603ba9d83f07fc566d38d2654ba35739102/Box2D/Testbed/Tests/ShapeEditing.h#L61
https://github.com/erincatto/Box2D/blob/f655c603ba9d83f07fc566d38d2654ba35739102/Box2D/Testbed/Tests/CompoundShapes.h
This is the best approach I've seen so far.
ChainShape: https://github.com/erincatto/Box2D/blob/f655c603ba9d83f07fc566d38d2654ba35739102/Box2D/Testbed/Tests/CharacterCollision.h#L56 But it won't work if one of the edges of your shape is not a straight line, e.g. a circle.
WeldJoint: https://github.com/erincatto/Box2D/blob/f655c603ba9d83f07fc566d38d2654ba35739102/Box2D/Testbed/Tests/Cantilever.h
However, this does not make the two bodies completely joined, as can be seen on the example itself, and from the Box2D manual:
It is tempting to use the weld joint to define breakable structures. However, the Box2D solver is iterative
so the joints are a bit soft. So chains of bodies connected by weld joints will flex
So it is more like a revolute joint that attempts to leave the two bodies at a given angle.
Those examples are very simple, and will be supported as Box2D evolves.
To create different shapes you can get idea from these examples:
To create circle shape.
bodyDef.type = b2Body.b2_dynamicBody;
var fixDef = new b2FixtureDef;
fixDef.density = 1000;
fixDef.friction = 0.5;
fixDef.restitution = 0.5;
fixDef.shape = new b2CircleShape(0.5);
bodyDef.position.x = 1;
bodyDef.position.y = 16;
world.CreateBody(bodyDef).CreateFixture(fixDef);
To create box(Rectangle or Square) shape.
var fixDef = new b2FixtureDef;
fixDef.density = 100;
fixDef.friction = 5;
fixDef.restitution = 0.5;
bodyDef.type = b2Body.b2_dynamicBody;
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(0.2,1);
bodyDef.position.x =i;
bodyDef.position.y = 15.5;
world.CreateBody(bodyDef).CreateFixture(fixDef);
To create unbox shape(polygon).
bodyDef.type = b2Body.b2_dynamicBody;
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsArray([
new b2Vec2(-1,0.5),//left vertex
new b2Vec2(3,-0.3),//top vertex
new b2Vec2(3,0.5),//right vertex
],3);
bodyDef.position.x =5;
bodyDef.position.y = 16;
world.CreateBody(bodyDef).CreateFixture(fixDef);
Related
I'm making a side scrolling game and I wan't to know how can I create an infinite terrain, do I need to use a static body that keeps on increasing its width? Also since its an infinite world, is it a good idea to just create a body to be used as an obstacle and then remove it when not in range?
public Body createPlatform(){
Body body;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.StaticBody;
def.fixedRotation = true;
def.position.set(0.6f, 1.6f);
body = world.createBody(def);
PolygonShape shape = new PolygonShape();
shape.setAsBox(2f, 1.5f);//have no Idea how to increase width infinitely or should I even be using a Body as ground.
FixtureDef fDef = new FixtureDef();
fDef.shape = shape;
fDef.density = 1f;
body.createFixture(fDef);
shape.dispose();
return(body);
}
Also I'm using Libgdx library and java of course.
It's best to split the world into chunks: once the player exits one chunk, load in one or more. You do not need to have the chunks pre-loaded; you load them in on the fly depending on the player's location.
I'm trying to create a game with "libGDX" and "Box2D".
I've several shapes in the game, so I created a BodyFactory class which creates my bodies using PolygonShape
The problem is, when I create a body, with Shape.setAsBox() method, everything works fine, but when I create bodies with PolygonShape.set(vertices), the position of bodies changes as I wish, but they won't rotate at all.
This is what I get (after stability) when I drop 3 bodies from the sky:
The square rotates and stays at the ground, bot the other shapes won't.
Also note that I tried adding
body.setFixedRotation(false);
to my code, but nothing changed.
Also friction, mass and density of shapes are at a reasonable amount.
This is the part of my code which creates a "PolygonShape" from a file:
...
Body body = world.createBody(bodyDef);
...
for (int i = 0; i < bodyConf.meshData.length; i++) {
PolygonShape polygonShape = new PolygonShape();
polygonShape.set(bodyConf.meshData[i]);
fixtureDef.shape = polygonShape;
body.createFixture(fixtureDef);
polygonShape.dispose();
}
I think the problem is that you are creating only one Body with three Fixtures attached to it.
What you actually want is three Bodys, with one Fixture attached to each of them. That way, each body can rotate independent from the others.
for (int i = 0; i < bodyConf.meshData.length; i++) {
BodyDef bodyDef = ...;
Body body = world.createBody(bodyDef);
PolygonShape polygonShape = new PolygonShape();
polygonShape.set(bodyConf.meshData[i]);
fixtureDef.shape = polygonShape;
body.createFixture(fixtureDef);
polygonShape.dispose();
}
I'm doing some initial experiments for a CS course, where I'm trying to use JBox2D as a physics library and drawing using JavaFX. I have had some luck draw circles that fall from the top of the screen, but now I have issues doing the same with rectangles (or any other shape).
I'm able to both draw and simulate, but I cannot figure out how to rotate the drawn nodes in JavaFX using values from the Body objects.
Here's my code for the bodies using JBox2D:
#Override
public Body createBody() {
BodyDef bd = new BodyDef();
bd.type = BodyType.DYNAMIC;
bd.position.set(centerX, centerY);
PolygonShape ps = new PolygonShape();
ps.setAsBox(2.0f,4.0f);
FixtureDef fd = new FixtureDef();
fd.shape = ps;
fd.density = 0.9f;
fd.friction = 0.3f;
fd.restitution = 0.5f;
Body b = PhysicalScene.world.createBody(bd);
b.createFixture(fd);
return b;
}
}
This is drawn using nodes in JavaFX - as written here:
#Override
public Node create() {
Rectangle r = new Rectangle();
r.setHeight(20);
r.setWidth(40);
r.setStroke(Color.RED);
r.setLayoutX(Physics.toPixelX(centerX));
r.setLayoutY(Physics.toPixelY(centerY));
// THIS IS WHAT I'M MISSING
// r.setRotate(/* some value from Body */);
return r;
}
The code isn't pretty, but I hope you get the idea. I am able to rotate the nodes by inserting arguments in the method, but do not know how to get these values from the Body objects themselves.
I hope you can help, thanks!
I want to know how to prevent an object in crossing another. I have a ball and a square which I can move whith my mouse. When my ball is on my square I move it (in top for example) if I go very slowly the ball remains on the square if not it crosses it.
if both of your 2 object have a fixture defined they will not be able to crossing one another this is an exmple of how a dynamic object who will be affected by physics in the BOX2D world must be created , and also this object can't tunneling through a sensor :
public Ball (World world){
this.world = world;
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DYNAMIC;
bodyDef.position.set(0.0f/RATE, 0.0f/RATE);
Ballbody = world.createBody(bodyDef);
CircleShape circle = new CircleShape();
radius = (int) (Math.random()*30+15); // you can set a non randum raduis
circle.m_radius = radius/RATE;
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.restitution = 0.8f;
fixtureDef.density = 2.0f;
fixtureDef.friction = 0.3f;
fixtureDef.filter.groupIndex = -1;
Ballbody.createFixture(fixtureDef);
Ballbody.getFixtureList().setUserData("Ballounaton"); // optional
Vec2 ballVec = new Vec2((float) (Math.random()*8+2),0.0f);
Ballbody.setLinearVelocity(ballVec);
}
make sure to define a fixture to your box2d dynamic or static object to avoid tunneling through a sensor like in this exmple :
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.restitution = 0.8f;
fixtureDef.density = 2.0f;
fixtureDef.friction = 0.3f;
fixtureDef.filter.groupIndex = -1;
Ballbody.createFixture(fixtureDef);
according to BOX2D official documentation :
Recall that shapes don’t know about bodies and may be used
independently of the physics simulation. Therefore Box2D provides the
b2Fixture class to attach shapes to bodies. Fixtures hold the
following:
a single shape
broad-phase proxies
density, friction, and restitution
collision filtering flags
back pointer to the parent body
user data
sensor flag
I'm using JBox2d to perform collision detection in a game project I'm working on.
I represent obstacles in the world with static bodies. Whenever a dynamic body (i.e. a game character) collides with one of these obstacles, there is a very noticeable drop in performance. Fps will drop from ~120 to ~5. This seems to happen more frequently when the corners of the static body are collided with.
When I set the body type of the world obstacles to be dynamic instead of static, with very high density(to prevent the body from moving when it is collided with), this issue disappears... This solution is not ideal for my situation however......
Any ideas as to what could be causing this huge fps drop?
Here's the code I use to create the static bodies:
BodyDef def = new BodyDef();
def.type = BodyType.STATIC; // If this line is commented and the other
//commented lines are uncommented, the issue goes away.
//def.type = BodyType.DYNAMIC;
def.position.set(worldBounds.getCenterX(), worldBounds.getCenterY());
Body staticBody = b2World.createBody(def);
PolygonShape box = new PolygonShape();
box.setAsBox(worldBounds.getWidth() * 0.5f, worldBounds.getHeight() * 0.5f);
FixtureDef fixture = new FixtureDef();
fixture.shape = box;
fixture.friction = 0.3f;
//fixture.density = 1000000000;
staticBody.createFixture(fixture);
//staticBody.setSleepingAllowed(true);
//staticBody.setFixedRotation(true);
I've tried using a CircleShape instead of a PolygonShape, but that doesn't help anything.
Thank you!
this is the code from the game im working on at the moment which works fine. hopefully if you copy and paste, change a few variable names and stuff it might sort your problem. im new to box2d so cant tell you exactly where the problem lies. hope it helps.
//bodydef
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.StaticBody;
bodyDef.position.set(position);
body = world.createBody(bodyDef);
//shape
PolygonShape shape = new PolygonShape();
shape.setAsBox(dimension.x / 2, dimension.y / 2);
//fixture
FixtureDef fixture = new FixtureDef();
fixture.friction = 0.3f;
fixture.shape = shape;
body.createFixture(fixture);
shape.dispose();