Help with creating smooth 2D movement

I have been attempting to implement some “smooth feeling” movement for a top-down action type game. The goal is to have the player slow down when changing direction and when stopping. The problem I have is the movement feels very inconsistent. Sometimes the “slow down” period feels very long and other times is feels just right, even though I have tried to code it to be consistent. Frankly it is so subtle it is hard to explain. I have compressed the project and uploaded it here:


If you could open it yourself and try moving the player around you can maybe see what I mean. Any feedback or advice is appreciated.
I believe all the relevant code should be in this section within the Player class:

  //move Player
  void movePlayer() {
    //selecting next Tile
    //if player is within a certain distance of the currentTilePos input is being given
    if (moving) {
      if (pos.dist(currentTilePos) < currentBoard.tileSize/2) {
        //pick possible next tile if there is certain input
        //also change directio variable
        int c = currentCol; //possible col
        int r = currentRow; //possible row
        switch(imd) {
        case 'w':
          c = currentCol;
          r = currentRow -1;
          md = imd;
          break;

        case 'd':
          c = currentCol +1;
          r = currentRow;
          md = imd;
          break;

        case 's':
          c = currentCol;
          r = currentRow +1;
          md = imd;
          break;

        case 'a':
          c = currentCol -1;
          r = currentRow;
          md = imd;
          break;
        }
        //if possible next tile is not out of bounds and not a wall make nextTile 
        if (c < currentBoard.cols && r < currentBoard.rows) {
          Boolean isWall = false;
          int i = 0;
          while (i < currentBoard.walls.size() && isWall == false) {
            Wall wall = currentBoard.walls.get(i);
            if (wall.col == c && wall.row == r) {
              isWall = true;
            }
            i++;
          }
          if (isWall == false) {
            currentCol = c;
            currentRow = r;
            currentTilePos = currentBoard.floor[c][r].pos.copy();
          }
        }
      }
    }

//detect if direction has just changed
    if (md != prevmd) {
      directionChange=true;
    }

//if changing direction
    if (directionChange) {
      //if magnitude of movement vector is less than 1
      if (moveVector.mag() < 1) {
        //direction change process is over, set speed to min for heading in new direction
        directionChange = false;
        speed = minSpeed;
      } else {
        //otherwise apply a slowdown to last frame's move vector and move player
        moveVector.mult(slowRate);
        pos.add(moveVector);
      }
    }

//if player is no longer changing direction
    if (!directionChange) {
      //if player is on the target tile (roughly lol)
      if (PVector.dist(pos, currentTilePos) < currentBoard.tileSize/2) {
        //apply slowing
        speed = speed*slowRate;
        //if speed is under the minimum
        if (speed < minSpeed) {
          //if player is very close to target speed may slow all the way down to zero once it is low enough
          //this prevents weird shaking on the spot h
          if (PVector.dist(pos, currentTilePos) < 2) {
            if (speed < 0.01) {
              speed = 0;
            }
          } else {
            //otherwise stop slowing at min speed until player gets closer to target
            speed = minSpeed;
          }
        }
        //if player has not reached the target tile
      } else {
        //apply acceleration
        speed = speed+accRate;
        //cap at top speed
        if (speed > topSpeed) {
          speed = topSpeed;
        }
      }

//target is center pixel of current tile
      PVector movementTarget = currentTilePos.copy();
      //produce vector from pos to target
      moveVector = PVector.sub(movementTarget, pos);
      //apply current speed
      moveVector.setMag(speed);
      //move player
      pos.add(moveVector);
      //record current input for detecting possible direction change next cycle
      prevmd = md;
    }
  }

However this might not make much sense outside the context of the full project so that is why I have linked it. Thanks for reading!

edit: after further investigation it seems the “moving” variable is false at times even when I am holding a key, causing the player to move to a tile and stop completely before moving to the next when direction is changing. Not very sure how to begin debugging something like this.

The first thing you should try to fix is the method in which you move the player with keys. A well excepted way of doing this is using a boolean[] array in the player class and coding it like this:

void keyPressed() { 

  //player movement input
  //set direction to key pressed
  switch(key) {

    //WASD
  case 'w':
  case 'W':
    santa.moves[0]=true;
    break;

  case 'd':
  case 'D':
    santa.moves[1]=true;
    break;

  case 's':
  case 'S':
    santa.moves[2]=true;
    break;

  case'a':
  case'A':
    santa.moves[3]=true;
    break;
  }
}

All you have to do is add a velocity depending on which moves[] are true, and make sure to do the same in keyReleased()

It would also be a good idea to control all the other key functions this way

  switch(keyCode) {

    //WASD
  case 'W':

Also I’m a little confused by the idea of columns and rows in your player code. Do you only wish to move your player in the x and y axis, but not both at the same time?

the player is on top of a board of floor tiles, when a movement key is pressed it will move towards the center of an adjacent tile. I think you are correct that the issue lies within my method of processing input.