Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[Qt, C++] Problem ze zmianą rozmiaru mapy

Ostatnio zmodyfikowano 2011-08-13 17:20
Autor Wiadomość
programista12
Temat założony przez niniejszego użytkownika
[Qt, C++] Problem ze zmianą rozmiaru mapy
» 2011-08-02 09:56:24
Chodzi o to, że w Qt mam problem ze zmianą rozmiaru mapy. Klasa mapy wygląda następująco:
C/C++
struct Tile
{
    QRectF box;
    int id;
    bool collision;
    QGraphicsPixmapItem * item;
    QGraphicsRectItem * collision_selection;
    Tile()
    {
        id = - 1;
        collision = false;
        box.setHeight( 32 );
        box.setWidth( 32 );
    }
};

class Map
    : public QGraphicsScene
{
    Q_OBJECT
private:
    Tile ** tiles;
    TilesetScene * tileset_scene;
    CURRENT_TOOL cur_tool;
    MAP_STATE map_state;
    QGraphicsRectItem * start_point, * map_rect;
    QString cur_map_file;
    int size_x, size_y;
public:
    Map( int w, int h, QObject * parent = 0 ); //ok
    Map();
    ~Map();
    void SetTile( int i, int j, int id ) { tiles[ i ][ j ].id = id; }
    int GetTileID( int i, int j ) const { return tiles[ i ][ j ].id; }
    TilesetScene * GetTilesetScene() const { return tileset_scene; }
    CURRENT_TOOL GetCurrentTool() const { return cur_tool; }
    void SetCurrentTool( CURRENT_TOOL ct ) { cur_tool = ct; }
    void SetTileCollision( int i, int j, bool c ) { tiles[ i ][ j ].collision = c; }
    bool GetTileCollision( int i, int j ) const { return tiles[ i ][ j ].collision; }
    QString GetCurMapFile() const { return cur_map_file; }
    void ShowMap();
    void ShowTiles( bool b );
    void ShowCollisionRects( bool b );
    void ShowTileCollisionRect( int i, int j, bool b );
    void ShowStartpoint( bool b );
    void SetStartpoint( qreal x, qreal y );
    void LoadMap( QString path );
    void UnloadMap();
    void SaveMap();
    void CheckTiles();
    void Resize( int x, int y );
    bool find( const std::string & str, const char * findValue );
    int GetSizeX() const { return size_x; }
    int GetSizeY() const { return size_y; }
protected:
    void mousePressEvent( QGraphicsSceneMouseEvent * event );
    void mouseMoveEvent( QGraphicsSceneMouseEvent * event );
};
Wyjaśnienia zmiennych:

struktura Tile:
box to zmienna przechowująca współrzędne kafelka i jego wymiary
id to numer kafelka z tilesetu (id = -1 to pusty kafelek)
item to zmienna do wyświetlania obrazka kafelka
collision_selection to prostokąt pokazujący, czy kafelek jest przeszkodą

klasa Map:
tiles to dynamiczna tablica kafelków
size_x, size_y to zmienne przechowujące wymiary mapy

Reszta jest nieważna.

