I'm creating a crash test game using Android Studio and LibGDX, I have everything I need on the game set, however I would like to create an upside down triangle like this in Box2D, Obviously, It's not going to look like this but this image is to give you an example
However when I run it it looks like this:
I've tried changing the order of the code in Box2D but it doesn't create an inverted triangle, like this :
private Fixture createcollisionFixture(Body collisionBody) {
Vector2[] vertices = new Vector2[3];
vertices[0] = new Vector2(-0.5f, -0.5f);
vertices[1] = new Vector2(0.5f, -0.5f);
vertices[2] = new Vector2(0, 0.5f);
PolygonShape shape = new PolygonShape();
shape.set(vertices);
Fixture fix = collisionBodyBody.createFixture(shape, 1);
shape.dispose();
return fix;
}
I change it to:
private Fixture createcollision2Fixture(Body collision2Body) {
Vector2[] vertices = new Vector2[3];
vertices[2] = new Vector2(0, 0.5f);
vertices[1] = new Vector2(0.5f, -0.5f);
vertices[0] = new Vector2(-0.5f, -0.5f);
PolygonShape shape = new PolygonShape();
shape.set(vertices);
Fixture fix = collision2Body.createFixture(shape, 1);
shape.dispose();
return fix;
}
But it keeps loading as the second picture, not like an inverted triangle, how do I fix this? Help would be greatly appreciated.
The problem is not in Box2D but in coordinates that you are using to draw triangle. No matter in what order you will be passing them to the Fixture they will produce triangle like this:
If you want to rotate the triangle you have to pass another set of coordinates like this:
So finally your code should look like:
...
Vector2[] vertices = new Vector2[3];
vertices[2] = new Vector2(-0.5, 0.5f);
vertices[1] = new Vector2(0.5f, 0.5f);
vertices[0] = new Vector2(0.5f, -0.5f);
...
Related
I am currently using libgdx and it's box2d extension to make an open world platformer. I wanted to render a world from a tmx tilemap, and add physics from it. The tilemap renders fine (using OrthogonalTiledMapRenderer), but when I tried to add phyiscs using the following code nothing happened.
public void renderPhysicsMap(TiledMap map, World world, int layer, int tileSize) {
TiledMapTileLayer mapLayer = (TiledMapTileLayer) map.getLayers().get(layer);
MapObjects mapObjects = mapLayer.getObjects();
for (MapObject mapObject : mapObjects) {
Rectangle rect = ((RectangleMapObject) mapObject).getRectangle();
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.StaticBody;
Body body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox((rect.width/2)/tileSize, (rect.height/2)/tileSize);
Fixture fixture = body.createFixture(shape, 0.0f);
fixture.setFriction(0.1f);
Vector2 center = new Vector2();
rect.getCenter(center);
body.setTransform(center.scl(1/tileSize), 0);
}
}
After some debugging (running mapObjects.getCount()) I found that the size was 0. This is odd, because I know this is a valid tilemap (I can render it just fine). Would anyone know why this is?
#Override
public void create()
{
batch = new SpriteBatch();
shape = new ShapeRenderer();
velocity = new Vector2(100, 0);
position = new Rectangle(0, 5, 100, 100);
font = new BitmapFont();
font.setColor(Color.BLACK);
font.getData().scale(3f);
camera = new OrthographicCamera();
confCamera();
}
#Override
public void render()
{
if(Gdx.input.isTouched())
position.x = Gdx.input.getX() - position.width/2;
position.y = (Gdx.input.getY() - position.height/2);
shape.begin(ShapeRenderer.ShapeType.Filled);
shape.setColor(Color.BLACK);
shape.rect(position.x, position.y, position.width, position.height);
shape.end();
}
It's a simple code, but I'm not undestanding Y axis, my shape moves like a mirror. If I touch on top, my shape goes to bottom. If I touch on bottom, my shape goes to top. How to fix it?
LibGDX (by default) for rendering uses coordinate system where 0 is at bottom of the screen and the more you go up Y coordinate grows.
Also, when you read input coordinates (touches, moves...) you get screen coordinates, but when you render your graphics you are using "world" coordinates. They are in 2 different coordinate system so to convert from screen to world you have to use camera.unproject() call. Should be like:
Vector3 touchPos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
and then use touchPos.x and touchPos.y.
The similar question is asked here so you can find more answers there:
Using unProject correctly in Java Libgdx
I have created a sphere using Texture by calling createSphere() method on modelBuilder using libGDX. As it is 3D, I used Perspective Camera. I am trying to move the sphere on the screen with the mouse. Its working fine, but the sphere had been changing its shape while moving on the screen.
I tried by changing the position and lookAt of the Perspective Camera. Still, shape is changing. Can anyone suggest the solution.
Here is my part of the code:
modelBatch = new ModelBatch();
ModelBuilder modelBuilder = new ModelBuilder();
Texture texture = new Texture(Gdx.files.internal("ball.png"));
Material material = new
Material(TextureAttribute.createDiffuse(texture));
final long attributes = VertexAttributes.Usage.Position |
VertexAttributes.Usage.TextureCoordinates;
sphere = modelBuilder.createSphere(0.5f, 0.5f, 0.5f, 24, 24, material, attributes);
sphereInstance = new ModelInstance(sphere);
perCamera = new PerspectiveCamera(67, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
perCamera.position.set(0f, 0f, 3f);
perCamera.lookAt(0f,0f,0f);
perCamera.near = 1f;
perCamera.far = 300f;
perCamera.update();
[Here I have attached screenshot for the reference, in which the regular sphere changes its shape to ellipse as it is moving away from the camera.][1]
I've been looking at some other threads, and despite every thing I have tried, the shapes I have created in box2d are not rendering. It is very bizarre, and I hope that you guys can provide a solution.
public class worldRender {
fighterGame game;
PlayScreen renderGame;
private Viewport gamePort = new StretchViewport(1020 / game.PPM,760 / game.PPM);
World world = new World(new Vector2(0,-10), true);
Box2DDebugRenderer b2dr = new Box2DDebugRenderer();
private OrthographicCamera gameCam = new OrthographicCamera();
BodyDef bDef = new BodyDef();
public Body b2body;
FixtureDef fixtureDef = new FixtureDef();
ShapeRenderer shapeRender;
public worldRender() {
gameCam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
gameCam.position.set(1020/2, 760/2, 0);
}
public worldRender(float dt) {
gameCam.update();
world.step(1/60f, 6, 2);
b2dr.render(world, gameCam.combined);
bodyRender();
}
public void bodyRender() {
BodyDef bdef = new BodyDef();
bdef.position.set(0.0f / game.PPM,4.0f / game.PPM);
bdef.type = BodyDef.BodyType.DynamicBody;
b2body = world.createBody(bdef);
FixtureDef fdef = new FixtureDef();
fdef.friction = 0.25f;
CircleShape shape = new CircleShape();
shape.setRadius(5);
fdef.shape = shape;
fdef.density = 1.0f;
b2body.createFixture(fdef);
}
}
I'm going to list off a few solutions because not everything is clear in the snippet:
Are you sure the worldRender() method is being run
If you are using Game and Screen make sure your game render() method calls super() otherwise your Screen render() method will not be run;
As mentioned before is the value of PPM correct/what is it?
Does this draw:
// First we create a body definition
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.StaticBody;
// Set our body's starting position in the world
bodyDef.position.set(50, 50);
// Create our body in the world using our body definition
Body body = world.createBody(bodyDef);
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(10f);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
// Create our fixture and attach it to the body
Fixture fixture = body.createFixture(fixtureDef);
// Remember to dispose of any shapes after you're done with them!
// BodyDef and FixtureDef don't need disposing, but shapes do.
circle.dispose();
This should draw a circle of radius 10 at x=10,y=10 (make sure those points are in your view port.
I would suggest cleaning up your code a bit, and studying some more tutorials, that will probably solve your problems. But let's give you some hints to get you on the way:
I somehow suspect you are creating a worldRender object every frame. Java is a garbage collected language, doing so will severly impact your performance. Persist as many objects as possible. In my bigger games, i create next to 0 objects each render and game logic tick. Aim for that.
Finally, what will probably solve your problem: the camera you use to render your box2ddebugrenderer ("dbrndr") has screen pixels as units. The dbrndr uses meters as render units. You need to give the dbrndr its own camera in meters. Your current method will draw a 10pixel wide circle at 0 / 4 pixels in the bottom left corner.
Do you create your world with gravity? if yes, the circle instantly falls out of your screen...Yes you do.
You might actually even see your circle for a splitsecond in the lower left corner after starting... given that you render before you do box2d logic.
Please dispose() all objects that you create, otherwise the memory they occupy is not free'd afterwards.
I set a contact listener on my world and for some reason it isn't getting called when fixtures collide. I can confirm that the fixtures are indeed colliding with a box2dDebugRenderer. I have a suspicion that the problem "could" be that each frame for the player, I remove the fixture and add a new one (Because there is no way (that I know of) to resize/re-position fixture). I am adding the listener to the correct world, the world is working correctly, act is being called (ofcourse). Thanks for your help!
This is called each frame in the player class :
private void createFixture(boolean remove) {
if (remove) {
body.destroyFixture(fixture);
}
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.KinematicBody;
bodyDef.position.set(0, 0);
body = world.createBody(bodyDef);
FixtureDef fixtureDef = new FixtureDef();
CircleShape circle = new CircleShape();
circle.setRadius(getWidth() / 2);
circle.setPosition(new Vector2(0, getY() + getHeight() / 2));
fixtureDef.shape = circle;
fixture = body.createFixture(fixtureDef);
circle.dispose();
}
You are missing filterdata in your FixtureDef. You have to set category bits and mask bits.
Try this:
fixtureDef.filter.categoryBits = 1;
fixtureDef.filter.maskBits = 1;