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: 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 ); 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): 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 ); 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: 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 < size_x ); i++ ) { for( int j = 0; ( j < size_y ); j++ ) { ntab[ i ][ j ].id = tiles[ i ][ j ].id; ntab[ i ][ j ].collision = tiles[ i ][ j ].collision; removeItem( tiles[ i ][ j ].collision_selection ); 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. |
|
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. |
|
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. |
|
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: 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++ ) { 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 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. |
|
malan |
» 2011-08-12 14:19:38 Debugger? |
|
programista12 Temat założony przez niniejszego użytkownika |
» 2011-08-12 15:25:32 |
|
pekfos |
» 2011-08-12 16:48:10 Jak wali SIGSEGVa to może chociaż zobacz gdzie? |
|
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ć? |
|
« 1 » 2 |