# 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);
}
}

//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
//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.