Zelda/Pokemon esque Grid Walking

Like many before me, I’m making a game in which the game world is stored in a 2D array
The player is able to walk around with the arrow keys, and when the player moves in a direction the game checks to make sure the space the player would like to move is unoccupied, and then moves the player there.

However, I would like movement that is more smooth. Instead of the player simply jumping to the adjacent block, how could I make it such that the place walks to the next block over a period of time?

How have people done this in the past? Thank you.

Which library are you using? What have you got so far?

If you don’t have a game loop, you’ll want to do some reading.



You’ll also need to load/render your tiles somehow.


“Smooth movement” is just a matter of moving your character sprite on a per-pixel basis rather than per-tile. Collision detection could be as simple as adding a “isTileBlocked(x, y)” method.

Slick2D has a very basic “scroller” test which does what you’re looking for: tiled map loading/rendering, smooth player movement, wall collision, centering the camera on the player, etc.
https://bitbucket.org/kevglass/slick/src/tip/trunk/Slick/examples/org/newdawn/slick/examples/scroller/Scroller.java

Here’s what I have.

I too am working on a tile based game, and wanted smooth walking. To get tile based movement with animated walking between tiles, I made it so that when you press a direction, say left, it sets your xDir value to -1, which represents left. It also sets moveDistance to 16, since my tiles are 16x16. Now, on every pass, it will subtract one from moveDistance, and, depending on the xDir and yDir variables, it will change your x or y coordinate.

Checking if done moving to a new tile


     if (moveDistance == 0) {
			newDir = 4;
			xDir = 0;
			yDir = 0;
			
			int tx = 0, ty = 0;
			
			if (listener.turn.down) {
				if (listener.up.down) dir = UP;
				else if (listener.down.down) dir = DOWN;
				else if (listener.left.down) dir = LEFT;
				else if (listener.right.down) dir = RIGHT;
			} else {
				if (listener.up.down) ty = -1;
				else if (listener.down.down) ty = 1;
				else if (listener.left.down) tx = -1;
				else if (listener.right.down) tx = 1;
			}
			
			if (Tile.checkEmpty(x / 16 + tx, y / 16 + ty, true)) {
				Tile.tilesArray[x / 16][y / 16] = Tile.EMPTY;
				Tile.tilesArray[x / 16 + tx][y / 16 + ty] = Tile.PLAYER;
				
				cx = x / 16 + tx;
				cy = y / 16 + ty;
				
				if (ty == -1) newDir = UP;
				if (ty == 1) newDir = DOWN;
				if (tx == -1) newDir = LEFT;
				if (tx == 1) newDir = RIGHT;
			} else {
				if (ty == -1) dir = UP;
				else if (ty == 1) dir = DOWN;
				else if (tx == -1) dir = LEFT;
				else if (tx == 1) dir = RIGHT;
			}
			
			if (newDir != 4) {
				dir = newDir;
				moveDistance = 16;
			}
		}

Moving in the Y direction


     if (yDir != 0) {
			y += yDir;
			
			if (y > Game.HEIGHT / 2 - 9 && y < Level.levelHeight - (Game.HEIGHT / 2) - 7) {
				super.updateOffs(0, yDir);
				if ((y - yoffs) < centerY) {
					yoffs--;
				} else if ((y - yoffs) > centerY) {
					yoffs++;
				}
			}
		} else {
			super.updateOffs(0, yDir);
		}

Moving in the X direction


     if (xDir != 0) {
			x += xDir;
				
			if (x > Game.WIDTH / 2 - 9 && x < Level.levelWidth - (Game.WIDTH / 2) - 7) {
				super.updateOffs(xDir, 0);
				if ((x - xoffs) < centerX) {
					xoffs--;
				} else if ((x - xoffs) > centerX) {
					xoffs++;
				}
			}
		} else {
			super.updateOffs(xDir, 0);
		}

Hope this helps.
-Nate

For smooth move, do interpolation one until the player reach a certain coordinate. There’ll be some pixels off depends on your FPS, just force it down.


x += dx * delta;
y += dy * delta;
...
if (x > targetX) x = targetX;
if (y > targetY) y = targetY;

Your name is Nate, too?

Do you want to move (aka animate) to the tiles, or to jump to them?

I couldn’t remember that it’s called interpolation, haha. And yep! It’s short for Nathaniel, but I don’t really care for that.

Yes as far as I recall that’s the name. I just know it this year too.

Thank you, Nate!
I my prexisting code was pretty different from yours, but I solved in a similar way
What I ended up doing is that when the character starts moving, the “tile coordinate” is changed, although the offset from that coordinate is made large enough such that it appears to not have moved yet. Then on subsequent “steps” I decrease the offset, at which point I keep checking if the object should start moving again. It works beautifully.

Thanks for your help!

You are welcome! Just a few months ago I was on here asking questions every day, and it feels nice to be able to answer someone else’s :slight_smile:

-Nate