Reputation: 179
In the game I'm trying to code I got to have two bodies. One StaticBody and one DynamicBody. I want to have the DynamicBody on top of the StaticBody. Somehow all I get is this:
Is it possible that the viewports lower, left corner isn't at 0,0? And why can't the DynamicBody get on top of the StaticBody?
Gamescreen.java
package com.joelbrun.jetskirider.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.utils.Scaling;
import com.badlogic.gdx.utils.viewport.ScalingViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
public class Gamescreen implements Screen {
private static final float TIMESTEP = 1 / 60;
private static final int VELOCITY_ITERATIONS = 8;
private static final int POSITION_ITERATIONS = 3;
public static final int GAMESCREEN_WIDTH = 1920;
public static final int GAMESCREEN_HEIGHT = 720;
public static final int OBSTACLE_TYPES = 5;
private static final int WATER_HEIGHT = 200;
private static final float JETSKI_BOX_X = 200;
private static final float JETSKI_BOX_Y = 100;
private World world;
private Box2DDebugRenderer debugRenderer;
public Texture jetski, wave;
public Sprite background;
public SpriteBatch batch;
public OrthographicCamera camera;
public Label score;
Viewport viewport;
@Override
public void show() {
world = new World(new Vector2(0, -9.81f), true);
debugRenderer = new Box2DDebugRenderer();
Texture[] texture = new Texture[OBSTACLE_TYPES];
//Textures
for (int i=0; i<OBSTACLE_TYPES; i++){
texture[i] = new Texture(Gdx.files.internal("game/obstacles/obstacle" + Integer.toString(i+1)+".png"));
}
background = new Sprite(new Texture("game/background.png"));
jetski = new Texture("game/jetski.png");
wave = new Texture("game/water1.png");
batch = new SpriteBatch();
//Camera & Viewport
camera = new OrthographicCamera();
viewport = new ScalingViewport(Scaling.fillY, GAMESCREEN_WIDTH, GAMESCREEN_HEIGHT, camera);
viewport.apply();
camera.position.set(GAMESCREEN_WIDTH / 2, GAMESCREEN_HEIGHT / 2, 0);
//body definition Water
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.position.set(0, 0);
Body body = world.createBody(bodyDef);
//shape
PolygonShape box = new PolygonShape();
box.setAsBox(2560, WATER_HEIGHT);
//fixture definition
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = box;
fixtureDef.density = 1000;
fixtureDef.friction = .25f;
fixtureDef.restitution = .1f;
Fixture fixture = body.createFixture(fixtureDef);
box.dispose();
//Jetski
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(1280,WATER_HEIGHT + 100);
Body jetskiObject = world.createBody(bodyDef);
PolygonShape jetskiBox = new PolygonShape();
jetskiBox.setAsBox(JETSKI_BOX_X, JETSKI_BOX_Y);
fixtureDef.shape = jetskiBox;
fixtureDef.density = 100;
fixtureDef.friction = 0;
Fixture jetskiFixture = body.createFixture(fixtureDef);
jetskiBox.dispose();
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
debugRenderer.render(world, camera.combined);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.end();
camera.update();
world.step(TIMESTEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
}
@Override
public void resize(int width, int height) {
int SCREEN_WIDTH = width;
int SCREEN_HEIGHT = height;
viewport.setWorldSize(GAMESCREEN_WIDTH, GAMESCREEN_HEIGHT);
viewport.update(SCREEN_WIDTH, SCREEN_HEIGHT,true);
camera.update();
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
dispose();
}
@Override
public void dispose() {
batch.dispose();
background.getTexture().dispose();
jetski.dispose();
wave.dispose();
world.dispose();
debugRenderer.dispose();
}
}
Upvotes: 1
Views: 1733
Reputation: 54
You should try to use a chainshape instead of a polygonshape for the staticbody. So that the dynamic body will remain in it instead of "teleporting" out. The dynamic body mustn't intersect the staticbody when it is created. Hope it will work!
Upvotes: 0
Reputation: 2667
You are using Box2D wrong. You should scale down Box2D to a small world because, without doing this, physics interaction will be 1px = 1m and an 1920 x 720 is too big (this will be reflected as your bodies moving too slow, because they are too big).
Check your code:
PolygonShape box = new PolygonShape();
box.setAsBox(2560, WATER_HEIGHT); // <- your water object dimensions
and
PolygonShape jetskiBox = new PolygonShape();dimensions
jetskiBox.setAsBox(JETSKI_BOX_X, JETSKI_BOX_Y); // <- your jetsky object
Then, check the setAsBox
method:
public void setAsBox(float hx, float hy)
Parameters:
hx - the half-width.
hy - the half-height.
(Added emphasis)
So for your water, you are creating an static body of 5120 x 400
and for your jetski 400 x 200
, this values are too high.
I sugest to try with the example that appear in the official wiki but then check sites like this and read the manual to understand how Box2D works. I could extract this:
In particular, Box2D has been tuned to work well with moving objects between 0.1 and 10 meters. So this means objects between soup cans and buses in size should work well. Static objects may be up to 50 meters big without too much trouble.
Being a 2D physics engine, it is tempting to use pixels as your units. Unfortunately this will lead to a poor simulation and possibly weird behavior. An object of length 200 pixels would be seen by Box2D as the size of a 45 story building.
Another thing, I don't know if this affect in someway, but I always do the world.step(...)
first then the debugRenderer.render(...)
at the end, in your code, you have this inverted (maybe this is why your jetski is not being moved).
Upvotes: 0
Reputation: 755
Yes with Box2D the origin is the bottom left corner of the viewport.
You can set the position of your bodies when you are setting up your BodyDef :
bodyDef.position.set(x, y);
And don't forget, in Box2D, the position of your body is the center of the Body. So when you set your PolygonShape as a box like this :
polygonShape.setAsBox(width, height);
Your actual box width will be width*2 and your actual box height will be height*2
Upvotes: 1