Search code examples
c++qtdictionaryqgraphicsscenetiled

Add a tiled base map to a GraphicsScene


I try to create a tiled base map by using Qt GUI: I have two classes: one to set my tile images that inherits from QGraphicPixmapItem, one to load my map from a text file that is a 2D array composed of the numbers 1, 0 and 2, and add it to a scene: But my program quits unexpectedly and I do not know where is the break:

my tile class:

class mapTile: public QGraphicsPixmapItem
{
public:
    enum Tile {DOOR, GRASS, FIRE};

    mapTile(): QGraphicsPixmapItem(),currentTile(GRASS){
        syncBitmap();
    }

    Tile getTile() const {return currentTile;}

    void setTile(Tile newTile){
        if(currentTile!= newTile){
            currentTile=newTile;
            syncBitmap();
        }
    }

private:
    void syncBitmap() {//Set my image to my tile
        switch(currentTile) {
        case DOOR:
            image->setPixmap(QPixmap(":/mpa/castledoors.png"));
        case GRASS:
            image->setPixmap(QPixmap(":/map/grass3_blur.jpg"));
        case FIRE:
            image->setPixmap(QPixmap(":/map/feu1/png"));
        }
    }

    Tile currentTile;
    QGraphicsPixmapItem *image;

};

my class map:

Map.h:

class Map
{

public:
    static const int TILE_SIZE=20; //value of the tile in pixels!!!->20X20=a tile
    void paintMap(QGraphicsScene *scene);
    Map();

 private:

    static const int WIDTH= 13;// width of the grid cell
    static const int HEIGHT= 9;//height  of the grid cell

    //my grid cell map !!!!
    int array[WIDTH][HEIGHT];
    mapTile *tile; //my tile

};

And Map.cpp

/*Create a default Map*/
Map::Map()
{
    QFile myfile("path to my file");
    if (!myfile.open(QIODevice::ReadOnly | QIODevice::Text))
    {
         QMessageBox::information(0, "error", myfile.errorString());
    }

    QTextStream in(&myfile);
    QString line ;
    QStringList fields;
    int i=0;
    int j=0;

    while (!in.atEnd()) {
        //Fill my array with my list--> convert Qtring into Int
        for (i=0; i<HEIGHT; i++ ) {

           line = in.readLine();
           fields = line.split(" ");

           for(j=0;j<WIDTH;j++)
           {
               //cout<<fields[j].toInt();
                array[i][j] = fields[j].toInt();
           }
        }
    }
}



//Paint my map with my tile
void Map::paintMap(QGraphicsScene *scene){

    int i=0, j=0;
    tile= new mapTile();

    for (i=0; i<HEIGHT; i++){
        for(j=0; j<WIDTH; j++){

            switch(array[i][j]){

            case 0:

                tile->setTile(mapTile::GRASS);
                tile->setPos(i,j);
                scene->addItem(tile);
                j+=TILE_SIZE;

            case 1:

                tile->setTile(mapTile::FIRE);
                tile->setPos(i,j);
                scene->addItem(tile);
                j+=TILE_SIZE;
            case 2:

                tile->setTile(mapTile::DOOR);
                tile->setPos(i,j);
                scene->addItem(tile);
                j+=TILE_SIZE;
            }

            i+=TILE_SIZE;//
        }
    }

}

and finally my mainwindow (I directly give the file.cpp):

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    myMap= new Map;
    scene= new QGraphicsScene(this);

    myMap->paintMap(scene);
    ui->graphicsView->setScene(scene);

}

MainWindow::~MainWindow()
{
    delete ui;
}

Sorry guys for the long post but I am stuck! Any ideas on what I missed?


Solution

  • Well, there are at least five problems in your code:

    • You can't share the same myTile instance when adding them to the scene. You need to create a new one each time you're adding a tile to the scene. At the moment you're creating only one instance at the start of Map::paintMap.

    • Your myTile class inherits from QGraphicsPixmapItem, however it also has a QGraphicsPixmapItem *image; member which it leaves uninitialized (so it's a roaming pointer), but then it uses it in image->setPixmap(QPixmap(":/mpa/castledoors.png")); which will crash. Instead, you'll want to just call setPixmap(QPixmap(":/mpa/castledoors.png")) (calling the function of your superclass).

    • In the above item you may have noticed that you misspelled "map" as "mpa", though this will not be the reason of your crash.

    • In mapTile::syncPixmap as well as in Map::paintMap, you forgot the break; statements in the switch. Without those, all tiles would appear like fire tiles.

    • You're adding your tile size to the i and j iterators, as if they were the pixel coordinates, but at the same time you're using them as array indexes. You need to either use separate variables for the pixel coordinates or multiply i and j by the TILE_SIZE when calling setPos instead.

    Good luck!