Jump to content
  • Advertisement
Sign in to follow this  
Drakk

Setting Velocity with SFML

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!