PDA

View Full Version : animating a QGraphicsObject



tommy22
6th January 2013, 11:15
Hi; this is my first question on this forum :)

**Situation**:
An upper class `dialog` generates a raster with squares. A player sits at (0,0) and when the user clicks on a square a pathfinding algoritm `pathFind` generates a `QString` of directions the player has to take to reach this goal. The `QString` is then converted to an array of `int`.

`dialog`calls a function from the `mysquare`class named movePlayer which should move the player in the correct direction.

*This movement should not happen instantaneous but at a certain rate which is why I'm trying to animate each movement so it takes a certain amount of time.*

My **problem** however is that the player square is not moving at all. Sometimes when I click somewhere outside of the grid it snaps to the ending position. Weird.


*MySquare class (the player)*


MySquare::MySquare(int x,int y, int w, int h){
curX = x;
curY = y;

initX = x;
initY = y;
width = w;
height = h;
posAnimation.setPropertyName("getGridPos");
posAnimation.setTargetObject(this);
}


bool MySquare::movePlayer(int direction){
switch (direction){
case 0: //move right
curX+=width;
break;
case 1: //move up
curY+=height;
break;
case 2: //move left
curX+=-width;
break;
case 3: //move down
curY+=-height;
break;
}
//setPos(curX,curY);
QPoint p;
p.setX(curX);
p.setY(curY);

setGridPos(p);
return true;
}

void MySquare::setGridPos(QPoint myPos) {
posAnimation.setStartValue(pos());
posAnimation.setDuration(2000); // 2 seconds
posAnimation.setEndValue(myPos);
posAnimation.start();
}


QPoint MySquare::getGridPos() const {
return pos();
}


*MySquare header (the player)*


class MySquare : public QGraphicsObject
{
Q_OBJECT
Q_PROPERTY(QPoint getGridPos READ getGridPos WRITE setGridPos) // define meta-property "pos"s
public:
QPropertyAnimation posAnimation;
MySquare(int x,int y,int h, int w);
QRectF boundingRect() const; //outer most edges of the object
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
bool movePlayer(int direction);
public slots:
QPoint getGridPos() const; // getter
void setGridPos(QPoint p); // setter

signals:
void targetChanged(int x, int y);

private:
int curX,curY,height,width,initX,initY;
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
};


edit:

* I've added some qDebug inside the setGridPos which are all immediately printed; which is telling me that the script is not blocking on the animation which could be part of the problem.

* The keyboard keys are also implemented to be able to move the player using the setPos() functions which are part of QGraphicsItem. When I press a key after clicking on a square it jumps to the corrent square (plus the key i've pressed that is) so it is updating the position of the square but somehow not showing it in the gui.

d_stranz
6th January 2013, 18:50
It isn't clear to me how a QPoint would be animated in the first place, since you have two parameters (x and y). Have you tried an animation of just one of the two coordinates, or a parallel animation of both? Do you need to specify some trajectory before a QPoint can be animated, or is there a default, like delta x = delta y?

I notice you have posted exactly the same question to stackoverflow. That is not considered good etiquette. Post in one place, if you don't get an answer in a reasonable amount of time (a day), then post somewhere else, but never simultaneously in two or more places.

wysota
6th January 2013, 22:57
Please post some compilable code demonstrating the problem. What you posted looks ok and in general should work, provided you call setGridPos() correctly.

@d_stranz: animating a point is not a problem, Qt knows how to do that.

d_stranz
7th January 2013, 05:26
animating a point is not a problem, Qt knows how to do that

So I guess the default easing curve for moving from point A to point B is linear? - Divide delta x and delta x by the time and move each incrementally by the appropriate amount at each step?

I don't see where QAbstractAnimation or its derived classes offer any control over the step size (time increment), only the duration of the animation. QEasingCurve allows control of the rate (i.e acceleration) of increment, but not of the increment itself. Is there a way to specify, f.e. that you want an animation that lasts for 5 seconds, and requires 10 steps? (I mean, maybe for some silly reason, you might want a jerky animation. Maybe you are trying to simulate an old silent movie).

(Looking at QEasingCurve, I suppose you could override the QEasingFunction::customType method to achieve a "jerky" motion by returning the same value for some range of progress values).

wysota
7th January 2013, 11:20
So I guess the default easing curve for moving from point A to point B is linear?
The default easing curve is always linear. What's important is that QVariantAnimation knows how to interpolate a QPoint.


I don't see where QAbstractAnimation or its derived classes offer any control over the step size (time increment),
They don't.


Is there a way to specify, f.e. that you want an animation that lasts for 5 seconds, and requires 10 steps?
No.

(I mean, maybe for some silly reason, you might want a jerky animation. Maybe you are trying to simulate an old silent movie).
In that case use a simple QTimer. Alternatively you might implement a custom easing curve but I don't think it is worth it.