Item scaling and rendering
I am making a small game in C ++ 11 with Qt. However, I'm having trouble scaling.
The background of my card is an image. Each pixel of this image represents a tile that the main character can act on and enemies / medical packs can be.
To set the size of the tile, I calculate the maximum number (for example, imageRows and imageCols are the number of pixels on the x and y axis of the background image):
QRect rec = QApplication::desktop()->screenGeometry();
int maxRows = rec.height() / imageRows;
int maxCols = rec.width() / imageCols;
if(maxRows < maxCols){
pixSize = maxRows;
} else{
pixSize = maxCols;
}
Now that I have the size of the tile, I add a background image to the scene (in GameScene ctor
, continues from QGraphicsScene
):
auto background = new QGraphicsPixmapItem();
background->setPixmap(QPixmap(":/images/map.png").scaledToWidth(imageCols * pixSize));
this->addItem(background);
Then to add enemies (they range from QGraphicsPixMapItem
):
Enemy *enemy = new Enemy();
enemy->setPixmap(QPixmap(":/images/enemy.png").scaledToWidth(pixSize));
scene->addItem(enemy);
This all works great, except that on large maps the images are scaled once (to a height of, say, 2 pixels) and when scaled on that element it becomes obscure but remains a large pixel. Here's an example: the left one is on a small map, where the pixSize is quite large, the second one has a rather small pixSize.
So how do I solve this? In general, with pixSize based on screen resolution is not very useful as it QGrapicsScene
changes according to QGraphicsView
what it is in, so at the end the view still determines how large the pixels are displayed on the screen.
MyGraphicsView w;
w.setScene(gameScene);
w.fitInView(gameScene->sceneRect(), Qt::KeepAspectRatio);
source to share
I think you might need to look at an example from Qt (link to Qt5, but also works for Qt4).
Something that might help you is in the chip.cpp file :
in method paint
:
const qreal lod = option->levelOfDetailFromTransform(painter->worldTransform());
where painter
is just a QPainter
and option
is of type QStyleOptionGraphicsItem
. This value returns you the current zoom level of yours QGraphicsView
and thus, as in the example, you can customize what is being done at which level, for example.
if (lod < 0.2) {
if (lod < 0.125) {
painter->fillRect(QRectF(0, 0, 110, 70), fillColor);
return;
}
QBrush b = painter->brush();
painter->setBrush(fillColor);
painter->drawRect(13, 13, 97, 57);
painter->setBrush(b);
return;
}
[...]
if (lod >= 2) {
QFont font("Times", 10);
font.setStyleStrategy(QFont::ForceOutline);
painter->setFont(font);
painter->save();
painter->scale(0.1, 0.1);
painter->drawText(170, 180, QString("Model: VSC-2000 (Very Small Chip) at %1x%2").arg(x).arg(y));
painter->drawText(170, 200, QString("Serial number: DLWR-WEER-123L-ZZ33-SDSJ"));
painter->drawText(170, 220, QString("Manufacturer: Chip Manufacturer"));
painter->restore();
}
Does it help?
source to share