Box2DBody not rendering LibGDX - java

I am trying to render a body, but it is not working. Other bodies render but this one won't. Here is the code in the Core class.
#Override
public void create () {
cam = new OrthographicCamera();
cam.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
b2dCam = new OrthographicCamera();
b2dCam.setToOrtho(false, Gdx.graphics.getWidth() / PPM, Gdx.graphics.getHeight() / PPM);
world = new World(new Vector2(0, -9.81f), true);
rend = new Box2DDebugRenderer();
batch = new SpriteBatch();
entity = new CircleEntity(world, 100, 200, 10, BodyType.DynamicBody);
entity.initBodyVariables(.1f, .1f, .1f);
//entity.attachSprite("badlogic.jpg");
BodyFactory.createBox(world, -1, 1f, 10000, .01f, BodyType.StaticBody, 1, 0, 0, "");
RopeJoint j = new RopeJoint(200,300, world);
j.create(4, 30);
}
#Override
public void render () {
b2dCam.update();
cam.update();
world.step(1/60f, 6, 2);
entity.update();
batch.setProjectionMatrix(b2dCam.combined);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
rend.render(world, b2dCam.combined);
batch.begin();
entity.render(batch);
batch.end();
}
Here is the code for the bodyFactory:
public static Body createBox(World world, float x, float y, float width,
float height, BodyType type, float density, float friction, float restitution, Object data){
bodyDef = new BodyDef();
bodyDef.type = type;
bodyDef.position.set(new Vector2(x, y));
body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(width / Core.PPM, height / Core.PPM);
fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = density;
fixtureDef.friction = friction;
fixtureDef.restitution = restitution;
fixture = body.createFixture(fixtureDef);
fixture.setUserData(data);
shape.dispose();
return body;
}
When creating the box using this code, it renders it. I tried creating another body like this (in the CircleEntity class):
public class CircleEntity extends EntityParent {
/**
*
* #param world
* of game
* #param x
* position
* #param y
* position
* #param type
* of body (static, kinematic, dynamic)
*/
public CircleEntity(World world, float x, float y, float radius, BodyType type) {
super(world, x, y, radius, type);
createBody();
}
public void createBody() {
bodyDef = new BodyDef();
bodyDef.type = type;
bodyDef.position.set(position);
body = world.createBody(bodyDef);
CircleShape entityShape = new CircleShape();
entityShape.setRadius(radius / Core.PPM);
fixtureDef = new FixtureDef();
fixtureDef.shape = entityShape;
fixtureDef.density = density;
fixtureDef.friction = friction;
fixtureDef.restitution = restitution;
fixture = body.createFixture(fixtureDef);
entityShape.dispose();
}
#Override
public void attachSprite(String filePath) {
super.attachSprite(filePath);
if (entitySprite != null) {
fixture.setUserData(entitySprite);
body.setUserData(entitySprite);
entitySprite.setPosition(position.x - dimensions.x, position.y - dimensions.y);
entitySprite.setSize(dimensions.x, dimensions.y);
}
}
#Override
public void update() {
super.update();
if (entitySprite != null)
entitySprite.setPosition(position.x - dimensions.x, position.y - dimensions.y);
if (Gdx.input.isKeyPressed(Keys.D))
body.applyForce(10, 0, position.x, position.y, true);
if (Gdx.input.isKeyPressed(Keys.A))
body.applyForce(-10, 0, position.x, position.y, true);
}
#Override
public void render(SpriteBatch batch) {
if (entitySprite != null)
entitySprite.draw(batch);
}
}
When I call this(I called it in the first set of code) it doesn't work. I can't figure out why only this entity won't render the circle. The collision still works with the body, so it is in the world but the circle itself I can't see. Any help with this is extremely appreciated.
To be clear, the Box2DBody isn't rendering, the Sprite is irrelevant.

Related

Using regular libgdx shapes with box2d shapes

