# Libgdx Fine Tune Megaman Movement

With help from my last question, I was able to fix the issue of having a stuttering effect if you keep hitting jump, while jumping.

I believe I have managed to match moving on the X axis and the physics behind jumping, but I have ran into another hurdle. I'm hoping someone might be able to point out what I am missing.

At this point, the jump looks right, but the collision logic allows Megaman to pass through the floor and stop with his head just under the floor.

EX. Before: After:

Any assistance would be greatly appreciated. I'm really exciting to be learning Libgdx. :)

Megaman.java

package com.mygdx.game;

public class Megaman extends Sprite implements InputProcessor
{
/**the movement velocity*/
private Vector2 velocity = new Vector2();

private float speed = 60 * 1.375f;

private float gravity = 0;
private float jumpV = 4.75f;
private static float GRAVITYCONST = -.25f;
private boolean canJump;
private boolean released;
private boolean movingX;
private int movingLR = 1;
private boolean jumping;

private TiledMapTileLayer collisionLayer;

public Megaman(Sprite sprite, TiledMapTileLayer collisionLayer)
{
super(sprite);
this.collisionLayer = collisionLayer;

}

@Override
public void draw(Batch spriteBatch)
{
update(Gdx.graphics.getDeltaTime());
super.draw(spriteBatch);
}

public void update(float delta)
{
// apply gravity
setY(getY() + gravity);

// clamp velocity
if(gravity < -7.0f)
gravity = -7.0f;

// save old position
float oldX = getX(), oldY = getY();
boolean collisionX = false, collisionY = false;

// move on x
if(movingLR == -1) // going left
collisionX = collidesLeft();
else if(movingLR == 1) // going right
collisionX = collidesRight();

// react to x collision
if((collisionX == false) && (movingX == true)) {
if(movingLR == -1)
{
setX(getX() - 1.375f);
}
else if(movingLR == 1)
{
setX(getX() + 1.375f);
}
}

if(jumping == false){ // going down
canJump = collidesBottom();
collisionY = collidesBottom();
released = collidesBottom();
}else if(jumping == true) // going up
{
collisionY = collidesTop();
setY(getY() + (jumpV += GRAVITYCONST));
}

// react to y collision
if((collisionY == true) && (jumping = true)) {
setY(oldY);
jumpV = 4.75f;
}
}

public Vector2 getVelocity() {
return velocity;
}

public void setVelocity(Vector2 velocity) {
this.velocity = velocity;
}

public float getSpeed() {
return speed;
}

public void setSpeed(float speed) {
this.speed = speed;
}

public float getGravity() {
return gravity;
}

public void setGravity(float gravity) {
this.gravity = gravity;
}

public TiledMapTileLayer getCollisionLayer() {
return collisionLayer;
}

public void setCollisionLayer(TiledMapTileLayer collisionLayer) {
this.collisionLayer = collisionLayer;
}

@Override
public boolean keyDown(int keycode) {
switch (keycode)
{
case Keys.W:
jumping = true;
if(canJump) {
canJump = false;
}
break;
case Keys.A:
//velocity.x = -speed;
movingX = true;
movingLR = -1;  //moving left
break;
case Keys.D:
//velocity.x = speed;
movingX = true;
movingLR = 1;  //moving right
break;
}
return true;
}

@Override
public boolean keyUp(int keycode) {
switch (keycode)
{
case Keys.W:
if (released == true)
{
//when W is released, set Y velocity to 0
//velocity.y = 0;
released = false;
jumping = true;
}
break;
case Keys.A:
case Keys.D:
//velocity.x = 0;
movingX = false;
break;
}
return true;
}

@Override
public boolean keyTyped(char character) {
return false;
}

@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {

return false;
}

@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
return false;
}

@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
return false;
}

@Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}

@Override
public boolean scrolled(int amount) {
return false;
}

private boolean isCellBlocked(float x, float y) {
Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey("blocked");
}

public boolean collidesRight() {
for(float step = 0; step < getHeight(); step += collisionLayer.getTileHeight() / 2)
if(isCellBlocked(getX() + getWidth(), getY() + step))
return true;
return false;
}

public boolean collidesLeft() {
for(float step = 0; step < getHeight(); step += collisionLayer.getTileHeight() / 2)
if(isCellBlocked(getX(), getY() + step))
return true;
return false;
}

public boolean collidesTop() {
for(float step = 0; step < getWidth(); step += collisionLayer.getTileWidth() / 2)
if(isCellBlocked(getX() + step, getY() + getHeight()))
return true;
return false;

}

public boolean collidesBottom() {
for(float step = 0; step < getWidth(); step += collisionLayer.getTileWidth() / 2)
if(isCellBlocked(getX() + step, getY()))
return true;
return false;
}
}

• Don't know libGDX, don't know Java, but tell me one thing, where are you setting jumping = false again? Atfer setting it true? I think thats why your collisionY has always collidesTop(). May be that is the reason. Feb 17 '16 at 5:33
• You're absolutely right. I never set jumping to false so therefore, collidesDown() never triggers. I'm having difficulty figuring out where/how to change the code to fix it. I've tried a handful of changes, I fix the collision detection, but I get other ambiguous behavior.(EX jump motion only happens while jump button is held or once the jump button is pressed, megaman keeps jumping over and over again). Feb 17 '16 at 17:35
• try to add jumping = false; in this if check if((collisionY == true) && (jumping = true)) { setY(oldY); jumpV = 4.75f; } Feb 17 '16 at 20:19

It seems like your problem is here:

public boolean collidesBottom() {
for(float step = 0; step < getWidth(); step += collisionLayer.getTileWidth() / 2)
if(isCellBlocked(getX() + step, getY()))
return true;
return false;
}


You only detect if the player has hit the floor when the cell inside of him is blocked. To fix this, change the code to:

public boolean collidesBottom() {
for(float step = 0; step < getWidth(); step += collisionLayer.getTileWidth() / 2)
if(isCellBlocked(getX() + step, getY() + playerHeight))
return true;
return false;
}