X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fobject%2Ftilemap.cpp;h=91360920364e78958e52a2494128f1dd674d1af7;hb=9eab9403c2b9ff629c07380e8d5f1032d21bd3f7;hp=4581b4a24b361d61bdfca3aa570a2528889ae417;hpb=08813a74da6ac1fd045a105e4e8105f1d7f716f0;p=supertux.git diff --git a/src/object/tilemap.cpp b/src/object/tilemap.cpp index 4581b4a24..913609203 100644 --- a/src/object/tilemap.cpp +++ b/src/object/tilemap.cpp @@ -19,57 +19,65 @@ #include "object/tilemap.hpp" #include "scripting/squirrel_util.hpp" #include "scripting/tilemap.hpp" -#include "supertux/main.hpp" +#include "supertux/globals.hpp" #include "supertux/object_factory.hpp" #include "supertux/tile_manager.hpp" #include "supertux/tile_set.hpp" #include "util/reader.hpp" TileMap::TileMap(const TileSet *new_tileset) : - tileset(new_tileset), - solid(false), - speed_x(1), - speed_y(1), + tileset(new_tileset), + tiles(), + real_solid(false), + effective_solid(false), + speed_x(1), + speed_y(1), width(0), - height(0), - z_pos(0), - x_offset(0), - y_offset(0), - movement(Vector(0,0)), + height(0), + z_pos(0), + offset(Vector(0,0)), + movement(0,0), drawing_effect(NO_EFFECT), - alpha(1.0), + alpha(1.0), current_alpha(1.0), remaining_fade_time(0), + path(), + walker(), draw_target(DrawingContext::NORMAL) { } TileMap::TileMap(const Reader& reader) : - solid(false), - speed_x(1), - speed_y(1), + tileset(), + tiles(), + real_solid(false), + effective_solid(false), + speed_x(1), + speed_y(1), width(-1), - height(-1), - z_pos(0), - x_offset(0), - y_offset(0), - movement(Vector(0,0)), + height(-1), + z_pos(0), + offset(Vector(0,0)), + movement(Vector(0,0)), drawing_effect(NO_EFFECT), - alpha(1.0), - current_alpha(1.0), + alpha(1.0), + current_alpha(1.0), remaining_fade_time(0), + path(), + walker(), draw_target(DrawingContext::NORMAL) { tileset = current_tileset; assert(tileset != NULL); reader.get("name", name); - reader.get("z-pos", z_pos); - reader.get("solid", solid); + reader.get("solid", real_solid); reader.get("speed", speed_x); reader.get("speed-y", speed_y); - - if(solid && ((speed_x != 1) || (speed_y != 1))) { + + z_pos = reader_get_layer (reader, /* default = */ 0); + + if(real_solid && ((speed_x != 1) || (speed_y != 1))) { log_warning << "Speed of solid tilemap is not 1. fixing" << std::endl; speed_x = 1; speed_y = 1; @@ -81,8 +89,7 @@ TileMap::TileMap(const Reader& reader) : path->read(*pathLisp); walker.reset(new PathWalker(path.get(), /*running*/false)); Vector v = path->get_base(); - set_x_offset(v.x); - set_y_offset(v.y); + set_offset(v); } std::string draw_target_s = "normal"; @@ -94,6 +101,10 @@ TileMap::TileMap(const Reader& reader) : current_alpha = alpha; } + /* Initialize effective_solid based on real_solid and current_alpha. */ + effective_solid = real_solid; + update_effective_solid (); + reader.get("width", width); reader.get("height", height); if(width < 0 || height < 0) @@ -118,30 +129,38 @@ TileMap::TileMap(const Reader& reader) : } if(empty) + { log_info << "Tilemap '" << name << "', z-pos '" << z_pos << "' is empty." << std::endl; + } } -TileMap::TileMap(const TileSet *new_tileset, std::string name, int z_pos, - bool solid, size_t width, size_t height) : - tileset(new_tileset), - solid(solid), - speed_x(1), - speed_y(1), +TileMap::TileMap(const TileSet *new_tileset, std::string name_, int z_pos_, + bool solid, size_t width_, size_t height_) : + tileset(new_tileset), + tiles(), + real_solid(solid), + effective_solid(solid), + speed_x(1), + speed_y(1), width(0), - height(0), - z_pos(z_pos), - x_offset(0), - y_offset(0), + height(0), + z_pos(z_pos_), + offset(Vector(0,0)), movement(Vector(0,0)), - drawing_effect(NO_EFFECT), - alpha(1.0), + drawing_effect(NO_EFFECT), + alpha(1.0), current_alpha(1.0), - remaining_fade_time(0), + remaining_fade_time(0), + path(), + walker(), draw_target(DrawingContext::NORMAL) { - this->name = name; + this->name = name_; + + if (this->z_pos > (LAYER_GUI - 100)) + this->z_pos = LAYER_GUI - 100; - resize(width, height); + resize(width_, height_); } TileMap::~TileMap() @@ -161,59 +180,66 @@ TileMap::update(float elapsed_time) if (amt > 0) current_alpha = std::min(current_alpha + amt, alpha); if (amt < 0) current_alpha = std::max(current_alpha + amt, alpha); } - if ((alpha < 0.25) && (current_alpha < 0.25)) set_solid(false); - if ((alpha > 0.75) && (current_alpha > 0.75)) set_solid(true); + update_effective_solid (); } movement = Vector(0,0); // if we have a path to follow, follow it if (walker.get()) { Vector v = walker->advance(elapsed_time); - movement = Vector(v.x-get_x_offset(), std::max(0.0f,v.y-get_y_offset())); - set_x_offset(v.x); - set_y_offset(v.y); + movement = v - get_offset(); + set_offset(v); } } void TileMap::draw(DrawingContext& context) { - // skip draw if current opacity is set to 0.0 + // skip draw if current opacity is 0.0 if (current_alpha == 0.0) return; context.push_transform(); - context.push_target(); - context.set_target(draw_target); + if(draw_target != DrawingContext::NORMAL) { + context.push_target(); + context.set_target(draw_target); + } if(drawing_effect != 0) context.set_drawing_effect(drawing_effect); if(current_alpha != 1.0) context.set_alpha(current_alpha); + /* Force the translation to be an integer so that the tiles appear sharper. + * For consistency (i.e., to avoid 1-pixel gaps), this needs to be done even + * for solid tilemaps that are guaranteed to have speed 1. + * FIXME Force integer translation for all graphics, not just tilemaps. */ float trans_x = roundf(context.get_translation().x); float trans_y = roundf(context.get_translation().y); context.set_translation(Vector(int(trans_x * speed_x), int(trans_y * speed_y))); - /** if we don't round here, we'll have a 1 pixel gap on screen sometimes. - * I have no idea why */ - float start_x = int((roundf(context.get_translation().x) - roundf(x_offset)) / 32) * 32 + roundf(x_offset); - float start_y = int((roundf(context.get_translation().y) - roundf(y_offset)) / 32) * 32 + roundf(y_offset); - float end_x = std::min(start_x + SCREEN_WIDTH + 32, float(width * 32 + roundf(x_offset))); - float end_y = std::min(start_y + SCREEN_HEIGHT + 32, float(height * 32 + roundf(y_offset))); - int tsx = int((start_x - roundf(x_offset)) / 32); // tilestartindex x - int tsy = int((start_y - roundf(y_offset)) / 32); // tilestartindex y + Rectf draw_rect = Rectf(context.get_translation(), + context.get_translation() + Vector(SCREEN_WIDTH, SCREEN_HEIGHT)); + Rect t_draw_rect = get_tiles_overlapping(draw_rect); + Vector start = get_tile_position(t_draw_rect.left, t_draw_rect.top); Vector pos; 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) { - if ((tx < 0) || (ty < 0)) continue; - const Tile* tile = tileset->get(tiles[ty*width + tx]); + + for(pos.x = start.x, tx = t_draw_rect.left; tx < t_draw_rect.right; pos.x += 32, ++tx) { + for(pos.y = start.y, ty = t_draw_rect.top; ty < t_draw_rect.bottom; pos.y += 32, ++ty) { + int index = ty*width + tx; + assert (index >= 0); + assert (index < (width * height)); + + if (tiles[index] == 0) continue; + const Tile* tile = tileset->get(tiles[index]); assert(tile != 0); tile->draw(context, pos, z_pos); - } - } + } /* for (pos y) */ + } /* for (pos x) */ - context.pop_target(); + if(draw_target != DrawingContext::NORMAL) { + context.pop_target(); + } context.pop_transform(); } @@ -242,15 +268,15 @@ void TileMap::expose(HSQUIRRELVM vm, SQInteger table_idx) { if (name.empty()) return; - Scripting::TileMap* interface = new Scripting::TileMap(this); - expose_object(vm, table_idx, interface, name, true); + scripting::TileMap* _this = new scripting::TileMap(this); + expose_object(vm, table_idx, _this, name, true); } void TileMap::unexpose(HSQUIRRELVM vm, SQInteger table_idx) { if (name.empty()) return; - Scripting::unexpose_object(vm, table_idx, name); + scripting::unexpose_object(vm, table_idx, name); } void @@ -266,8 +292,12 @@ TileMap::set(int newwidth, int newheight, const std::vector&newt, tiles.resize(newt.size()); tiles = newt; - z_pos = new_z_pos; - solid = newsolid; + if (new_z_pos > (LAYER_GUI - 100)) + z_pos = LAYER_GUI - 100; + else + z_pos = new_z_pos; + real_solid = newsolid; + update_effective_solid (); // make sure all tiles are loaded for(Tiles::iterator i = tiles.begin(); i != tiles.end(); ++i) @@ -306,10 +336,24 @@ TileMap::resize(int new_width, int new_height, int fill_id) width = new_width; } +Rect +TileMap::get_tiles_overlapping(const Rectf &rect) const +{ + Rectf rect2 = rect; + rect2.move(-offset); + + int t_left = std::max(0 , int(floorf(rect2.get_left () / 32))); + int t_right = std::min(width , int(ceilf (rect2.get_right () / 32))); + int t_top = std::max(0 , int(floorf(rect2.get_top () / 32))); + int t_bottom = std::min(height, int(ceilf (rect2.get_bottom() / 32))); + return Rect(t_left, t_top, t_right, t_bottom); +} + void TileMap::set_solid(bool solid) { - this->solid = solid; + this->real_solid = solid; + update_effective_solid (); } uint32_t @@ -333,7 +377,8 @@ TileMap::get_tile(int x, int y) const uint32_t TileMap::get_tile_id_at(const Vector& pos) const { - return get_tile_id(int(pos.x - x_offset)/32, int(pos.y - y_offset)/32); + Vector xy = (pos - offset) / 32; + return get_tile_id(int(xy.x), int(xy.y)); } const Tile* @@ -353,7 +398,8 @@ TileMap::change(int x, int y, uint32_t newtile) void TileMap::change_at(const Vector& pos, uint32_t newtile) { - change(int(pos.x - x_offset)/32, int(pos.y - y_offset)/32, newtile); + Vector xy = (pos - offset) / 32; + change(int(xy.x), int(xy.y), newtile); } void @@ -370,28 +416,39 @@ TileMap::change_all(uint32_t oldtile, uint32_t newtile) } void -TileMap::fade(float alpha, float seconds) +TileMap::fade(float alpha_, float seconds) { - this->alpha = alpha; + this->alpha = alpha_; this->remaining_fade_time = seconds; } -void -TileMap::set_alpha(float alpha) +void +TileMap::set_alpha(float alpha_) { - this->alpha = alpha; + this->alpha = alpha_; this->current_alpha = alpha; this->remaining_fade_time = 0; - if (current_alpha < 0.25) set_solid(false); - if (current_alpha > 0.75) set_solid(true); + update_effective_solid (); } -float +float TileMap::get_alpha() { return this->current_alpha; } - -IMPLEMENT_FACTORY(TileMap, "tilemap"); + +/* + * Private methods + */ +void +TileMap::update_effective_solid (void) +{ + if (!real_solid) + effective_solid = false; + else if (effective_solid && (current_alpha < .25)) + effective_solid = false; + else if (!effective_solid && (current_alpha >= .75)) + effective_solid = true; +} /* EOF */