Before I decided that I wanted to use box2d for all my game physics, I had set up all the non-animated shapes using shaperenderer. I have converted my box2d world and shape to meters at a scale of 32 ppm but all my regular shapes are still drawn with pixels.
Since my box2d circle has been scaled along with the camera, it renders fine with the right size. However, all the shapes that I drew with pixels using shaperenderer are way out of view.
Do I need to redo all of my original shapes with box2d shapes?
Can I just scale all the original shapes with my PPM scaling?
From what I understand, I should be able to just scale all the dimensions of the original shapes by the PPM since I have already scaled the camera?
public class Controller extends Game {
public OrthographicCamera cam;
public ShapeRenderer shape;
public ShapeRenderer circle;
public FitViewport viewport;
public Stage stage;
public World world;
public Body ball;
public Box2DDebugRenderer box2DDebugRenderer;
#Override
public void create() {
cam = new OrthographicCamera();
viewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), cam);
cam.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
shape = new ShapeRenderer();
circle = new ShapeRenderer(); //balls shot from cannon
world = new World(new Vector2(0, 0), true);
box2DDebugRenderer = new Box2DDebugRenderer();
setScreen(new GameScreen(this));
//setScreen(new TitleScreen(this));
}
#Override
public void dispose() {
shape.dispose();
stage.dispose();
circle.dispose();
box2DDebugRenderer.dispose();
world.dispose();
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void resize(int width, int height) {
viewport.update(width, height);
}
public Body createBall(){
Body bBody;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.DynamicBody;
def.position.set(500,500);
def.fixedRotation = true;
bBody = world.createBody(def);
return bBody;
}
}
And here is is the actual game screen that implements all the original shapes and the box2d shapes:
import static com.mygdx.game.Utils.Constants.PPM;
public class GameScreen extends ScreenAdapter {
Controller game;
//x-axis length for top/bottom bar
private float goalWidth;
//y-axis height for back bar
private float goalHeight;
private float goalPostThickness;
//Screen height and width
private float screenWidth;
private float screenHeight;
//How far down/up posts are from edge of screen
private float goalPostTopOffset;
private float goalPostBottomOffset;
private float cannonOriginX; //Variables used for starting position of balls
private float cannonOriginY;
float ballX;
float ballY;
public GameScreen (Controller game){
this.game = game;
}
#Override
public void show(){
game.ball = game.createBall();
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(32/2/PPM);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 0.5f;
fixtureDef.friction = 0.4f;
fixtureDef.restitution = 0.6f; // Make it bounce a little bit
// Create our fixture and attach it to the body
Fixture fixture = game.ball.createFixture(fixtureDef);
circle.dispose();
}
#Override
public void render(float delta){
//Logic
screenWidth = Gdx.graphics.getWidth();
screenHeight = Gdx.graphics.getHeight();
goalPostTopOffset = screenHeight/7;
goalPostBottomOffset = goalPostTopOffset * 3;
goalHeight = screenHeight - (goalPostTopOffset + goalPostBottomOffset);
goalWidth = screenWidth / 6;
goalPostThickness = screenWidth / 75;
cannonOriginX = goalWidth / 2; //Variables used for starting position of balls
cannonOriginY = (goalPostThickness*5) / 2;
ballX = 0 + cannonOriginX;
ballY = (goalPostBottomOffset - (goalPostBottomOffset / 4)) + cannonOriginY;
game.world.step(1/60f, 6, 2);
//Draw
game.cam.update();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.box2DDebugRenderer.render(game.world, game.cam.combined.scl(PPM));
game.shape.setProjectionMatrix(game.cam.combined);
drawNonAnimated();
drawAnimated();
}
#Override
public void hide(){
}
//draws stationary objects such as goal posts
public void drawNonAnimated(){
//Top goal bar
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(screenWidth - goalWidth, screenHeight - goalPostTopOffset, goalWidth, goalPostThickness);
game.shape.end();
//Bottom goal bar
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(screenWidth - goalWidth, goalPostBottomOffset, goalWidth, goalPostThickness);
game.shape.end();
//Back goal bar
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(screenWidth - goalPostThickness, goalPostBottomOffset, goalPostThickness, goalHeight);
game.shape.end();
//Cannon platform
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(0, goalPostBottomOffset - (goalPostBottomOffset / 4),goalWidth, goalPostThickness*2);
game.shape.end();
//Cannon
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(0, goalPostBottomOffset - (goalPostBottomOffset / 4), cannonOriginX,
cannonOriginY, goalWidth, goalPostThickness*5, 1, 1, 45);
game.shape.end();
}
public void drawAnimated(){
//Ball(s)
game.circle.setColor(1, 1, 1, 1);
game.circle.begin(ShapeRenderer.ShapeType.Filled);
game.circle.circle(ballX, ballY, goalPostThickness * 2.5f);
game.circle.end();
game.cam.update();
ballX += 1;
}
}
As I mentioned earlier, the circle shape rendered with box2d shows fine with the PPM scale. However, all the shapes that I drew with shaperenderer are off the screen.

