2
\$\begingroup\$

I spawn my player he falls hits the ground and starts falling through it slowly. Code:

 package com.pumkinmelon.Systems;

 import com.badlogic.ashley.core.ComponentMapper;
 import com.badlogic.ashley.core.Entity;
 import com.badlogic.ashley.core.Family;
 import com.badlogic.ashley.systems.IteratingSystem;
 import com.badlogic.gdx.graphics.OrthographicCamera;
 import com.badlogic.gdx.maps.MapLayer;
 import com.badlogic.gdx.maps.MapObjects;
 import com.badlogic.gdx.maps.objects.RectangleMapObject;
 import com.badlogic.gdx.maps.tiled.TiledMap;
 import com.badlogic.gdx.math.Rectangle;
 import com.badlogic.gdx.math.Vector2;
 import com.pumkinmelon.Components.HitBox;
 import com.pumkinmelon.Components.Player;
 import com.pumkinmelon.Components.Position;
 import com.pumkinmelon.Components.Velocity;

 public class CollisionSystem extends IteratingSystem {

    ComponentMapper<HitBox> Box;
    ComponentMapper<Position> Pos;
    ComponentMapper<Velocity> Vel;
    ComponentMapper<Player> Player;

TiledMap map;

private OrthographicCamera cam;



public CollisionSystem(TiledMap map, OrthographicCamera cam) {
    super(Family.all(HitBox.class, Position.class, Velocity.class).get());

    Box = ComponentMapper.getFor(HitBox.class);
    Pos = ComponentMapper.getFor(Position.class);
    Vel = ComponentMapper.getFor(Velocity.class);
    Player = ComponentMapper.getFor(Player.class);

    this.map = map;
    this.cam = cam;
}

@Override
protected void processEntity(Entity e, float dt) {
    HitBox box = Box.get(e);
    Position pos = Pos.get(e);
    Velocity vel = Vel.get(e);
    Player player = Player.get(e);

    Vector2 Topright = new Vector2(box.rect.x + box.rect.width, box.rect.y + box.rect.height);
    Vector2 bottomleft = new Vector2(box.rect.x, box.rect.y);

    MapLayer collisionObjectLayer =  map.getLayers().get(1);
    MapObjects objects = collisionObjectLayer.getObjects();

    for (RectangleMapObject rectangleObject : objects.getByType(RectangleMapObject.class)) {
        Rectangle rectangle = rectangleObject.getRectangle();

        if(player.falling) {
            if(rectangle.contains(bottomleft)) {
                vel.velY = 0;
                player.falling = false;
                player.canjump = true;
                player.falling = false;
            }
        }

        if(!player.falling) {
            if(!rectangle.contains(bottomleft)) {
                player.falling = true;
            }
        }

        if(rectangle.contains(Topright)) {
            vel.velX = 0;
        }
    }

    cam.position.x = pos.pos.x + box.rect.width / 2;
    cam.position.y = pos.pos.y;




    box.rect.x = pos.pos.x;
    System.out.println(box.rect.x);
    box.rect.y = pos.pos.y;
    System.out.println(box.rect.y);
    System.out.println("falling " + player.falling);
    System.out.println("Can Jump " + player.canjump);



  }

}

.

package com.pumkinmelon.Systems;

import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IteratingSystem;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.pumkinmelon.Components.Player;
import com.pumkinmelon.Components.Position;
import com.pumkinmelon.Components.Velocity;

public class VelocitySystem extends IteratingSystem {

ComponentMapper<Velocity> Vel;
ComponentMapper<Position> Pos;
ComponentMapper<Player> Player;

float G = -15f;

@SuppressWarnings("unchecked")
public VelocitySystem() {
    super(Family.all(Velocity.class, Position.class, Player.class).get());


    Vel = ComponentMapper.getFor(Velocity.class);
    Pos = ComponentMapper.getFor(Position.class);
    Player = ComponentMapper.getFor(Player.class);

}

@Override
protected void processEntity(Entity e, float dt) {
    Velocity vel = Vel.get(e);
    Position pos = Pos.get(e);
    Player player = Player.get(e);

    if(player.falling) {
        vel.velY += G * dt;
    }
    else vel.velY = 0;
    System.out.println("Falling velSystem " + player.falling);

    pos.pos.y += vel.velY;
    pos.pos.x += vel.velX;


    System.out.println("posY" + pos.pos.y);
    System.out.println("velY" + vel.velY);

  }

}

I think the problem is that when i check for collision i check too many rectangles. I'm i right?

If i am or not i can't fix this i have tried for so long.

\$\endgroup\$
1
  • \$\begingroup\$ The fact the player slowly falls through the floor could indicate that the collision detection procedure runs in the wrong order. If it runs in order: check for collisions -> apply gravity -> update position, that could explain the sinking behavior. Typically you'll want to apply all forces first, and then perform collision checking using the final velocity vector, right before updating the position. I'd suggest running through your code and checking if perhaps the velocity is reset to 0 too late, after the player has already been moved into the ground. \$\endgroup\$ Oct 21, 2017 at 10:13

1 Answer 1

0
\$\begingroup\$

I believe it is as you say, you check for too many rectangles, specifically you check rectangles, presumably find one that sets player.falling to false, then you keep checking rectangles and you find one that is not directly under the player which sets player.falling to true.

So what you want to do is stop checking rectangles if you find one under the player. You can use the break keyword to do that like so:

if(player.falling) {
    if(rectangle.contains(bottomleft)) {
        vel.velY = 0;
        player.falling = false;
        player.canjump = true;
        player.falling = false;
        break;
    }
}

When the break line runs the for loop stops immediately and the next line after it is executed. In this case, cam.position.x = pos.pos.x + box.rect.width / 2;.

Edit

You essentially want the player to fall unless there's a block under them right? Looking at the code some more, I think you can simplify by removing these lines:

if(!player.falling) {
    if(!rectangle.contains(bottomleft)) {
        player.falling = true;
    }
 }

and adding player.falling = true; just before the for loop. In that case, the if(player.falling) check is unnecessary, (keep the part inside it of course).

\$\endgroup\$
5
  • \$\begingroup\$ Works but now i can't jump. \$\endgroup\$ Oct 20, 2017 at 23:13
  • \$\begingroup\$ Are the printlns you have in processEntity showing "falling false" and "Can Jump false" somehow? \$\endgroup\$
    – Ryan1729
    Oct 20, 2017 at 23:20
  • \$\begingroup\$ No it says that it is not falling and it can jump i think as soon as i jump the for loop sets the velY to 0. \$\endgroup\$ Oct 21, 2017 at 1:30
  • \$\begingroup\$ It is hard to tell without seeing more code, but what if instead of setting player.falling to true you only run the loop if (player.falling)? \$\endgroup\$
    – Ryan1729
    Oct 21, 2017 at 1:41
  • \$\begingroup\$ i did it. I had too get rid of the else at the end of the gravity loop \$\endgroup\$ Oct 23, 2017 at 21:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .