What I want to do here: I want to make a top down game where you move your player by right clicking somewhere and making the player move towards that point with a constant speed like in league of legends.
Here's my code so far that almost works. Player.cpp:
void player::initVarribles()
{
// player
movementSpeed = 2.0f;
tempB = false;
allowMove = false;
movedTimes = 0;
mX = 0.0f;
mY = 0.0f;
}
void player::update(RenderWindow* Twin)
{
if (Mouse::isButtonPressed(Mouse::Right))
{
allowMove = true;
tempB = false;
}
// Movement
if (tempB == false)
{
mX = Mouse::getPosition(*Twin).x;
mY = Mouse::getPosition(*Twin).y;
tempB = true;
}
if (allowMove == true)
{
if (mX > playerS.getPosition().x)
{
playerS.move(movementSpeed, 0.0f);
}
if (mX < playerS.getPosition().x)
{
playerS.move(-movementSpeed, 0.0f);
}
if (mY > playerS.getPosition().y)
{
playerS.move(0.0f, movementSpeed);
}
if (mY < playerS.getPosition().y)
{
playerS.move(0.0f, -movementSpeed);
}
}
}
Player.h:
#include "Libs.cpp"
class player
{
public:
player();
virtual ~player();
void update(RenderWindow* Twin);
void render(RenderTarget* target);
private:
void initBody();
void initVarribles();
// player
Texture playerT;
Sprite playerS;
bool allowMove;
int movedTimes;
float mX;
float mY;
bool tempB;
float movementSpeed;
};
I don't think showing void initBody(), void render(), player() and virtual ~player() is necessary. So if I run this, the player will go towards where the mouse was right clicked. But it follows a weird path, like it doesn't go straight to the mouse it kinda zigs zags. I think it's because the delta between playerX ... mouseX and playerY ... mouseY can differ. For example:
player_X = 500,
player_Y = 500,
Mouse_X = 760,
Mouse_Y = 124,
Mouse_X - player_X = 260
Mouse_Y - player_Y = 376
So if 376 is higher than 260 that means player_X will become Mouse_X first than player_Y. I want it make them go smoothly, arive at the same time. I tried to do that but it didn't really work, well my code almost worked but honestly it's such a mess and creates other issues like the player shaking, whatever Im not gonna post that code. But if anyone knows how to make it smooth please.
For starters, you would do well to adopt sf::Vector2f
to represent positions and speeds. Let us replace mX
, mY
and allowMove
by a std::optional<sf::Vector2f> target
.
We then have three situations:
target
is empty: we do not need to movetarget
is not empty, and distance(player, target) < moveSpeed
: we have arrived. Teleport to the target position and clear target
.target
is not empty, and distance(player, target) >= moveSpeed
: move one moveSpeed
increment towards target
.So update
becomes:
void player::update(RenderWindow* Twin)
{
if (Mouse::isButtonPressed(Mouse::Right) && !mouseDown) {
mouseDown = true;
target = Mouse::getPosition(*Twin);
}
if (!Mouse::isButtonPressed(Mouse::Right)) {
mouseDown = false;
}
// Movement
if (target)
{
sf::Vector2f vectorToTarget = *target - playerS.getPosition();
float distanceToTarget = sqrt(vectorToTarget.x * vectorToTarget.x + vectorToTarget.y * vectorToTarget.y);
if (distanceToTarget < movementSpeed) {
playerS.move(vectorToTarget);
target = {}; // clear target
} else {
sf::Vector2f movementDirection = vectorToTarget / distanceToTarget;
playerS.move(movementDirection * moveMentSpeed);
}
}
}