Libgdx box2d body overlaps with sprite

I have been puzzling my mind with the code and I've made a huge amount of progress from not doing pixel to meter to now having a body and sprite almost in line however ive reached another point where i can't seem to figure out where I have gone wrong.
As you can see from the image the body is off from the actual sprite, I have a hunch that it might be origin as it the difference is very slight but I can't seem to work out how to get it in line.
My Create method
public class Physics1 extends ApplicationAdapter implements InputProcessor {
SpriteBatch batch;
Sprite sprite;
Texture img;
World world;
Body body;
Box2DDebugRenderer debugRenderer;
Matrix4 debugMatrix;
OrthographicCamera camera;
Vector2 bodyOrigin;
float torque = 0.0f;
boolean drawSprite = true;
final float PIXELS_TO_METERS = 100f;
final float WORLD_WIDTH =100;
final float WORLD_HEIGHT=100;
#Override
public void create() {
Assets.instance.init(new AssetManager());
batch = new SpriteBatch();
bodyOrigin = new Vector2();
sprite = new Sprite();
sprite.setRegion(Assets.instance.tyre.tyre);
sprite.setSize(12,12);
sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
sprite.setPosition(50-sprite.getWidth()/2,25);
Gdx.app.log("Physics1", "Sprite positions"+ -sprite.getWidth()/2+ " ,"+ -sprite.getHeight()/2);
world = new World(new Vector2(0, 0f),true);
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
BodyEditorLoader load = new BodyEditorLoader(Gdx.files.internal("levels/pittstop.json"));
bodyDef.position.set(sprite.getX()/PIXELS_TO_METERS,sprite.getY()/PIXELS_TO_METERS);
Gdx.app.log("Physics1", "Body positions calculations"+ sprite.getX() +" "+ sprite.getWidth()/2);
Gdx.app.log("Physics1", "Body positions"+ bodyDef.position);
body = world.createBody(bodyDef);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.density = 0.1f;
fixtureDef.friction = 0.0f;
fixtureDef.restitution = 0.0f;
float scale =0.2f;
load.attachFixture(body, "tyre", fixtureDef, scale);
Gdx.app.log("Physics1"," Orgin of body" +load.getOrigin("tyre", scale).cpy());
bodyOrigin = load.getOrigin("tyre", scale).cpy();
body.setUserData("tyre");
Gdx.input.setInputProcessor(this);
debugRenderer = new Box2DDebugRenderer();
camera = new OrthographicCamera(WORLD_WIDTH,WORLD_HEIGHT);
Gdx.app.log("Physics1", "camera "+ camera.viewportWidth+" "+camera.viewportHeight);
camera.position.set(WORLD_WIDTH / 2f, WORLD_HEIGHT / 2f, 0);
Gdx.app.log("Physics1", "camera "+ camera.viewportWidth+" "+camera.viewportHeight);
}
My render method
public void render() {
camera.update();
world.step(1f/60f, 6, 2);
body.applyTorque(torque,true);
sprite.setPosition((body.getPosition().x * PIXELS_TO_METERS),
(body.getPosition().y * PIXELS_TO_METERS))
;
sprite.setRotation((float)Math.toDegrees(body.getAngle()));
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
debugMatrix = batch.getProjectionMatrix().cpy().scale(PIXELS_TO_METERS,
PIXELS_TO_METERS, 0);
batch.begin();
if(drawSprite)
batch.draw(sprite, sprite.getX(), sprite.getY(),bodyOrigin.x,
bodyOrigin.y,
sprite.getWidth(),sprite.getHeight(),sprite.getScaleX(),sprite.
getScaleY(),sprite.getRotation());
batch.end();
debugRenderer.render(world, debugMatrix);
}
False alarm, turns out in physics editor you have the opportunity to change the origin of the body you are drawing up, just by clicking around I was able to move the origin to the centre and there you have it.

libGDX orthographic camera view size (with Box2D)

I have next easy class with one ball and four walls around screen:
SpriteBatch batch;
Box2DDebugRenderer debugRenderer;
World world;
OrthographicCamera camera;
public float VIRTUAL_WIDTH = 720f;
public float VIRTUAL_HEIGHT = 1280f;
#Override
public void create () {
batch = new SpriteBatch();
camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
world = new World(new Vector2(0, -9), true);
debugRenderer = new Box2DDebugRenderer();
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
CircleShape circleShape = new CircleShape();
circleShape.setRadius(50);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circleShape;
fixtureDef.restitution = 1;
Body body = world.createBody(bodyDef);
body.createFixture(fixtureDef);
createWall(0f, -VIRTUAL_HEIGHT/2, VIRTUAL_WIDTH/2, 30f);
createWall(0f, VIRTUAL_HEIGHT/2, VIRTUAL_WIDTH/2, 30f);
createWall(-VIRTUAL_WIDTH/2, 0f, 30f, VIRTUAL_HEIGHT/2);
createWall(VIRTUAL_WIDTH/2, 0f, 30f, VIRTUAL_HEIGHT/2);
}
private void createWall(float x, float y, float hx, float hy){
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.position.set(x, y);
PolygonShape polygonShape = new PolygonShape();
polygonShape.setAsBox(hx, hy);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = polygonShape;
world.createBody(bodyDef).createFixture(fixtureDef);
}
#Override
public void render () {
camera.update();
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(1 / 60.0f, 8, 3);
batch.setProjectionMatrix(camera.combined);
batch.begin();
debugRenderer.render(world, camera.combined);
batch.end();
}
And it's do next screen on my device (maybe not perfect screenshot):
The screen is slightly shifted to the left, it's because rounding errors?
UPDATE:
Instead of this
public float VIRTUAL_WIDTH = 720f;
public float VIRTUAL_HEIGHT = 1280f;
Try this
public float VIRTUAL_WIDTH = Gdx.graphics.getWidth();
public float VIRTUAL_HEIGHT = Gdx.graphics.getHeight();

Getting the computer to know when a sprite walks over a specific tile in a tmx map

I have a Circle shape that is going to represent the character I will play and control. I have a tmx map, and in the map there are red squares that are meant to represent "fences". The fences are in each corner of the map, inside the fences I have the ground that looks the same as the rest of the ground in the map, but I want to make it so that the game knows when the character is standing on those tiles in the map. can anyone help me? I don't know if it will help but here is the code:
public class PlayScreen implements Screen{
private Game game;
private OrthographicCamera gamecam;
private Viewport gamePort;
private TmxMapLoader mapLoader;
private TiledMap map;
OrthogonalTiledMapRenderer renderer;
//Box#d variables
private World world;
private Box2DDebugRenderer b2dr;
private Hero hero;
private ArrayList<Rectangle> specGroundList;
private boolean heroOnGround;
public PlayScreen(BasicGame game){
this.game = game;
gamecam = new OrthographicCamera();
gamePort = new FitViewport(BasicGame.V_WIDTH, BasicGame.V_HEIGHT, gamecam);
mapLoader = new TmxMapLoader();
map = mapLoader.load("Basic Map.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
gamecam.position.set(gamePort.getWorldWidth() / 2, gamePort.getWorldHeight() / 2, 0);
world = new World(new Vector2(0, 0), true);
b2dr = new Box2DDebugRenderer();
hero = new Hero(world, this);
specGroundList = new ArrayList<Rectangle>();
world.setContactListener(new WorldContactListener());
BodyDef bdef = new BodyDef();
PolygonShape shape = new PolygonShape();
FixtureDef fdef = new FixtureDef();
Body body;
//create fence bodies/fixtures
for(MapObject object: map.getLayers().get(3).getObjects().getByType(RectangleMapObject.class)){
Rectangle rect = ((RectangleMapObject) object).getRectangle();
bdef.type = BodyDef.BodyType.StaticBody;
bdef.position.set(rect.getX() + rect.getWidth() / 2, rect.getY() + rect.getHeight() / 2);
body = world.createBody(bdef);
shape.setAsBox(rect.getWidth() / 2, rect.getHeight() / 2);
fdef.shape = shape;
body.createFixture(fdef);
}
//create special ground bodies/fixtures
for(MapObject object: map.getLayers().get(2).getObjects().getByType(RectangleMapObject.class)) {
Rectangle rect = ((RectangleMapObject) object).getRectangle();
bdef.type = BodyDef.BodyType.StaticBody;
bdef.position.set(rect.getX() + rect.getWidth() / 2, rect.getY() + rect.getHeight() / 2);
body = world.createBody(bdef);
shape.setAsBox(rect.getWidth() / 2, rect.getHeight() / 2);
fdef.shape = shape;
body.createFixture(fdef);
}
}
#Override
public void render(float delta) {
update(delta);
// Clear the game screen with Black
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
b2dr.render(world, gamecam.combined);
}
#Override
public void show() {
}
public void handleInput(float dt){
if(Gdx.input.isTouched()) {
// gamecam.position.x += 100 * dt;
gamecam.position.y -= 100 * dt;
}
}
public void update(float dt){
handleInput(dt);
world.step(1/60f, 6, 0);
hero.update(dt);
for(Rectangle rect: specGroundList){
}
gamecam.update();
renderer.setView(gamecam);
}
#Override
public void resize(int width, int height) {
gamePort.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
public Viewport getGamePort() {
return gamePort;
}
}
Assuming your hero has a known position, and your regions of special ground are oriented rectangles then can't you just use a boolean function that returns something along the lines of:
Hero.x > rectangle.left & Hero.x < rectangle.right & hero.y > rectangle.bottom & hero.y < rectangle.top

Draw and moving shape issues

I got an issues concerning the vertices of my shape.
The origin is at the top left corner (0,0) when I set the position of the bodyDef at 1, 1 bodyDef.position.set(position.x, position.y) the body do a translation diagonally by applying a vector (1,1) and I don't get it why ... can you help me ?
public class Player {
private Body body;
public Player(World world, Vec2 position) {
BodyDef bodyDef = new BodyDef();
bodyDef.position.set(position.x, position.y);
bodyDef.type = BodyType.DYNAMIC;
PolygonShape shapeShip = new PolygonShape();
Vec2[] verticesShip = {
new Vec2(0.0f, -10.0f),
new Vec2(10.0f, 10.0f),
new Vec2(-10.0f, 10.0f)
};
shapeShip.set(verticesShip, verticesShip.length);
FixtureDef fixtureDefShip = new FixtureDef();
fixtureDefShip.shape = shapeShip;
fixtureDefShip.density = 0.5f;
fixtureDefShip.friction = 0.3f;
fixtureDefShip.restitution = 0.5f;
body = world.createBody(bodyDef);
body.createFixture(fixtureDefShip);
}
public void draw(Graphics2D graphics, int width, int height) {
PolygonShape polygonShape = (PolygonShape) body.getFixtureList().getShape();
Vec2[] vertices = polygonShape.getVertices();
for(int i = 0; i < polygonShape.getVertexCount(); i++) {
Vec2 vertice = vertices[i];
vertices[i] = body.getWorldPoint(vertice);
System.out.println(body.getWorldCenter());
}
DrawShape.drawPolygon(graphics, polygonShape.getVertices(), polygonShape.getVertexCount(), Color.WHITE);
}
public void forward() {
Vec2 force = new Vec2(0.0f, 10.0f);
Vec2 point = body.getPosition();
body.applyForce(force, point);
}
public void rotateLeft() {
float angle = (float) Math.toDegrees(body.getAngle()) % 360;
body.setTransform(body.getPosition(), (float) Math.toRadians(--angle));
}
public void rotateRight() {
float angle = (float) Math.toDegrees(body.getAngle()) % 360;
body.setTransform(body.getPosition(), (float) Math.toRadians(++angle));
}
public Body getBody() {
return body;
}
}
public void draw(Graphics2D graphics, int width, int height) {
PolygonShape polygonShape = (PolygonShape) body.getFixtureList().getShape();
Vec2[] vertices = polygonShape.getVertices();
Vec2[] verticesTransform = new Vec2[polygonShape.getVertexCount()];
for(int i = 0; i < polygonShape.getVertexCount(); i++) {
verticesTransform[i] = body.getWorldPoint(vertices[i]);
System.out.println(verticesTransform[i]);
}
DrawShape.drawPolygon(graphics, verticesTransform, verticesTransform.length, Color.WHITE);
}

Categories