Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) Qt example 9: custom sprites over custom background

 

This Qt example shows how to let custom sprites move over custom background, like this screenshot (png).

 

 

Operating system: Ubuntu 10.04 LTS Lucid Lynx

IDE: Qt Creator 2.0.0

Project type: Qt4 GUI Application

Selected required modules: QtCore, QtGui

Compiler: G++ 4.4.1

Libraries used:

 

 

 

 

 

Qt project file

 

#-------------------------------------------------
#
# Project created by QtCreator 2010-07-21T13:31:08
#
#-------------------------------------------------
QT += core gui
TARGET = QtExample9
TEMPLATE = app
SOURCES += main.cpp

 

 

 

 

 

Source code

 

#include <cassert>
#include <cmath>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/static_assert.hpp>
#include <boost/timer.hpp>
#include <QApplication>
#include <QBitmap>
#include <QDialog>
#include <QGraphicsPixmapItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QTimer>
#include <QVBoxLayout>

BOOST_STATIC_ASSERT(sizeof(qreal)==sizeof(double)
  && "Assume use of double is equivalent of qreal");

struct Background : public QGraphicsPixmapItem
{
  Background(const int width = 256, const int height = 256)
  {
    QImage i(width,height,QImage::Format_ARGB32);
    for (int y=0;y!=height;++y)
    {
      for (int x=0;x!=width;++x)
      {
        const int gray = (x + y) % 256;
        i.setPixel(QPoint(x,y),QColor(gray,gray,gray).rgb());
      }
    }
    this->setPixmap(this->pixmap().fromImage(i));
  }
};

struct Sprite : public QGraphicsPixmapItem
{
  Sprite(const int width = 32, const int height = 32)
    : dx(1.0), dy(1.0), maxx(0.0), maxy(0.0)
  {
    QImage i(width,height,QImage::Format_ARGB32);
    for (int y=0;y!=height;++y)
    {
      for (int x=0;x!=width;++x)
      {
        const int gray = ((8 * x) + (8 * y)) % 256;
        i.setPixel(QPoint(x,y),QColor(gray,gray,gray).rgb());
      }
    }
    this->setPixmap(this->pixmap().fromImage(i));
  }
  void advance(int)
  {
    double new_x = this->x();
    double new_y = this->y();
    new_x+=dx;
    new_y+=dy;
    if (new_x<0.0 || new_x>maxx) dx= -dx;
    if (new_y<0.0 || new_y>maxy) dy= -dy;
    this->setX(new_x);
    this->setY(new_y);
  }
  void setRect(const int width, const int height)
  {
    maxx = static_cast<double>(width - this->pixmap().width() );
    maxy = static_cast<double>(height - this->pixmap().height());
  }
  private:
  double dx;
  double dy;
  double maxx;
  double maxy;
};

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  //Start with creating a scene
  boost::shared_ptr<QGraphicsScene> scene(new QGraphicsScene);

  //Add background to scene
  boost::shared_ptr<Background> background(new Background);
  scene->addItem(background.get());

  //Add sprites to scene
  std::vector<boost::shared_ptr<Sprite> > sprites;
  //Add multiple sprites
  {
    const int n_sprites = 20;
    const double midx = background->pixmap().width() / 2.0;
    const double midy = background->pixmap().height() / 2.0;
    const double ray = std::min(midx,midy) * 0.8;
    const double d_angle = 2.0 * M_PI / static_cast<double>(n_sprites);
    double angle = 0.0;
    for (int i=0; i!=n_sprites; ++i)
    {
      boost::shared_ptr<Sprite> sprite(new Sprite);
      const double x = midx + (std::sin(angle) * ray) - (sprite->pixmap().width() / 2);
      const double y = midy - (std::cos(angle) * ray) - (sprite->pixmap().height() / 2);
      sprite->setX(x);
      sprite->setY(y);
      sprite->setRect(background->pixmap().width(),background->pixmap().height());
      scene->addItem(sprite.get());
      sprites.push_back(sprite);
      angle+=d_angle;
    }
  }

  //Connect a view to display the scene
  boost::shared_ptr<QGraphicsView> view(new QGraphicsView);
  view->setScene(scene.get());

  //Create a layout to put the scene in
  boost::shared_ptr<QVBoxLayout> layout(new QVBoxLayout);
  layout->addWidget(view.get());

  //Create a dialog to display to laid-out-scene
  boost::shared_ptr<QDialog> dialog(new QDialog);
  dialog->setLayout(layout.get());
  dialog->setGeometry(view->rect());

  //Create a timer to call 'advance' on all sprites'
  boost::shared_ptr<QTimer> timer(new QTimer(scene.get()));
  timer->connect(timer.get(), SIGNAL(timeout()), scene.get(), SLOT(advance()));
  timer->start(20);

  //Show the graphicsscene with its sprites
  dialog->show();

  return a.exec();
}

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict