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

Author Topic: Complicated movement question  (Read 5035 times)

0 Members and 1 Guest are viewing this topic.

two-tone-

  • Newbie
  • *
  • Posts: 23
    • View Profile
Complicated movement question
« on: February 01, 2014, 10:16:33 am »
My player sprite has a total of 8 different locations it could be on screen based on keyboard input.  If a player presses the A key it sends the sprite to the "A" location. If they press the L key it sends the sprite to the "L" location.

My question is how do I create a movement function that can send the player to any of the 8 locations from any of the other 7 locations without having to write 64 if/else-if statements?  And how can I make sure that it is extensible in the future? So that if I need to bump up or down the amount I don't have to write or remove a dozen statements.
« Last Edit: February 01, 2014, 10:23:03 am by two-tone- »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Complicated movement question
« Reply #1 on: February 01, 2014, 11:00:47 am »
Well it's a bit hard to tell, what do you mean with "sending the player"? If you simply want to move the player to a certain position, all you'd need to do, is map the keys with wanted location, e.g. something like this:

std::map<sf::Keyboard::Key, sf::Vector2f> key_location;
key_location.insert(std::make_pair(sf::Keyboard::A, sf::Vector2f(20.f, 40.f)));

And then test the KeyPressed/KeyReleased event against the map.
« Last Edit: February 01, 2014, 11:04:25 am by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

two-tone-

  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: Complicated movement question
« Reply #2 on: February 01, 2014, 12:43:14 pm »
I am not entirely sure what is going on here.  The map container is something I've been struggling with I'll gladly admit.

Azaral

  • Full Member
  • ***
  • Posts: 110
    • View Profile
Re: Complicated movement question
« Reply #3 on: February 02, 2014, 04:26:30 am »
I am not entirely sure what is going on here.  The map container is something I've been struggling with I'll gladly admit.

Maps work like vectors, but instead of using numbers to access elements at an index, you can use any data type that can be sorted or hashed. There are three types of map: map, unordered_map, and multi_map. Map stores items in a sorted list inside and is good if you need the data to be stored in a sorted manner. Unordered maps use hashing and are best for random access, it is O(1). Multi map is like a regular map, except each index in the map can store more than one thing.

To access something in a map, it is just like a vector, except you use a variable of the type you specified when you created the map.

//adding on to exploiters example
std::map<sf::Keyboard::Key, sf::Vector2f> key_location;
key_location.insert(std::make_pair(sf::Keyboard::A, sf::Vector2f(20.f, 40.f)));

//access is done like this

 playerPosition =  key_location[ sf::Keyboard::A ] //sets player position (assuming its a sf::Vector2f) to 20,40
 

Maps also have function for finding if a key already exists or not called find. It will return an pointer to the iterator of the key if it exists, or it will return end() if it does not.

so you would just need to save the key pressed, check if it exists in the map, and if it does, then set the player's position equal to the value you stored inside.

Hope that helps.


two-tone-

  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: Complicated movement question
« Reply #4 on: February 02, 2014, 10:14:23 am »
Hmm, I understand now but this doesn't solve my original issue.  I realize now that I have not explained my issue very well, so this is all my fault.  I'll restart.

I have 8 locations the player could be on screen and I need to figure out the logic needed to animate the sprite/rect going from on point to another without having write out logic for each of the 64 different paths the sprite could take.

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Complicated movement question
« Reply #5 on: February 02, 2014, 10:30:07 am »
if you know your current position and your destination, you can work out the path like this:

if(someKeyPressed) //destination has been updated
{
    m_path = normalize(destination[keyPressed] - m_currentPostion);
}

move(m_path * speed * dt);

 

two-tone-

  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: Complicated movement question
« Reply #6 on: February 02, 2014, 11:59:46 am »
Could you explain your code for me?

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Complicated movement question
« Reply #7 on: February 02, 2014, 12:44:40 pm »
The code assumes you have a map of key presses and locations like mentioned above. When you get a new key press, and hence a new location you can work out the path as a 2d vector by subtracting the current position from the destination. Normalize this (reduce it to a length of 1) and store it as a member variable. Normalizing usually involves a square root so you want to do this as little as possible, so you store the result rather than calculating it each frame. Then you move by the path vector multiplied by the speed you want to travel, usually units per second, multiplied by the frame time (dt). You'll then keep moving along this path until you either set a new path (from another key press) or you set the path to zero when you reach the current destination.

two-tone-

  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: Complicated movement question
« Reply #8 on: February 03, 2014, 07:20:52 am »
Questions: Isn't normalization just finding the square root of of C^2 from Pythagoras' theorem (Never took geometry so I know very little and the resources online suck)? Wouldn't that then mean that your m_path is just a single float? How does move() use that use that data to direct the transformable? I'm assuming you're using the move() function from the sf::Transformable class, if not please clarify as I have even less of a clue than I already do.

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Complicated movement question
« Reply #9 on: February 03, 2014, 10:42:57 am »
Not quite. You use Pythagoras to find the length (magnitude) of the vector, then divide the vector's x and y components by it to reduce the magnitude to 1. This is often called a unit vector. Multiplying a unit vector by an arbitrary number will increase its magnitude by that amount (in this case speed) so

unitVec * 300.f;


would give you a vector 300 units long. sf::Transformable (and anything which inherits it such as sf::Sprite) use Move() to add a vector to the transformable's current position (which is also a vector) hence moving it. Vector maths is fundamental to pretty much all game programming, so if you can't find any good online resources (such as this one) you should definitely consider buying a book or two.

two-tone-

  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: Complicated movement question
« Reply #10 on: February 03, 2014, 11:02:51 am »
Thanks! I'll do that.

Jonny

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • Email
Re: Complicated movement question
« Reply #11 on: February 03, 2014, 05:11:29 pm »
Might be worth looking up linear interpolation as well...