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.
I also create a Background class derived from QGraphicsViewCode: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()); } }
main.cppCode: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);; }
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.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(); }

Reply With Quote

