[Libgdx] Collision check [Solved]

Hello,

i trying to figure out the best way to make collision check on my code. I would like to add it into onWalk and using getNextPosition to check if the position is walkAble. Monsters & Players share the same logic.

public class Creature {

    protected enum Direction {
        NORTH, EAST, SOUTH, WEST
    }

    protected final String name;
    protected Direction direction;
    private Vector2 targetPosition;
    protected Vector2 position;
    protected float speed;

    private Texture texture = new Texture("badlogic.jpg");

    protected boolean isMoving = false;

    public Creature(String name, Vector2 position) {
        this.name = name;
        this.position = position;
        targetPosition = new Vector2();
        speed = 4f;
        direction = Direction.SOUTH;
    }

    public void onThink(float deltaTime) {
        if (isMoving) {
            onWalk(direction, deltaTime);
        }
    }

    protected void onWalk(Direction direction, float deltaTime) {
        if (targetPosition.isZero()) {
            targetPosition.set(getNextPosition(direction, position));
        }

        if (position.dst(targetPosition) <= 0.1f) {
            isMoving = false;
            position.set(targetPosition);
            targetPosition.setZero();
            return;
        }

        switch (direction) {
            case NORTH:
                position.y += speed * deltaTime;
                break;
            case EAST:
                position.x += speed * deltaTime;
                break;
            case SOUTH:
                position.y -= speed * deltaTime;
                break;
            case WEST:
                position.x -= speed * deltaTime;
                break;
            default:
                break;
        }
    }

    public Vector2 getNextPosition(Direction dir, Vector2 pos) {
        pos = new Vector2(pos.x, pos.y);
        switch (dir) {
            case NORTH:
                pos.y++;
                break;
            case EAST:
                pos.x++;
                break;
            case SOUTH:
                pos.y--;
                break;
            case WEST:
                pos.x--;
                break;
            default:
                break;
        }

        return pos;
    }

    public Vector2 getPosition() {
        return position;
    }

    public boolean isCreature() {
        return true;
    }

    public Texture getTexture() {
        return texture;
    }

    public boolean isPlayer() {
        return false;
    }

    public boolean isMonster() {
        return false;
    }
}

Seems like you are going for smoothed grid based movement, right?

If that’s the case, you would just add in code before starting the movement.

I’m guessing your onThink would have a condition before deciding on where to move a function of isMoveValid, in which case you would test if the square is full.

Are you considering that things can collide only on a tile basis? If so, that’s really easy, it’s just a matter of checking if the target cell contains things that would prevent it from moving, iswall, isenemy, etc… maybe simply isblocked. depends on what you need/

How can i execute a check before it? Since when they are overlaping its already to late. It May get stuck or something.

I understand your question a bit better…

This doesnt really tell me how your map is formatted or anything, so, the specifics on how you would check might be different…



    public void onThink(float deltaTime) {
        if (isMoving) {
            onWalk(direction, deltaTime);
        }
    }

    protected void onWalk(Direction direction, float deltaTime) {
        if (targetPosition.isZero()) {
            targetPosition.set(getNextPosition(direction, position));
        }

        if (position.dst(targetPosition) <= 0.1f) {
            isMoving = false;
            position.set(targetPosition);
            targetPosition.setZero();
            return;
        }

    public Vector2 getNextPosition(Direction dir, Vector2 pos) {
        this.pos.set(pos); //Don't create a new vector each time you want to move, make a class vector instead
        switch (dir) {
            case NORTH:
                pos.y++;
                break;
            case EAST:
                pos.x++;
                break;
            case SOUTH:
                pos.y--;
                break;
            case WEST:
                pos.x--;
                break;
            default:
                break;
        }
        // do your collision check here, 
if (isNextPosition())
if the move is valid return the desired position
if it is blocked return the current position (usually, unless you want the effect of walking into the wall)

    }
}

the is next position would be something like if desired position contains wall, or is flagged as a wall, or whatever then return true otherwise return false.

If you are using a tiled map its like
Cell cell;
cell = tiledmap.getcell(x, y);
I forget exactly…

Another way is to draw rectangles over the walls, then you can make a list of the rectangles and see if the rectangles.contain(desiredposition)

The problem i mostly have is how badly i structured the classes i guess. Since i can only check the overlaps of Rectangles on my GameScreen class and i have no idea what to do from there :confused:

        for (int i = 0; i < blockArray.size; i++) {
            // Fetch the current block
            Creature creature = blockArray.get(i);

            // Clear out the entities to check
            entitiesToCheck.clear();

            // Retrieve the entities we might be able to compare against
            quadTree.retrieve(entitiesToCheck, creature);

            // Check the blocks
            for (Creature spectator : entitiesToCheck) {
                // SPECIAL CASE: No need to check against our self
                if (creature == spectator) {
                    continue;
                }

                if (creature.getRectangle().overlaps(spectator.getRectangle())) {
                    System.out.println("Collision has occured");
                }
            }
        }

ok, so, you have things checking for overlaps that have already occurred, so, all you would need is to do that check on the rectangle representing the desired position.

in other words, find out what the desired position is then run that test on THAT position.

So, the logic is:

  • determine where the collision is going to happen
  • if no collision then move
  • if theres a collision dont move, maybe attack, not sure what you need

I dont think youll have to re-write a whole lot, doesnt look like anything wrong, but you may need to reorganize things.

Well that is the thing i tried. With check if there is overlaps on the nextPosition. Which i got the function. But things still does not work :confused:

Sorry, I’m at a loss for what to suggest next, without looking through the project.

Best bet, Setup a bunch of logging commands (Gdx.app.log(tag, string):wink: this way you can make sure that you are sending and receiving the correct data.

You might be doing something off without realizing it.

Cheers mate, i was able to port your suggestion and works perfectly now.