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.
CodePudding user response:
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, anddistance(player, target) < moveSpeed
: we have arrived. Teleport to the target position and cleartarget
.target
is not empty, anddistance(player, target) >= moveSpeed
: move onemoveSpeed
increment towardstarget
.
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);
}
}
}