• 13
• 17
• 19
• 27
• 9

# Setting Velocity with SFML

This topic is 2505 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm trying to incorporate "velocity" with SFML sprites. If anybody could even help me with some pseudo code, that would be nice.
Here's what I have so far, it's really buggy. It speeds up / slows down, but not correctly.

 //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// #include <SFML/Window.hpp> #include <SFML/Graphics.hpp> #include <iostream> //////////////////////////////////////////////////////////// /// Entry point of application /// /// \return Application exit code /// //////////////////////////////////////////////////////////// int main() { // Create the main window sf::RenderWindow App(sf::VideoMode(800, 600, 32), "SFML Time"); sf::Shape Rectangle = sf::Shape::Circle(150.0f,150.0f,20.0f,sf::Color::Red); // Disable vertical synchronization to get maximum framerate App.UseVerticalSync(false); // Create a clock for measuring time sf::Clock Clock; // Some dummy variables to simulate an object that moves const float Speed = 0.05f; float Left = 0.f; float Top = 0.f; // Start main loop while (App.IsOpened()) { // Process events sf::Event Event; while (App.GetEvent(Event)) { // Close window : exit if (Event.Type == sf::Event::Closed) App.Close(); // Escape key : exit if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape)) App.Close(); } // Get elapsed time since last frame (we could as well use App.GetFrameTime()) float ElapsedTime = Clock.GetElapsedTime(); float Velo = 0.0f; // Make our virtual object move if (App.GetInput().IsKeyDown(sf::Key::Left)) { Left -= Speed * ElapsedTime; Velo = Left; } else if (App.GetInput().IsKeyDown(sf::Key::Right)) { Left += Speed * ElapsedTime; Velo = Left; } else if (App.GetInput().IsKeyDown(sf::Key::Up)) { Top -= Speed * ElapsedTime; Velo = Top; } else if (App.GetInput().IsKeyDown(sf::Key::Down)) { Top += Speed * ElapsedTime; Velo = Top; } else { if( Velo ) { Top -= Speed * ElapsedTime; Left -=Speed * ElapsedTime; } } if( Velo ) { if( Left ) Rectangle.Move( Left, 0 ); else if( Top ) Rectangle.Move( 0, Top ); } Clock.Reset(); App.Clear(); App.Draw( Rectangle ); // Display window on screen App.Display(); } return EXIT_SUCCESS; } 

This doesn't have to be specific, like I said, even pseudo code (:
Thanks

##### Share on other sites
One issue you will run into with the "else ifs" is that pressing two directions at the same time won't work -- for instance, pressing up+left during a frame will register as just left, etc...

I would recommend using vector math. First, you'll obtain an acceleration value which determines how the player's speed will change this frame. Then you'll add the acceleration to the player's speed vector. The speed vector will determine how much the player moves this frame.

You'll probably want to keep a "requested movement vector" and do something like this (pseudocode):

 requestedMovementVector = Vector2f(0.0f,0.0f); // initializes the requested movement vector -- note that you may not have a Vector2f class, this is just an example if(left is pressed) requestedMovementVector.x -= 1.0f; if(right is pressed) requestedMovementVector.x += 1.0f; if(up is pressed) requestedMovementVector.y -= 1.0f; if(down is pressed) requestedMovementVector.y += 1.0f;

By doing this, you'll get a vector that tells you which direction(s) the player wants to move. If the player presses left and right at the same time, the movement requested on x will be 0.0f. If the player presses up+left, the request will be (-1.0f, -1.0f). You'll want to normalize this vector to get a vector of length 1; this will ensure that moving diagonally is not faster than moving in a straight line.

Once you've got the normalized vector, you'll have a movement direction that you can multiply by an acceleration (a constant value that you define). That gives you the acceleration requested by the player.

This acceleration represents the number of units to add to the speed vector per time unit (which should be one second).

So you multiply it by the elapsed time to determine how much acceleration to apply this frame.

You then add the resulting acceleration vector to the speed vector. You can also add other forces to the speed vector, such as a constant downwards vector for gravity (multiplied by elapsed time as well).

At this point, you've got a speed vector. Depending on what you want, you can do some modifications on it. For instance, if you want the player to slow down over time, you could apply some damping by dividing the speed by a certain constant (this will effectively lower the speed towards zero over time). You could also clamp the player's speed based on a maximum speed you define.

