Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Help with tile based movement  (Read 3722 times)

0 Members and 1 Guest are viewing this topic.

albert_lazaro

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Help with tile based movement
« on: May 20, 2021, 07:54:08 pm »
Good afternoon,

First I have to say that I have been trying to implement the SMOOTH tile-based movement for five days (I'm trying to add it using clean code).

For the moment, I have implemented a "teleportation movement" where the sprite moves to the next (up, down, left or right) tile without walking, so it goes 16px automatically. When I say next, if I maintain pressed the button it can be more than one tile. Here goes the GIF:



This is done in the GameState, that represents the state where the game occurs. The most important classes are:
Source/World:  this contains the elements that you see on the screen: the NPCs (for the moment one).
Source/TileMap: this builds and renders the tilemap that you see in the gif.
Source/Npc: this is the guy you see on the image.
Source/Player: this sends the Player output to the Npc via a command Queue.

Github: https://github.com/lazaro92/fantasy-maker/tree/develop

My idea to implement the smooth movement is to move the npc via the Player class, in the Player NpcMover struct. While I move the player, in the World class I would like to check if the movement has been completed (so the npc has moved all the exact16px, not one less or more).

Do you have any ideas or examples of a smooth tile-based movement? It would help me a lot :)

----------------

After I implement the movement, I will start with collision detection, so the idea after movement will be that if I press a key, before the Npc starts to move the system will check if the destination tile is available to move in.
« Last Edit: May 20, 2021, 09:08:30 pm by albert_lazaro »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Help with tile based movement
« Reply #1 on: May 21, 2021, 10:28:08 am »
I don't really have the time to go too deep into details, but here's how I see it.

Once a key has been pressed (or is being held), move the player at a fixed speed in the wanted direction.
If the player releases the key, the player will continue in the set direction, until it hits the next center of a tile.
While the characters is still moving and the player presses a key in the opposite direction, then it will immediately switch direction and move until it hits the center of the previous tile.
While the characters is still moving and the player presses a key in an orthogonal direction, then the character keeps moving in the previously set direction, until it reaches the center of the tile and then starts moving up.

For the movement, you can just use the common distance physics formula: velocity * deltaTime = distance
So for every frame you take the deltaTime, multiply it with the velocity and take that value as move distance.

Note: In order to determine whether you're in the "center" of a tile, you'll have to do some position "snapping", since it won't ever hit the center position 100%, but say if it's around +-2 units, you accept it as center.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

albert_lazaro

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Help with tile based movement
« Reply #2 on: May 25, 2021, 08:25:32 pm »
    At the end I solved it!



So from the Player class I send a command which contains the direction to go (left, right, upper, down) and then the Ncp changes his status from wait to move, performing one step in the received direction. Then it goes to the destination tile and changes the state to wait (state which accepts the input).

For the tile move from tile to tile I use the lerp function that I have programmed, where the params are:
  • The origin position
: The center of the origin tile.
  • The destination position
: The center of the destination tile.[/li]
[li]dt: the time it has passed (value in the range of (0,1])[/li]
[/list]

float Npc::lerp(float origin, float dest, float dt)
{
    return origin + dt * (dest - origin);
}

Now the idea is to animate the Npc sprite using a class Animation  that I have in progress, but first I have to do some refactor  :P