W konstruktorze klasy Map ustawiam rozmiar mapy (5x5):
C/C++
Map::Map( int w, int h, QObject * parent )
    : QGraphicsScene( parent )
{
    size_x = w;
    size_y = h;
    tiles = new Tile *[ w ];
    for( int i = 0; i < w; i++ )
         tiles[ i ] = new Tile[ h ];
   
    setBackgroundBrush( Qt::gray );
    tileset_scene = new TilesetScene( parent );
    cur_tool = CT_DRAWING;
    map_state = MS_NEW;
    map_rect->setPos( 0, 0 );
    map_rect = addRect( 0, 0, w * 32, h * 32, QPen( QBrush( QColor( 255, 255, 255 ) ), 2 ) );
    map_rect->show();
    start_point = addRect( 0, 0, 32, 32, QPen( QBrush( QColor( 0, 0, 255 ) ), 2 ) );
    start_point->hide();
    start_point->setZValue( 3 );
   
    //set up tiles
    for( int i = 0; i < w; i++ )
    {
        for( int j = 0; j < h; j++ )
        {
            tiles[ i ][ j ].id = - 1;
            tiles[ i ][ j ].box = QRectF( i * 32, j * 32, 32, 32 );
            tiles[ i ][ j ].collision = false;
           
            tiles[ i ][ j ].item = addPixmap( QPixmap( 1, 1 ) );
            tiles[ i ][ j ].item->setPos( i * 32, j * 32 );
            tiles[ i ][ j ].item->hide();
           
            tiles[ i ][ j ].collision_selection = addRect( 0, 0, 32, 32, QPen( QBrush( QColor( 255, 0, 0 ) ), 2 ) );
            tiles[ i ][ j ].collision_selection->setPos( i * 32, j * 32 );
            tiles[ i ][ j ].collision_selection->setZValue( 2 );
            tiles[ i ][ j ].collision_selection->hide();
        }
    }
    setSceneRect( 0, 0, w * 32, h * 32 );
}
Funkcja Resize wygląda tak:
C/C++
void Map::Resize( int x, int y )
{
    Tile ** ntab;
    ntab = new Tile *[ x ];
    for( int i = 0; i < x; i++ )
         ntab[ i ] = new Tile[ y ];
   
    for( int i = 0; /*(i < x) && */( i < size_x ); i++ )
    {
        for( int j = 0; /*(j < y) && */( j < size_y ); j++ )
        {
            ntab[ i ][ j ].id = tiles[ i ][ j ].id;
            ntab[ i ][ j ].collision = tiles[ i ][ j ].collision;
           
            /*tiles[i][j].collision_selection = */ removeItem( tiles[ i ][ j ].collision_selection );
            /*tiles[i][j].item = */ removeItem( tiles[ i ][ j ].item );
            delete tiles[ i ][ j ].collision_selection;
            delete tiles[ i ][ j ].item;
        }
    }
   
    for( int i = 0; i < size_x; i++ )
         delete[] tiles[ i ];
   
    delete[] tiles;
   
    tiles = new Tile *[ x ];
    for( int i = 0; i < x; i++ )
         tiles[ i ] = new Tile[ y ];
   
    for( int i = 0; i < x; i++ )
    {
        for( int j = 0; i < y; j++ )
        {
            if(( i < size_x ) &&( j < size_y ) )
            {
                tiles[ i ][ j ].id = ntab[ i ][ j ].id;
                tiles[ i ][ j ].collision = ntab[ i ][ j ].collision;
            }
           
            tiles[ i ][ j ].item = addPixmap( QPixmap( 1, 1 ) );
            tiles[ i ][ j ].item->setPos( i * 32, j * 32 );
            if( tiles[ i ][ j ].id >= 0 ) tiles[ i ][ j ].item->show();
            else tiles[ i ][ j ].item->hide();
           
            tiles[ i ][ j ].collision_selection = addRect( 0, 0, 32, 32, QPen( QBrush( QColor( 255, 0, 0 ) ), 2 ) );
            tiles[ i ][ j ].collision_selection->setPos( i * 32, j * 32 );
            tiles[ i ][ j ].collision_selection->setZValue( 2 );
            if( tiles[ i ][ j ].collision ) tiles[ i ][ j ].collision_selection->show();
            else tiles[ i ][ j ].collision_selection->hide();
           
        }
    }
   
   
    for( int i = 0; i < x; i++ )
    {
        for( int j = 0; j < y; j++ )
        {
            tiles[ i ][ j ].box.setX( static_cast < qreal >( i * 32 ) );
            tiles[ i ][ j ].box.setY( static_cast < qreal >( j * 32 ) );
        }
    }
   
    for( int i = 0; i < x; i++ )
         delete[] ntab[ i ];
   
    delete[] ntab;
   
    size_x = x;
    size_y = y;
    setSceneRect( 0, 0, x * 32, y * 32 );
    map_rect->setRect( 0, 0, x * 32, y * 32 );
    ShowMap();
    update();
}
Jednak nie działa dobrze, gdyż jak ją wywołuję, to program się zawiesza. Co robię nie tak? Bardzo proszę o pomoc. Próbowałem sprawdzić w debuggerze, ale na samym początku wywala błąd Segmentation Fault, ale nie wiem w którym miejscu kodu, bo nie umiem obsługiwać debuggera Qt Creatora, a nie za bardzo chce mi się instalować Qt do Visuala tylko po to, żeby sprawdzić gdzie jest błąd.
P-37889
DejaVu
» 2011-08-05 16:07:26
Skoro dostajesz segmentation fault zanim debugger dojdzie do miejsca o którym mówisz to znaczy, że problem nie dotyczy tej części kodu.
P-38214
programista12
Temat założony przez niniejszego użytkownika
» 2011-08-08 11:08:51
Dzięki za odpowiedź. Problem już rozwiązałem. W funkcji Resize() trochę namieszałem w pętlach for, ale już to ogarnąłem. Zamykam temat.
P-38385
programista12
Temat założony przez niniejszego użytkownika
» 2011-08-12 10:16:25
Niestety, przeliczyłem się. Funkcja nadal nie działa tak, jak trzeba. Oto jej kod:
C/C++
void Map::Resize( int x, int y )
{
    Tile ** ntab;
    ntab = new Tile *[ x ];
    for( int i = 0; i < x; i++ )
         ntab[ i ] = new Tile[ y ];
   
    QMessageBox::information( NULL, "Informacja", "Utworzono tymczasowa tablice." );
   
    for( int i = 0; i < size_x; i++ )
    {
        for( int j = 0; j < size_y; j++ )
        {
            //removeItem(tiles[i][j].collision_selection);
            //removeItem(tiles[i][j].item);
            delete tiles[ i ][ j ].collision_selection;
            delete tiles[ i ][ j ].item;
        }
    }
   
    QMessageBox::information( NULL, "Informacja", "Usunieto itemy." );
   
    for( int i = 0;( i < x ) &&( i < size_x ); i++ )
    {
        for( int j = 0;( j < y ) &&( j < size_y ); j++ )
        {
            ntab[ i ][ j ].box = tiles[ i ][ j ].box;
            ntab[ i ][ j ].id = tiles[ i ][ j ].id;
            ntab[ i ][ j ].collision = tiles[ i ][ j ].collision;
        }
    }
   
    QMessageBox::information( NULL, "Informacja", "Przeniesiono informacje do tymczasowej tablicy." );
   
    for( int i = 0; i < size_x; i++ )
         delete[] tiles[ i ];
   
    delete[] tiles;
   
    QMessageBox::information( NULL, "Informacja", "Usunieto tablice mapy." );
   
    tiles = new Tile *[ x ];
    for( int i = 0; i < x; i++ )
         tiles[ i ] = new Tile[ y ];
   
    QMessageBox::information( NULL, "Informacja", "Utworzono nowa tablice mapy." );
   
    for( int i = 0;( i < x ) &&( i < size_x ); i++ )
    {
        for( int j = 0;( i < y ) &&( j < size_y ); j++ )
        {
            tiles[ i ][ j ].id = ntab[ i ][ j ].id;
            tiles[ i ][ j ].collision = ntab[ i ][ j ].collision;
            tiles[ i ][ j ].item = ntab[ i ][ j ].item;
            tiles[ i ][ j ].collision_selection = ntab[ i ][ j ].collision_selection;
        }
    }
   
    QMessageBox::information( NULL, "Informacja", "Przeniesiono informacje z tmp to mapy." );
   
    for( int i = 0; i < x; i++ )
    {
        for( int j = 0; j < y; j++ )
        {
            tiles[ i ][ j ].box.setX( static_cast < qreal >( i * 32 ) );
            tiles[ i ][ j ].box.setY( static_cast < qreal >( j * 32 ) );
           
            tiles[ i ][ j ].item = addPixmap( QPixmap( 1, 1 ) );
            tiles[ i ][ j ].item->setPos( i * 32, j * 32 );
           
            tiles[ i ][ j ].collision_selection = addRect( 0, 0, 32, 32, QPen( QBrush( QColor( 255, 0, 0 ) ), 2 ) );
            tiles[ i ][ j ].collision_selection->setPos( i * 32, j * 32 );
            tiles[ i ][ j ].collision_selection->setZValue( 2 );
            tiles[ i ][ j ].collision_selection->hide();
        }
    }
   
    QMessageBox::information( NULL, "Informacja", "Zmieniono pozycje kafelkow i dodano itemy." );
   
    for( int i = 0; i < x; i++ )
         delete[] ntab[ i ];
   
    delete[] ntab;
   
    QMessageBox::information( NULL, "Informacja", "Usunieto ntab." );
   
    size_x = x;
    size_y = y;
    setSceneRect( 0, 0, x * 32, y * 32 );
    map_rect->setRect( 0, 0, x * 32, y * 32 );
    QMessageBox::information( NULL, "Informacja", "Zmieniono size_x/y, sceneRect, map_rect." );
    ShowMap();
    QMessageBox::information( NULL, "Informacja", "ShowMap() = OK." );
    update();
    QMessageBox::information( NULL, "Informacja", "Pomyslnie zmieniono rozmiar mapy." );
}

