×

Discussion Board

Results 1 to 2 of 2
  1. #1
    Registered User
    Join Date
    Dec 2009
    Posts
    73

    How to get rid of flicking when animating QGraphicsPixmapItem

    Hi all,
    I am trying to write a simple game by Qt graphics view framework. I have created a ball derived from QGraphicsPixmapItem and simulate collision effect between the ball and four sides.
    Code:
    Ball::Ball(const QString filePath, QGraphicsScene *scn) : QGraphicsPixmapItem(0, scn)
    {
        setPixmap(QPixmap(filePath));
        qDebug() << pixmap().isNull();
    
        mSpeed.setX(.5);
        mSpeed.setY(.5);
        mMass = 1.0;
    
        int w = scene()->width();
        int h = scene()->height();
        setPos(w/2, h/2);
        setCacheMode(DeviceCoordinateCache);
    
        mTopLine = scene()->addLine(0, 0, w, 0, QPen(QColor(0, 0, 0, 0)));
        mBottomLine = scene()->addLine(0, h, w, h, QPen(QColor(0, 0, 0, 0)));
        mLeftLine = scene()->addLine(0, 0, 0, h, QPen(QColor(0, 0, 0, 0)));
        mRightLine = scene()->addLine(w, 0, w, h, QPen(QColor(0, 0, 0, 0)));
    }
    
    QRectF Ball::boundingRect() const
    {
        return pixmap().rect();
    }
    
    QPainterPath Ball::shape() const
    {
        QPainterPath path;
        path.addEllipse(boundingRect());
        return path;
    }
    
    void Ball::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        painter->drawPixmap(0, 0, pixmap());
    }
    
    void Ball::advance(int phase)
    {
        if (phase == 1)
        {
            if (collidesWithItem(mTopLine) || collidesWithItem(mBottomLine))
            {
                mSpeed.setY(-mSpeed.y());
            }
            if (collidesWithItem(mLeftLine) || collidesWithItem(mRightLine))
            {
                mSpeed.setX(-mSpeed.x());
            }
            setPos(pos()+mSpeed.toPointF());
        }
    }
    I also create a Background class derived from QGraphicsView
    Code:
    Background::Background(int w, int h)
    {
        mScene = new QGraphicsScene(0, 0, w, h);
        setScene(mScene);
        mScene->setBackgroundBrush(Qt::white);
    
        resize(w, h);
    
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    
        setRenderHint(QPainter::Antialiasing);
        setCacheMode(QGraphicsView::CacheBackground);
        setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
    
        QImage img(":/image/backgrounds/tanakawho03.jpg");
        QImage img1 = img.scaled(w/2, h/2);
    
        QGraphicsPixmapItem *item1 = mScene->addPixmap(QPixmap(QPixmap::fromImage(img1.mirrored(false, false))));
        item1->setPos(0, 0);
        item1->setCacheMode(QGraphicsPixmapItem::DeviceCoordinateCache);
    
        QGraphicsPixmapItem *item2 = mScene->addPixmap(QPixmap(QPixmap::fromImage(img1.mirrored(true, false))));
        item2->setPos(w/2, 0);
        item2->setCacheMode(QGraphicsPixmapItem::DeviceCoordinateCache);
    
        QGraphicsPixmapItem *item3 = mScene->addPixmap(QPixmap(QPixmap::fromImage(img1.mirrored(false, true))));
        item3->setPos(0, h/2);
        item3->setCacheMode(QGraphicsPixmapItem::DeviceCoordinateCache);
    
        QGraphicsPixmapItem *item4 = mScene->addPixmap(QPixmap(QPixmap::fromImage(img1.mirrored(true, true))));
        item4->setPos(w/2, h/2);
        item4->setCacheMode(QGraphicsPixmapItem::DeviceCoordinateCache);
    
    
        QTimer* timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), mScene, SLOT(advance()));
        timer->start(10);;
    
    }
    main.cpp
    Code:
    int main(int argc, char *argv[])
    {
        QTime time = QTime::currentTime();
        qsrand(time.hour()*3600+time.minute()*60+time.second());
        qrand();
    
        QApplication a(argc, argv);
        Background view;
        Ball ball(":/image/images/dot28_s_blue.png", view.scene());
    
    #if defined(Q_WS_S60)
        view.showMaximized();
    #else
        view.show();
    #endif
    
    
        return a.exec();
    }
    The problem is the flicking effect in the animation. If the advance() happens in a fixed frequency, there is some good velocity for the ball moving in the scene. If the velocity too small or too large, the ball will flick. How to handle such kinds of situations? Thanks.

  2. #2
    Super Contributor
    Join Date
    Mar 2009
    Posts
    1,024

    Re: How to get rid of flicking when animating QGraphicsPixmapItem

    Hi,
    First things that come to my mind are:
    1. set a GLWidget as viewport to speed up drawing
    2. If that doesn't help than remove antialiasing and set a viewport update mode which doesn't not redraw areas which are not change

Similar Threads

  1. Replies: 9
    Last Post: 2009-02-11, 07:52
  2. Replies: 2
    Last Post: 2008-04-25, 11:58
  3. Replies: 5
    Last Post: 2007-08-16, 09:56
  4. Replies: 0
    Last Post: 2004-07-14, 01:04
  5. how to get rid of the voice when playing a .au file
    By Lu_wenhui in forum PersonalJava
    Replies: 0
    Last Post: 2002-05-18, 16:47

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×