2
\$\begingroup\$

I'm currently using SFML 2.0 to develop a game in C++. I have a game sprite class that has a click and drag method. The method works, but there is a slight problem. If the mouse moves too fast, the object the user selected can't keep up and is left behind in the spot where the mouse left its bounds. I will share the class definition and the given function implementation.

Definition:

class codePeg
{
protected:
    FloatRect bounds;
    CircleShape circle;
    int xPos, yPos, xDiff, yDiff, once;
    int xBase, yBase;
    Vector2i mousePos;
    Vector2f circlePos;
public:
    void init(RenderWindow& Window);
    void draw(RenderWindow& Window);
    void drag(RenderWindow& Window);
    void setPegPosition(int x, int y);
    void setPegColor(Color pegColor);
    void mouseOver(RenderWindow& Window);
    friend int isPegSelected(void);
};

Implementation of the "drag" function:

void codePeg::drag(RenderWindow& Window)
{
mousePos = Mouse::getPosition(Window);
circlePos = circle.getPosition();

if(Mouse::isButtonPressed(Mouse::Left))
{
    if(mousePos.x > xPos && mousePos.y > yPos
        && mousePos.x - bounds.width < xPos && mousePos.y - bounds.height < yPos)
    {
        if(once)
        {
            xDiff = mousePos.x - circlePos.x;
            yDiff = mousePos.y - circlePos.y;
            once = 0;
        }
        xPos = mousePos.x - xDiff;
        yPos = mousePos.y - yDiff;
        circle.setPosition(xPos, yPos);
    }
}
else
{
    once = 1;
    xPos = xBase;
    yPos = yBase;
    xDiff = 0;
    yDiff = 0;
    circle.setPosition(xBase, yBase);
}
Window.draw(circle);
}

Like I said, the function works, but to me, the code is very ugly and I think it could be improved and could be more efficient. The only thing I can think of as to why the object cannot keep up with the mouse is that there are too many function calls and/or checks. The user does not really have to move the mouse "fast" for it to happen, I would say at an average pace the object is left behind. How can I improve the code so that the object remains with the mouse when it is selected?

Any help improving this code or giving advice is greatly appreciated.

\$\endgroup\$
6
\$\begingroup\$

You have to implement behavior for when it was pressed last frame, pretty much.

something like

void codePeg::drag(RenderWindow& Window)
{
mousePos = Mouse::getPosition(Window);
circlePos = circle.getPosition();

if(Mouse::isButtonPressed(Mouse::Left))
{

    if(***pressedLastFrame ||***
        mousePos.x > xPos && mousePos.y > yPos
        && mousePos.x - bounds.width < xPos && mousePos.y - bounds.height < yPos)
    {
        if(once)
        {
            xDiff = mousePos.x - circlePos.x;
            yDiff = mousePos.y - circlePos.y;
            once = 0;
        }
        xPos = mousePos.x - xDiff;
        yPos = mousePos.y - yDiff;
        circle.setPosition(xPos, yPos);
    }
    ***pressedLastFrame = true;***
}
else
{
    once = 1;
    xPos = xBase;
    yPos = yBase;
    xDiff = 0;
    yDiff = 0;
    circle.setPosition(xBase, yBase);
    ***pressedLastFrame = false;***
}
Window.draw(circle);
}

That way, when it's been pressed already and you go out of bounds, it won't lose the connection with the drag.

\$\endgroup\$
2
  • \$\begingroup\$ Ok, I will try this. \$\endgroup\$
    – Josh
    Nov 5 '13 at 17:01
  • \$\begingroup\$ Thanks man! That is a pretty simple check I can't believe I looked over. \$\endgroup\$
    – Josh
    Nov 5 '13 at 17:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .