PDA

View Full Version : Prevent QPixmap from being moved out of QGraphicsView



Macok
11th March 2009, 20:49
I'd like to write very simple game.
Here's a part of code:
QGraphicsScene *scene=new QGraphicsScene;
QGraphicsPixmapItem *pixmap=scene->addPixmap(QPixmap("img.png"));
ui->graphicsView->setScene(scene);pixmap is a creature that can be moved by player using WSAD keys.
I did it by this way:
void MainWindow::keyPressEvent(QKeyEvent *event){
switch(event->key()){
case Qt::Key_D:
pixmap->setPos(pixmap->pos().x()+1, pixmap->pos().y());
break;
case Qt::Key_A:
pixmap->setPos(pixmap->pos().x()-1, pixmap->pos().y());
break;
(...)
}
}Now i want to prevent pixmap from being moved out of QGraphicsView.
How can I do it?
Thanks in advance.

radek.z
12th March 2009, 06:59
try to use

bool QGraphicsItem::collidesWithItem ( const QGraphicsItem * other, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape ) const [virtual]

Macok
12th March 2009, 10:36
Thanks, but what should I pass as arguments of this function?

koral
12th March 2009, 11:26
Hello, here are some thoughts:
if you're making a sprite-based game, you should either:
- have a QGraphicsScene that has the size of the game and use QGraphicsView scrollbars/scrolling to pan/zoom the scene
- use a fixed Screen-size QGraphicsScene and do do your own code to 'scroll' the items (or the 'insert at right edga, scroll all items left, and remove at left edge type of thing)

I assume you're using 1, so the QGraphicsScene has the size of the game area and your 'player' sprite is in there.
In this case:

A. when moving the player, just don't move it out of the scene
QRect sceneRect = scene()->sceneRect().toRect();
player->setPos(qBound(sceneRect.left(), player->pos(), sceneRect.right() - player_width));
this keeps the X coordinate between scene rect boundaries (assuming the item has its origin in the top-left corner)

B. the QGraphicsView can scroll to see the player
just call player->ensureVisible(); and the view will scroll

Good luck ;-)

jpn
12th March 2009, 11:36
Take a look at QGraphicsItem::itemChange(). Notice the example.

Macok
12th March 2009, 12:53
Thanks for the replies.

@jpn
Based on that example I wrote something like this:
void MainWindow::keyPressEvent(QKeyEvent *event){
switch(event->key()){
case Qt::Key_D:
pixmap->setPos(pixmap->pos().x()+5, pixmap->pos().y());
break;
case Qt::Key_A:
pixmap->setPos(pixmap->pos().x()-5, pixmap->pos().y());
break;
case Qt::Key_W:
pixmap->setPos(pixmap->pos().x(), pixmap->pos().y()-5);
break;
case Qt::Key_S:
pixmap->setPos(pixmap->pos().x(), pixmap->pos().y()+5);
break;
}

if(!scene->sceneRect().contains(pixmap->pos())){
QMessageBox box;
box.setText("Player is out of the screen!");
box.exec();
}
}But it doesn't work.
I think the problem is that everytime I move pixmap, QGraphicsScene expands, so scene->sceneRect().contains(pixmap->pos()) will always return true.

radek.z
12th March 2009, 14:48
bool QGraphicsItem::collidesWithItem ( const QGraphicsItem * other, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape ) const [virtual]

as a QGraphicsItem you can pass QGraphicsRectItem(scene->sceneRect())
It means that you create graphics item with sboundary same as of graphicsscene has and then you check if your pixmap icollides with this RectItem

jpn
12th March 2009, 15:24
Yes, the scene will expand automatically by default, but shouldn't you define the game board area if that's the desired behavior? Something like:


void MyGraphicsView::resizeEvent(QResizeEvent* event)
{
QGraphicsview::resizeEvent(event);
if (scene())
scene()->setSceneRect(QRectF(QPointF(0,0), event->size()));
}

Macok
12th March 2009, 15:52
When I reimplemented QGraphicsView::resizeEvent program crashes imidiately after being started.
In QtCreator's console I have:
The program has unexpectedly finished.

jpn
12th March 2009, 16:19
See the backtrace from the debugger.