I'm moving from QGraphicsScene/QGraphicsView to QQuickItem for rendering my
game objects. One of the things this involves is setting up a scene and the
view onto that scene, as this was previously managed by QGraphicsScene and
QGraphicsView.
My naive attempt was to do the following:
void SceneView::centerOn(const QPointF &pos)
{
if (mScene) {
mScene->setX(-(pos.x() - width() / 2));
mScene->setY(-(pos.y() - height() / 2));
}
}
This works, but it produces this odd effect where some game objects "jump
around" between neighbouring pixels while the camera comes to a halt while
following the player:
http://i.imgur.com/AP1yIoO.gif
The player's movement is fine. The crate also does not seem to exhibit this
problem (though its Box2D debug drawing marker does).
This is what it looks like when the player moves without the camera following
it:
http://i.imgur.com/mA4JTC7.gif
This is what I'd expect from the other game objects when the camera is moving;
no movement whatsoever relative to the scene.
The old, correct movement looked like this:
http://i.imgur.com/7yMcVpS.gif
The old code:
void MapView::centerOverFollowedItem()
{
QRectF geometry(mFollowing->pos(), mFollowing->boundingRect().size());
centerOn(geometry.center());
}
I thought I'd take a look at how QGraphicsView does it:
void QGraphicsView::centerOn(const QPointF &pos)
{
Q_D(QGraphicsView);
qreal width = viewport()->width();
qreal height = viewport()->height();
QPointF viewPoint = d->matrix.map(pos);
QPointF oldCenterPoint = pos;
if (!d->leftIndent) {
if (isRightToLeft()) {
qint64 horizontal = 0;
horizontal += horizontalScrollBar()->minimum();
horizontal += horizontalScrollBar()->maximum();
horizontal -= int(viewPoint.x() - width / 2.0);
horizontalScrollBar()->setValue(horizontal);
} else {
horizontalScrollBar()->setValue(int(viewPoint.x() - width / 2.0));
}
}
if (!d->topIndent)
verticalScrollBar()->setValue(int(viewPoint.y() - height / 2.0));
d->lastCenterPoint = oldCenterPoint;
}
http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/graphicsview/qgraphicsview.cpp#n1904
It casts the x and y position of its view to integers, so I tried doing that
too:
void SceneView::centerOn(const QPointF &pos)
{
if (mScene) {
mScene->setX(int(-(pos.x() - width() / 2)));
mScene->setY(int(-(pos.y() - height() / 2)));
}
}
This fixes the movement of objects that shouldn't move, but produces a subtle
yet irritating effect where the movement of the camera looks "blocky":
http://i.imgur.com/Z3Wc66h.gif
It's mostly noticeable when the player is coming to a stop.
Why does this happen with a Qt Quick scene, but not QGraphicsView, when they
are both using integer positioning in this case?
(All objects are Images in the new code, and I set smooth to false on them
because my assets will be pixel art)
_______________________________________________
Interest mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/interest