If you're doing collision detection, you'll want to test whether movement is possible, and possibly do additional calculations, such as calculating where the obstacle is so the player sprite doesn't overlap with it.

Once the speed vector has been properly set, you'll want to have a temporary vector that is equal to the speed vector, multiplied by the elapsed time. You add that to the player's x,y coordinates, and the final coordinates you get this way will be the player's new x,y position.

Notice that we're using physics as a guide here: acceleration is actually in units/second/second; when you multiply it by elapsed time (a value in seconds), it gives you a variation in units/second that you have to add to the velocity, and then, you multiply the velocity by elapsed time as well to get a variation in units, which tells you the displacement of the sprite for the frame.

##### Share on other sites
It looks like you want to accelerate your sprite to the direction you are pressing, and slow down to 0 when not pressing any keys. If not, then you're way off.

I would do something like this (keeping it simple, not introducing vectors, trig, or 2d physics)
 float xVel =0.0f; float yVel = 0.0f; float Accel = 0.5f; float xLoc = 100; float yLoc = 100; float ElapsedTime; while(bRunning) { if (KeyDown(Left)) { xVel -= Accel; } else if (KeyDown(Right)) { xVel += Accel; } else { // neither key pressed, slow down xVel to 0 (if positive add, negative, subtract) if (xVel > 0) { xVel -= Accel; } else if (xVel < 0) { xVel += Accel; } } if (KeyDown(Up)) { yVel -= Accel; } else if (KeyDown(Down)) { yVel += Accel; } else { // neither key pressed, slow down xVel to 0 (if positive add, negative, subtract) if (yVel > 0) { yVel -= Accel; } else if (yVel < 0) { yVel += Accel; } } ElapsedTime = GetElapsedTime(); xLoc += (xVel * ElapsedTime); yLoc += (yVel * ElapsedTime); SpriteToDraw.SetLocation(xLoc, yLoc); AppClear(); App.Draw(SpriteToDraw); App.Display(); } 

I'm trying to incorporate "velocity" with SFML sprites. If anybody could even help me with some pseudo code, that would be nice.
Here's what I have so far, it's really buggy. It speeds up / slows down, but not correctly.

 //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// #include <SFML/Window.hpp> #include <SFML/Graphics.hpp> #include <iostream> //////////////////////////////////////////////////////////// /// Entry point of application /// /// \return Application exit code /// //////////////////////////////////////////////////////////// int main() { // Create the main window sf::RenderWindow App(sf::VideoMode(800, 600, 32), "SFML Time"); sf::Shape Rectangle = sf::Shape::Circle(150.0f,150.0f,20.0f,sf::Color::Red); // Disable vertical synchronization to get maximum framerate App.UseVerticalSync(false); // Create a clock for measuring time sf::Clock Clock; // Some dummy variables to simulate an object that moves const float Speed = 0.05f; float Left = 0.f; float Top = 0.f; // Start main loop while (App.IsOpened()) { // Process events sf::Event Event; while (App.GetEvent(Event)) { // Close window : exit if (Event.Type == sf::Event::Closed) App.Close(); // Escape key : exit if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape)) App.Close(); } // Get elapsed time since last frame (we could as well use App.GetFrameTime()) float ElapsedTime = Clock.GetElapsedTime(); float Velo = 0.0f; // Make our virtual object move if (App.GetInput().IsKeyDown(sf::Key::Left)) { Left -= Speed * ElapsedTime; Velo = Left; } else if (App.GetInput().IsKeyDown(sf::Key::Right)) { Left += Speed * ElapsedTime; Velo = Left; } else if (App.GetInput().IsKeyDown(sf::Key::Up)) { Top -= Speed * ElapsedTime; Velo = Top; } else if (App.GetInput().IsKeyDown(sf::Key::Down)) { Top += Speed * ElapsedTime; Velo = Top; } else { if( Velo ) { Top -= Speed * ElapsedTime; Left -=Speed * ElapsedTime; } } if( Velo ) { if( Left ) Rectangle.Move( Left, 0 ); else if( Top ) Rectangle.Move( 0, Top ); } Clock.Reset(); App.Clear(); App.Draw( Rectangle ); // Display window on screen App.Display(); } return EXIT_SUCCESS; } 

This doesn't have to be specific, like I said, even pseudo code (:
Thanks