Te MessageBoxy porobiłem, aby zbadać, gdzie leży błąd. Program zawiesza się na fragmencie
C/C++
for( int i = 0; i < x; i++ )
{
    for( int j = 0; j < y; j++ )
    {
        tiles[ i ][ j ].box.setX( static_cast < qreal >( i * 32 ) );
        tiles[ i ][ j ].box.setY( static_cast < qreal >( j * 32 ) );
       
        tiles[ i ][ j ].item = addPixmap( QPixmap( 1, 1 ) );
        tiles[ i ][ j ].item->setPos( i * 32, j * 32 );
       
        tiles[ i ][ j ].collision_selection = addRect( 0, 0, 32, 32, QPen( QBrush( QColor( 255, 0, 0 ) ), 2 ) );
        tiles[ i ][ j ].collision_selection->setPos( i * 32, j * 32 );
        tiles[ i ][ j ].collision_selection->setZValue( 2 );
        tiles[ i ][ j ].collision_selection->hide();
    }
}
Bardzo proszę o pomoc, bo nie wiem co jest nie tak.
P-38918
malan
» 2011-08-12 14:19:38
Debugger?
P-38959
programista12
Temat założony przez niniejszego użytkownika
» 2011-08-12 15:25:32
Debugger na starcie wywala Segmentation Fault i pokazuje to, co widać na obrazku: https://www.dropbox.com/gallery/18801631/1/Screeny?h=a94129
I wielokrotnie próbowałem kontynuować debugowanie, ale nic nie ruszało do przodu.
P-38972
pekfos
» 2011-08-12 16:48:10
Jak wali SIGSEGVa to może chociaż zobacz gdzie?
P-38983
programista12
Temat założony przez niniejszego użytkownika
» 2011-08-12 19:33:48
Chętnie bym zobaczył, ale nie wiem jak to zrobić, bo nigdy nie korzystałem debuggera Qt Creatora, tylko z Visuala. Mógłbyś mi podpowiedzieć jak to zrobić?
P-38994
« 1 » 2
  Strona 1 z 2 Następna strona