javalibgdx2dtop-down

Java 2D Game 'Grid Movement'


I'm using libGDX trying to make a top-down 2D game with movement along the lines of Pokemon. However, I'm not sure how to implement this.

I want the player to be able to press a key (ie: arrow keys or WASD) in order to move, however, when the player releases the key, I don't want the character to stop moving until it's position falls along a grid of cells that consist of 32x32 pixel squares.

So how would I go about creating an 'invisible' grid of 32x32 pixel cells and making my character only stop moving whenever it's on top of one of those cells?

So far I've only done by-pixel movement. Which, I've contemplated I could just have a boolean stating whether the character was moving and just change that if the character landed on the right area, but I haven't thought of any way to implement that.

Here's the method that I'm using for my by-pixel movement (the libGDX covers key input and it draws the sprite based on where the player's bounding box is):

public void generalUpdate() {
    if(Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT)) {
        if (anim_current == Assets.anim_walkingLeft)
            if(player.collides(wall.bounds)) {
                player.bounds.x += 1;
            }
            else
                player.dx = -1;
        else
            anim_current = Assets.anim_walkingLeft;
        Assets.current_frame = anim_current.getKeyFrame(stateTime, true);
    }
    else if (Gdx.input.isKeyPressed(Keys.D) || Gdx.input.isKeyPressed(Keys.RIGHT)) {
        if (anim_current == Assets.anim_walkingRight)
            if(player.collides(wall.bounds)) {
                player.bounds.x -= 1;
            }
            else
                player.dx = 1;
        else
            anim_current = Assets.anim_walkingRight;
        Assets.current_frame = anim_current.getKeyFrame(stateTime, true);
    }
    else if (Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.UP)) {
        if (anim_current == Assets.anim_walkingUp)
            if(player.collides(wall.bounds)) {
                player.bounds.y += 1;
            }
            else
                player.dy = -1;
        else
            anim_current = Assets.anim_walkingUp;
        Assets.current_frame = anim_current.getKeyFrame(stateTime, true);
    }
    else if (Gdx.input.isKeyPressed(Keys.S) || Gdx.input.isKeyPressed(Keys.DOWN)) {
        if (anim_current == Assets.anim_walkingDown)
            if(player.collides(wall.bounds)) {
                player.bounds.y -= 1;
            }
            else
                player.dy = 1;
        else
            anim_current = Assets.anim_walkingDown;
        Assets.current_frame = anim_current.getKeyFrame(stateTime, true);
    }
    else {
        Assets.current_frame = anim_current.getKeyFrames()[0];
        player.dx = player.dy = 0;
    }

    player.bounds.x += player.dx;
    player.bounds.y += player.dy;
}

Solution

  • Your code is a huge mess, and I don't want to try to fix it, but here's generally how you can approach your problem:

    Have a boolean to represent if you are moving. Let's call it isMoving. Also have a method to store direction (maybe as an integer between 0 and 3?). Let's call it dir.


    When you press a key, set isMoving to true. If you are aligned with the grid, update dir to the direction of the key you press as well.

    If you aren't holding keys, set isMoving to false.

    When you get to moving your character, if isMoving is true and they are not aligned with the grid, then move is the direction represented by dir. If they are aligned with the grid, then set isMoving to false and don't move.


    // Only including one key, process is same for others.
    if (rightKey) {
        isMoving = true;
        if (aligned)
            dir = 0;
    } /* chain other keys in here */ else {
        isMoving = false;
    }
    
    if (isMoving) {
        if (!aligned) {
            move(dir);
            render(dir);
        } else {
        }
    }
    

    I just realized nearing the end that it might not work in it's current state :/. I hope this at least gives you an idea of what to do. I'll try to revise it some more...