(Java/LibGDX) Weak/Unresponsive Movement
Posted: Fri Jun 09, 2017 8:13 pm
Hello, I am using Box2D for a platformer game with the LibGDX framework on Java. I've been struggling to reach the point where I'm content with the movement of my player. After solving my issue of the player "gliding," all of the movement within my Box2D world was weak and unresponsive to impulses/force/velocity. In other terms, it would take a max velocity of 70F to even move my character at a decent pace (at 7F it is trudging along). Because of this, I wiped all of the Box2D code I wrote and replaced it with code from this example:
http://www.badlogicgames.com/wordpress/?p=2017. Yet, nothing really changed. It would still take a max velocity (movement speed) of 70F to even budge my player.
I was convinced I was doing something wrong outside of Box2D, but, when I disabled other things from updating, the problem persisted.
This is how my code runs: main loop -> UPDATE SECTION -> update time -> step box2d world -> update ashley entity engine -> update my entities -> DRAW SECTION -> update camera position -> draw stage segments -> draw entities -> box2d debug render
Only stepping the world and doing the box2d debug render provided the same results.
Here is my player code:
The only changes I made were removing the MovingPlatform class and storing a Body instance instead and moving the jump mechanics to a separate method that is called externally.
I only have one other body right now, and it is creating using this method:
Here is where I create my world and update it:
This problem came up after another issue was resolved on the java-gaming forums, and a user directed me here.
I am open to further inquiries, thank you.
http://www.badlogicgames.com/wordpress/?p=2017. Yet, nothing really changed. It would still take a max velocity (movement speed) of 70F to even budge my player.
I was convinced I was doing something wrong outside of Box2D, but, when I disabled other things from updating, the problem persisted.
This is how my code runs: main loop -> UPDATE SECTION -> update time -> step box2d world -> update ashley entity engine -> update my entities -> DRAW SECTION -> update camera position -> draw stage segments -> draw entities -> box2d debug render
Only stepping the world and doing the box2d debug render provided the same results.
Here is my player code:
Code: Select all
public Body body;
public Fixture upperFixture, bottomFixture;
public boolean grounded;
public long lastGroundTime;
public Body groundedPlatform;
public float walkSpeed = 2F, maxVelocity = 7F, jumpSpeed = 30F;
@Override
public void update(float deltaTime) {
super.update(deltaTime);
this.grounded = isGrounded();
if(grounded) {
lastGroundTime = System.nanoTime();
} else {
if(System.nanoTime() - lastGroundTime < 100000000) {
grounded = true;
}
}
Vector2 pos = body.getPosition();
Vector2 vel = body.getLinearVelocity();
if(Math.abs(vel.x) > maxVelocity) {
vel.x = Math.signum(vel.x) * maxVelocity;
body.setLinearVelocity(vel);
}
if(!moveLeft && !moveRight) {
body.setLinearVelocity(vel.x * 0.9F, vel.y);
walkTime = 0F;
idleTime += deltaTime;
} else {
idleTime = 0F;
walkTime += deltaTime;
}
if(!grounded) {
upperFixture.setFriction(0F);
bottomFixture.setFriction(0F);
} else {
if(!moveLeft && !moveRight && idleTime > 0.2) {
upperFixture.setFriction(100F);
bottomFixture.setFriction(100F);
} else {
upperFixture.setFriction(0.2F);
bottomFixture.setFriction(0.2F);
}
}
if(moveLeft) {
facing = Direction.LEFT;
body.applyLinearImpulse(-walkSpeed, 0, pos.x, pos.y, true);
}
if(moveRight) {
facing = Direction.RIGHT;
body.applyLinearImpulse(walkSpeed, 0, pos.x, pos.y, true);
}
body.setAwake(true);
}
public void jump() {
if(grounded) {
Vector2 pos = body.getPosition();
Vector2 vel = body.getLinearVelocity();
body.setLinearVelocity(vel.x, 0);
body.setTransform(pos.x, pos.y + 0.01F, 0);
body.applyLinearImpulse(0, jumpSpeed, pos.x, pos.y, true);
}
}
public boolean isGrounded() {
groundedPlatform = null;
World world = stage.getBox2DWorld();
Array<Contact> contacts = world.getContactList();
for(int i = 0; i < contacts.size; i++) {
Contact contact = contacts.get(i);
if(contact.isTouching() && (contact.getFixtureA() == bottomFixture || contact.getFixtureB() == bottomFixture)) {
Vector2 pos = getPosition();
WorldManifold manifold = contact.getWorldManifold();
boolean below = true;
for(int j = 0; j < manifold.getNumberOfContactPoints(); j++) {
below &= (manifold.getPoints()[j].y < pos.y - 1.5F);
}
if(below) {
if(contact.getFixtureA() != null) {
groundedPlatform = contact.getFixtureA().getBody();
}
if(contact.getFixtureB() != null) {
groundedPlatform = contact.getFixtureB().getBody();
}
return true;
}
return false;
}
}
return false;
}
@Override
public void createBodies() {
World world = stage.getBox2DWorld();
BodyDef def = new BodyDef();
def.type = BodyType.DynamicBody;
Body body = world.createBody(def);
float hx = getWidth() / 2F, hy = getHeight() / 2F;
PolygonShape poly = new PolygonShape();
poly.setAsBox(hx, hy - (hx / 2F), new Vector2(0, (hx / 2F)), 0);
upperFixture = body.createFixture(poly, 1);
poly.dispose();
CircleShape circle = new CircleShape();
circle.setRadius(getWidth() / 2F);
circle.setPosition(new Vector2(0, -hy + hx));
bottomFixture = body.createFixture(circle, 0);
body.setBullet(true);
body.setFixedRotation(true);
this.body = body;
}
I only have one other body right now, and it is creating using this method:
Code: Select all
public void createRectangle(World world, float x, float y, float width, float height) {
BodyDef bD = new BodyDef();
bD.type = BodyType.StaticBody;
bD.position.set(x + (width / 2), y + (height / 2));
FixtureDef fD = new FixtureDef();
PolygonShape shape = new PolygonShape();
shape.setAsBox(width / 2, height / 2);
fD.shape = shape;
fD.density = 3F;
Body body = world.createBody(bD);
body.createFixture(fD);
shape.dispose();
bodies.add(body);
}
Code: Select all
public GameStage() {
engine = new Engine();
world = new World(new Vector2(0, -20F), true);
segments = new ArrayList<Segment>();
EntityPlayer player = new EntityPlayer(this, PlayerColor.GREEN);
addEntity(player);
this.focus = player;
addSegment(new SpawnSegment());
}
public void update(float deltaTime) {
world.step(deltaTime, 4, 4);
engine.update(deltaTime);
for(Entity entity : engine.getEntities()) {
if(entity instanceof EntityBase) {
((EntityBase) entity).update(deltaTime);
}
}
}
I am open to further inquiries, thank you.