Drawing rotated bodies using JBox2D and JavaFX - java

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!

Related

Jbox2d Issues with positioning platforms

I am working on developing a platformer, and everything's working fine, except, I seem to be unable to position the bodies for the static platforms.
// creating all the bodies
BodyDef bdef = new BodyDef();
bdef.position.set(x, y);
bdef.type = BodyType.STATIC;
Body body = world.createBody(bdef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(width, height);
FixtureDef fdef = new FixtureDef();
fdef.friction = 0.3f;
fdef.shape = shape;
body.createFixture(fdef);
This is general code that's used to create every body in the map. The bodies work fine, but they don't line up with the width nor the coordinates of the map that I've set. I've noticed that I must specify the bottom left point as starting point for it to make body, but what else I am missing? Why bodies tend to be bigger and go past the starting point of X and Y?
Bodies in box2d are made from their center points. When you define it's position, you are setting it's center and when you define it's width/height, you are actually setting half the width/height (i.e. the size ends up double what you intended).

How to create infinite Platform with Box2d?

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.

LibGDX Box2D: Cannot get Fixture to render

I have been recently trying to get back into LibGDX's version of Box2D, and I looked back at a demo I created a few months back, and my code looks fine, and from my Google search results, my code is fine, but for the life of me, I cannot get the Fixture to render.
Here is my (Minimalist example) code, and for the life of me, I cannot get it to work Note: I built a wrapper around the LibGDX Game class, should be self-explanatory:
public class TestBox2D extends EGGame {
int width;
int height;
static final Vector2 ZERO_GRAVITY = new Vector2(0f, 0f);
OrthographicCamera camera;
World world;
Body body;
Box2DDebugRenderer box2dDebugRenderer;
RayHandler rayHandler;
... // Removed Constructor, nothing special here.
#Override
protected void init() {
width = Gdx.graphics.getWidth() / 2;
height = Gdx.graphics.getHeight() / 2;
camera = new OrthographicCamera(width, height);
camera.position.set(width / 2, height / 2, 0);
camera.update();
world = new World(ZERO_GRAVITY, true);
box2dDebugRenderer = new Box2DDebugRenderer();
rayHandler = new RayHandler(world);
rayHandler.setCombinedMatrix(camera.combined);
// creating Body
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.position.set(width/2, height/2);
body = world.createBody(bodyDef);
CircleShape shape = new CircleShape();
shape.setRadius(1f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
body.createFixture(fixtureDef);
}
#Override
protected void updateGame() {
world.step(1f / 30f, 6, 2);
rayHandler.update();
}
#Override
protected void renderGame() {
box2dDebugRenderer.render(world, camera.combined);
rayHandler.render();
}
#Override
public void dispose() {
world.dispose();
}
... // Removed main method, nothing special here.
}
Note that world.getBodyCount(); and world.getFixtureCount(); both return 1.
Probable causes of problem.
Check if you have called render on fixtures in either RayHandler class or Box2DDebugRenderer class.
You have not set the position of the circle shape. It might be lying on the edge and remain out of camera bounds.
Check your units. Radius of circle might be relatively so small that it would be invisible, or it might be so large that it might be covering entire screen.
Hope this helps.
You can try the following, one of the things mention Tanmay Patil, it resizes body:
Example:
Varible Class:
long time = 0;
float testSize = 0;
Call in your render method:
time += System.nanoTime();
if (time >= 100000000){
time = 0;
testSize += (0.1f);
body.getFixtureList().first().getShape().setRadius(testSize);
}
if not notice any change, try the opposite:
time += System.nanoTime();
if (time >= 100000000){
time = 0;
testSize -= (0.1f);
body.getFixtureList().first().getShape().setRadius(testSize);
}
Edit:
On the other hand, this does not affect the question, but you can call dispose here if you want:
.////////////
CircleShape shape = new CircleShape();
shape.setRadius(1f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
body.createFixture(fixtureDef);
shape.dispose();
}
Fixed.
The issue was that I was attempting to call RayHandler#render() after Box2DDebugRenderer.render(...) while the RayHandler didn't have any Light objects (Adding a PointLight allowed it to render), but whatever the reason for it is, it's weird, but calling the RayHandler#render() first allows it to work. This might be a bug in LibGDX that I will report.

Box2d setAngularVelocity do not work for high speeds

I am using Box2d for a game, and although I use large constants to set angular velocity, the fastest speed I can get is 1 revolution at 3.86 seconds.
I had checked my source code in the following thread and everything is the same with what I have been suggested from both users in here and in tutorials:
setAngularVelocity rotates really slowly
However than I noticed the following unresolved thread:
http://www.reddit.com/r/libgdx/comments/1qr2m3/the_strangest_libgdxbox2d_behaviour/
and noticed that might actually be the problem. Here is my dispose method
public void dispose() {
//Get Rid of Everything!
Assets.Clear();
GameEngine.Clear();
BallMap.clear();
PlayerMap.clear();
shapeRenderer.dispose();
debugRenderer.dispose();
world.dispose();
batch.dispose();
font.dispose();
}
They are all reinitialized on the beginning as follows:
this.game = game;
this.cameraWidth = cameraWidth*pixelRatio;
this.cameraHeight = cameraHeight*pixelRatio;
batch = new SpriteBatch();
shapeRenderer = new ShapeRenderer();
stateTime = 0F;
Scores = new Integer[]{0, 0};
debugRenderer = new Box2DDebugRenderer();
world = new World(new Vector2(0, 0), true); //Create a world with no gravity
GameEngine.setContactListener(world);
I navigate through screens with the following code:
public void create () {
scene_menu = new MainMenuScreen(this, cameraWidth, cameraHeight);
setScreen(scene_menu);
}
public void swtogame(){
scene_menu.dispose();
scene_game = new MatchScreen(this, cameraWidth, cameraHeight);
setScreen(scene_game);
}
public void swtomenu(){
scene_game.dispose();
scene_menu = new MainMenuScreen(this, cameraWidth, cameraHeight);
setScreen(scene_menu);
}
the way i initialize objects:
public Object(World world, short category, short mask, float x, float y, float radius, Sprite image,
float maxSpeed, float frictionStrength, float linearDamping, float angularDamping, boolean movable,
float elasticity, float mass){
this.world = world;
this.category = category;
this.mask = mask;
// We set our body type
this.bodyDef = new BodyDef();
if(movable==true){bodyDef.type = BodyType.DynamicBody;}else{bodyDef.type = BodyType.StaticBody;}
// Set body's starting position in the world
bodyDef.position.set(x, y);
bodyDef.linearDamping = linearDamping;
bodyDef.angularDamping = angularDamping;
// Create our body in the world using our body definition
this.body = world.createBody(bodyDef);
// Create a circle shape and set its radius
CircleShape circle = new CircleShape();
circle.setRadius(radius);
// Create a fixture definition to apply our shape to
fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = (float) (mass/(Math.PI*radius*radius));
fixtureDef.friction = frictionStrength;
fixtureDef.restitution = elasticity;
fixtureDef.filter.categoryBits = category;
fixtureDef.filter.maskBits = mask;
// Create our fixture and attach it to the body
this.fixture = body.createFixture(fixtureDef);
// BodyDef and FixtureDef don't need disposing, but shapes do.
circle.dispose();
... unrelated functions after that
}
Am I disposing correctly? Is this a bug? Is there any way to get around it and use the setAngularVelocity properly?
Because you haven't shown much code, I can I'm not 100% sure that I'm right, but I think that you are hitting the built in maximum movement limit of 2.0 units per time step. This means that at a typical framerate of 60Hz a body covering 2 units per timestep is moving at 120 m/s or 432 km/h (270 mph). Unfortunately it seems that there is no direct way to change this limit in Java, because this limit seems to be defined in the native C++ librarys.
But I think that the real problem is that you have a wrong scale. Box2D uses MKS (meters, kilograms, and seconds). And you may have used pixels instead of meters. The FAQ of Box2D suggests to use
objects [that are] between 0.1 - 10 meters
otherwise you can get strange situations.
See http://www.iforce2d.net/b2dtut/gotchas#speedlimit
and https://code.google.com/p/box2d/wiki/FAQ
I just found the problem, and it was pretty simple. Im just going to post this here for future googlers:
Object was actually rotating properly, the problem was in my drawing method, I didn't use conversion between radians to degrees in my batch.draw, and it interpreted everything in radians. I know such an amateur mistake! Thanks a lot for your time.

Box2D static body collision performance issue

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();

Categories