Home > database >  How to make the player move towards the mouse in c SFML
How to make the player move towards the mouse in c SFML

Time:06-11

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 move
  • target 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);
        }
    }
}
  • Related