From: Ingo Ruhnke Subject: BouncyBrick bugfix To: super-tux-devel@lists.sourceforge.net Date: Sun, Jun 13 2004 22:04:58 CEST Reply-To: super-tux-devel@lists.sourceforge.net Here goes a little bugfix for the bouncybrick problem, ie. when we have a bouncybrick it is drawn twice, one time the bouncybrick is drawn and a second time the same tile is drawn via the tilemap: +---+ <- BouncyBrick +---+| |+---++---+ | |+---+| || | +---++---++---++---+ ^- brick drawn via tilemap The patch works by using the last bit of the tile id as visibility indicator, so that the bouncybrick hiddes the tile as long as the bouncy brick itself is in action. Since it changes the 'unsigned int' of the tileid to a bitfield struct I am not sure if people will like it. Alternative aproach would be to use a visibility-map (visible[width*h+x]), which has the flags instead of storing them in the struct. Yet another way would be to replace the tile temporaly with a solid invisible tile and change it back to its original stage once the bouncybrick is done, not sure however if this couldn't go wrong if the player bounces against the same tile very fast (especially in case of multiplayer or special enemies that also can bounce tiles). Having a visiblity flag might also be usefull as a later point, ie. have levels where part of the level gets invisible or so. Index: gameobjs.cpp =================================================================== RCS file: /cvsroot/super-tux/supertux/src/gameobjs.cpp,v retrieving revision 1.39 diff -u -r1.39 gameobjs.cpp --- gameobjs.cpp 9 Jun 2004 05:23:19 -0000 1.39 +++ gameobjs.cpp 13 Jun 2004 19:53:12 -0000 @@ -80,9 +80,10 @@ } BouncyBrick::BouncyBrick(const Vector& pos) - : position(pos), offset(0), offset_m(-BOUNCY_BRICK_SPEED) -{ - shape = Sector::current()->solids->get_tile_id_at(pos); + : position(pos), offset(0), offset_m(-BOUNCY_BRICK_SPEED), + shape(Sector::current()->solids->get_tile_id_at(pos)) +{ + shape.hidden = true; } void @@ -96,14 +97,17 @@ /* Stop bouncing? */ if (offset >= 0) - remove_me(); + { + shape.hidden = false; + remove_me(); + } } void BouncyBrick::draw(DrawingContext& context) { TileManager::instance()-> - draw_tile(context, shape, position + Vector(0, offset), LAYER_TILES+1); + draw_tile(context, shape.id, position + Vector(0, offset), LAYER_TILES+1); } FloatingScore::FloatingScore(const Vector& pos, int score) Index: gameobjs.h =================================================================== RCS file: /cvsroot/super-tux/supertux/src/gameobjs.h,v retrieving revision 1.26 diff -u -r1.26 gameobjs.h --- gameobjs.h 31 May 2004 02:40:30 -0000 1.26 +++ gameobjs.h 13 Jun 2004 19:53:12 -0000 @@ -37,6 +37,8 @@ #define NO_BOUNCE 0 #define BOUNCE 1 +struct TileId; + class BouncyDistro : public GameObject { public: @@ -82,7 +84,7 @@ Vector position; float offset; float offset_m; - int shape; + TileId& shape; }; class FloatingScore : public GameObject Index: leveleditor.cpp =================================================================== RCS file: /cvsroot/super-tux/supertux/src/leveleditor.cpp,v retrieving revision 1.137 diff -u -r1.137 leveleditor.cpp --- leveleditor.cpp 9 Jun 2004 05:23:19 -0000 1.137 +++ leveleditor.cpp 13 Jun 2004 19:53:14 -0000 @@ -491,7 +491,7 @@ for(std::vector::const_iterator sit = (*it).tiles.begin(); sit != (*it).tiles.end(); ++sit, ++i) { - Tile& tile = *(TileManager::instance()->get(*sit)); + Tile& tile = TileManager::instance()->get(*sit); Surface* image; if(tile.editor_images.size() > 0) image = tile.editor_images[0]; Index: sector.cpp =================================================================== RCS file: /cvsroot/super-tux/supertux/src/sector.cpp,v retrieving revision 1.9 diff -u -r1.9 sector.cpp --- sector.cpp 13 Jun 2004 17:54:28 -0000 1.9 +++ sector.cpp 13 Jun 2004 19:53:15 -0000 @@ -18,6 +18,7 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#include #include #include #include @@ -761,7 +762,7 @@ throw SuperTuxException(errmsg, __FILE__, __LINE__); */ //Bad tiles (i.e. tiles that are not defined in supertux.stgt but appear in the map) are changed to ID 0 (blank tile) - std::cout << "Warning: Undefined tile at " <<(int)pos.x/32 << "/" << (int)pos.y/32 << " (ID: " << (int)solids->get_tile_id_at(pos) << ")" << std::endl; + std::cout << "Warning: Undefined tile at " <<(int)pos.x/32 << "/" << (int)pos.y/32 << " (ID: " << (int)solids->get_tile_id_at(pos).id << ")" << std::endl; solids->change_at(pos,0); tile = solids->get_tile_at(pos); } Index: tile.cpp =================================================================== RCS file: /cvsroot/super-tux/supertux/src/tile.cpp,v retrieving revision 1.28 diff -u -r1.28 tile.cpp --- tile.cpp 9 Jun 2004 19:15:22 -0000 1.28 +++ tile.cpp 13 Jun 2004 19:53:15 -0000 @@ -210,22 +210,20 @@ if(c == 0) return; - Tile* tile = get(c); - if(!tile) - return; + Tile& tile = get(c); - if(!tile->images.size()) + if(!tile.images.size()) return; - if(tile->images.size() > 1) + if(tile.images.size() > 1) { size_t frame - = ((global_frame_counter*25) / tile->anim_speed) % tile->images.size(); - context.draw_surface(tile->images[frame], pos, layer); + = ((global_frame_counter*25) / tile.anim_speed) % tile.images.size(); + context.draw_surface(tile.images[frame], pos, layer); } - else if (tile->images.size() == 1) + else if (tile.images.size() == 1) { - context.draw_surface(tile->images[0], pos, layer); + context.draw_surface(tile.images[0], pos, layer); } } Index: tile.h =================================================================== RCS file: /cvsroot/super-tux/supertux/src/tile.h,v retrieving revision 1.27 diff -u -r1.27 tile.h --- tile.h 9 Jun 2004 05:23:20 -0000 1.27 +++ tile.h 13 Jun 2004 19:53:15 -0000 @@ -141,17 +141,19 @@ const Vector& pos, int layer); static std::set* tilegroups() { if(!instance_) { instance_ = new TileManager(); } return tilegroups_ ? tilegroups_ : tilegroups_ = new std::set; } - Tile* get(unsigned int id) { + Tile& get(unsigned int id) { + id &= (~(1 << 31)); + if(id < tiles.size()) { - return tiles[id]; + return *tiles[id]; } else { // Never return 0, but return the 0th tile instead so that // user code doesn't have to check for NULL pointers all over // the place - return tiles[0]; + return *tiles[0]; } } }; Index: tilemap.cpp =================================================================== RCS file: /cvsroot/super-tux/supertux/src/tilemap.cpp,v retrieving revision 1.9 diff -u -r1.9 tilemap.cpp --- tilemap.cpp 9 Jun 2004 05:23:20 -0000 1.9 +++ tilemap.cpp 13 Jun 2004 19:53:15 -0000 @@ -65,9 +65,19 @@ if(!reader.read_int("width", width) || !reader.read_int("height", height)) throw std::runtime_error("No width or height specified in tilemap."); + + std::vector tmp_tiles; - if(!reader.read_int_vector("tiles", tiles)) + if(!reader.read_int_vector("tiles", tmp_tiles)) throw std::runtime_error("No tiles in tilemap."); + + tiles.resize(tmp_tiles.size()); + for(unsigned int i = 0; i < tmp_tiles.size(); ++i) + { + tiles[i].hidden = false; + tiles[i].id = tmp_tiles[i]; + } + if(int(tiles.size()) != width*height) throw std::runtime_error("wrong number of tiles in tilemap."); } @@ -95,7 +105,7 @@ writer.write_float("speed", speed); writer.write_int("width", width); writer.write_int("height", height); - writer.write_int_vector("tiles", tiles); + //writer.write_int_vector("tiles", tiles); writer.end_list("tilemap"); } @@ -123,7 +133,8 @@ int tx, ty; for(pos.x = start_x, tx = tsx; pos.x < end_x; pos.x += 32, ++tx) { for(pos.y = start_y, ty = tsy; pos.y < end_y; pos.y += 32, ++ty) { - tilemanager->draw_tile(context, tiles[ty*width + tx], pos, layer); + if (!tiles[ty*width + tx].hidden) + tilemanager->draw_tile(context, tiles[ty*width + tx].id, pos, layer); } } } @@ -134,11 +145,18 @@ { assert(int(newt.size()) == newwidth * newheight); - width = newwidth; + width = newwidth; height = newheight; - tiles = newt; - layer = newlayer; - solid = newsolid; + + tiles.resize(newt.size()); + for(unsigned int i = 0; i < newt.size(); ++i) + { + tiles[i].hidden = false; + tiles[i].id = newt[i]; + } + + layer = newlayer; + solid = newsolid; } void @@ -160,7 +178,7 @@ for(int y = std::min(height, new_height)-1; y >= 0; --y) { for(int x = new_width-1; x >= 0; --x) { if(x >= width) { - tiles[y * new_width + x] = 0; + tiles[y * new_width + x] = TileId(); } else { tiles[y * new_width + x] = tiles[y * width + x]; } @@ -176,9 +194,9 @@ TileMap::get_tile(int x, int y) const { if(x < 0 || x >= width || y < 0 || y >= height) - return tilemanager->get(0); + return &tilemanager->get(0); - return tilemanager->get(tiles[y*width + x]); + return &tilemanager->get(tiles[y*width + x].id); } Tile* @@ -187,11 +205,12 @@ return get_tile(int(pos.x)/32, int(pos.y)/32); } -unsigned int -TileMap::get_tile_id_at(const Vector& pos) const +TileId& +TileMap::get_tile_id_at(const Vector& pos) { int x = int(pos.x)/32; int y = int(pos.y)/32; + return tiles[y*width + x]; } @@ -199,7 +218,7 @@ TileMap::change(int x, int y, unsigned int newtile) { assert(x >= 0 && x < width && y >= 0 && y < height); - tiles[y*width + x] = newtile; + tiles[y*width + x].id = newtile; } void Index: tilemap.h =================================================================== RCS file: /cvsroot/super-tux/supertux/src/tilemap.h,v retrieving revision 1.7 diff -u -r1.7 tilemap.h --- tilemap.h 9 Jun 2004 05:23:20 -0000 1.7 +++ tilemap.h 13 Jun 2004 19:53:15 -0000 @@ -31,6 +31,15 @@ class LispReader; class Tile; +struct TileId +{ + TileId() : id(0), hidden(0) {} + explicit TileId(unsigned int i, bool hidden_ = false) : id(i), hidden(hidden_) {} + + unsigned id :31; + unsigned hidden :1; +}; + /** * This class is reponsible for drawing the level tiles */ @@ -63,7 +72,7 @@ bool is_solid() const { return solid; } - unsigned int get_tile_id_at(const Vector& pos) const; + TileId& get_tile_id_at(const Vector& pos); /// returns tile in row y and column y (of the tilemap) Tile* get_tile(int x, int y) const; @@ -74,8 +83,8 @@ void change_at(const Vector& pos, unsigned int newtile); -public: - std::vector tiles; +private: + std::vector tiles; private: TileManager* tilemanager; -- WWW: http://pingus.seul.org/~grumbel/ JabberID: grumbel@jabber.org ICQ: 59461927