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.