Basically you need to calculate a movement vector for your character based on the mouse position. So you need two things:
- Angle from the character to the cursor, which is also the rotation of the character/sprite
- The distance, so you can implement a "deadzone", i will explain later why this is needed
You get the angle by using simple geometry, as described here (https://stackoverflow.com/questions/17530169/get-angle-between-point-and-origin)
Getting the distance is also not very difficult (https://www.mathsisfun.com/algebra/distance-2-points.html)
With these two values we can move the character by calculating a movement vector. This can be easily derived from the angle
sf::Vector2f movement = sf::Vector2f(cos(angle), sin(angle)) * movementSpeed;
where angle is a float (in radiant) from (1) and movementSpeed is a float which you can set.
Now you have everything you need to move your character
yourCharacter.move(movement );
You need to take the frametime into account to get a nice and smooth result, as described here (https://gamedev.stackexchange.com/questions/70255/what-is-framerate-independent-motion)
Also there is another small problem, the character will start spinning around your cursor once it has reached it. Because it will move a bit to far "over" the cursor and in the next frame it will "bounce" back. To avoid this you need a deadzone, which should look like this (modify the part above with the deadzone):
const float DEAD_ZONE = some_amount_based_on_movementSpeed
if(distance > DEAD_ZONE)
{
yourCharacter.move(movement);
}
Where distance is described in (2)
I hope this gives you a basic idea how to tackle this problem.
AlexAUT
Basically you need to calculate a movement vector for your character based on the mouse position. So you need two things:
- Angle from the character to the cursor, which is also the rotation of the character/sprite
- The distance, so you can implement a "deadzone", i will explain later why this is needed
You get the angle by using simple geometry, as described here (https://stackoverflow.com/questions/17530169/get-angle-between-point-and-origin)
Getting the distance is also not very difficult (https://www.mathsisfun.com/algebra/distance-2-points.html)
With these two values we can move the character by calculating a movement vector. This can be easily derived from the angle
sf::Vector2f movement = sf::Vector2f(cos(angle), sin(angle)) * movementSpeed;
where angle is a float (in radiant) from (1) and movementSpeed is a float which you can set.
Now you have everything you need to move your character
yourCharacter.move(movement );
You need to take the frametime into account to get a nice and smooth result, as described here (https://gamedev.stackexchange.com/questions/70255/what-is-framerate-independent-motion)
Also there is another small problem, the character will start spinning around your cursor once it has reached it. Because it will move a bit to far "over" the cursor and in the next frame it will "bounce" back. To avoid this you need a deadzone, which should look like this (modify the part above with the deadzone):
const float DEAD_ZONE = some_amount_based_on_movementSpeed
if(distance > DEAD_ZONE)
{
yourCharacter.move(movement);
}
Where distance is described in (2)
I hope this gives you a basic idea how to tackle this problem.
AlexAUT
Thanks for the answer. But I wrote it, a little bit differently:
for the character to follow the cursor, I get the distance, like this and move it
if ( Mouse::isButtonPressed(Mouse::Right) )
{
Vector2f totalMovement;
totalMovement.x = Mouse::getPosition(window).x - hero_sprite.getPosition().x;
totalMovement.y = Mouse::getPosition(window).y - hero_sprite.getPosition().y;
hero_sprite.move(totalMovement * (1.f/1000.f));
}
then created a function for the sides
enum look
{
right, left, down, up, downright, upright, upleft, downleft
};
and then I get the angle of my distance from this function
float mtrAngle_f(float x, float y)
{
float dir;
dir = acosf( x / sqrtf(powf(-x, 2.0f) + powf(-y, 2.0f)) );
if (y > 0.0f) { dir = MTR_2PI_F - dir; }
return dir * MTR_RADIAN_F;
}
and finally create a function that determine in what side the character looks at..
look lookAtMouse(int x, int y)
{
float direction = mtrAngle_f(x, y);
if (direction > angle && direction <= angle) // here we define the range of the angle
{
return look::right; // or left, or down, etc.
}
}
in depending on the side in which he looks at, I drew the appropriate sprites
if (player.lookAtMouse(pos.x, pos.y) == look::up) // or left, or down, etc.
{
player.animation();
}
Can you tell me how correctly or incorrectly I implemented it?
Can you tell me how correctly or incorrectly I implemented it?
Does your implementation work like you expect? Then you did it correctly :).
There is one thing which might not work like you expect: Your character will move faster when farther away from the cursor, because you take the distance vector and not the direction in your calculation. So I would recommend the following for your movement vector:
if ( Mouse::isButtonPressed(Mouse::Right) )
{
Vector2f totalMovement;
totalMovement.x = Mouse::getPosition(window).x - hero_sprite.getPosition().x;
totalMovement.y = Mouse::getPosition(window).y - hero_sprite.getPosition().y;
// Create a unit vector, to move at constant speed
totalMovement /= std::sqrt(std::pow(totalMovement.x, 2) + std::pow(totalMovement.y, 2))
hero_sprite.move(totalMovement * (1.f/1000.f)); //1/1000 should then be choosen bigger like 5
}
This will make your character move at the same speed independent from the distance to the mouse
AlexAUT
Can you tell me how correctly or incorrectly I implemented it?
Does your implementation work like you expect? Then you did it correctly :).
There is one thing which might not work like you expect: Your character will move faster when farther away from the cursor, because you take the distance vector and not the direction in your calculation. So I would recommend the following for your movement vector:
if ( Mouse::isButtonPressed(Mouse::Right) )
{
Vector2f totalMovement;
totalMovement.x = Mouse::getPosition(window).x - hero_sprite.getPosition().x;
totalMovement.y = Mouse::getPosition(window).y - hero_sprite.getPosition().y;
// Create a unit vector, to move at constant speed
totalMovement /= std::sqrt(std::pow(totalMovement.x, 2) + std::pow(totalMovement.y, 2))
hero_sprite.move(totalMovement * (1.f/1000.f)); //1/1000 should then be choosen bigger like 5
}
This will make your character move at the same speed independent from the distance to the mouse
AlexAUT
If i do this, my character moving with freeze, by jerks, regardless of what I did set as speed 5 or 1/1000 or 100
If the freezes/jerks come from your variable frametime you should read this very well written articel (https://gafferongames.com/post/fix_your_timestep/) on how to fix this "issue"
I have "sf::Clock clock" then i get time
float time = clock.getElapsedTime().asMicroseconds();
clock.restart();
time = time / 800;
and i pass the received time in method "animation()"
float frame = 0.f;
void animation(float &time, Vector2f &totalMovement, int scale)
{
frame += 0.005 * time;
if (frame > 8)
frame -= 8;
sprite.setTextureRect(IntRect(127 * int(frame), scale, width, height));
cout << totalMovement.x << " " << totalMovement.y << " " << time << " " << speed << endl;
sprite.move(totalMovement * time * speed); // time - getted early "time" , speed = 0.001f
}
And, yeah, i prined my totalMovement vector, its values <= 1 (like (x)0.95151 (y)0.307619 or (x)1 (y)-0.000951649), no, i dont have framelimit. But my character dont move at all, he only spins on the spot, and the animation starts with freezes.