void Background::draw_image(DrawingContext& context, const Vector& pos_) { Sizef level(Sector::current()->get_width(), Sector::current()->get_height()); Sizef screen(SCREEN_WIDTH, SCREEN_HEIGHT); Sizef parallax_image_size = (1.0f - speed) * screen + level * speed; Rectf cliprect = context.get_cliprect(); int start_x = static_cast<int>(floorf((cliprect.get_left() - (pos_.x - image->get_width() /2.0f)) / image->get_width())); int end_x = static_cast<int>(ceilf((cliprect.get_right() - (pos_.x + image->get_width() /2.0f)) / image->get_width()))+1; int start_y = static_cast<int>(floorf((cliprect.get_top() - (pos_.y - image->get_height()/2.0f)) / image->get_height())); int end_y = static_cast<int>(ceilf((cliprect.get_bottom() - (pos_.y + image->get_height()/2.0f)) / image->get_height()))+1; switch(alignment) { case LEFT_ALIGNMENT: for(int y = start_y; y < end_y; ++y) { Vector p(pos_.x - parallax_image_size.width / 2.0f, pos_.y + y * image->get_height() - image->get_height() / 2.0f); context.draw_surface(image, p, layer); } break; case RIGHT_ALIGNMENT: for(int y = start_y; y < end_y; ++y) { Vector p(pos_.x + parallax_image_size.width / 2.0f - image->get_width(), pos_.y + y * image->get_height() - image->get_height() / 2.0f); context.draw_surface(image, p, layer); } break; case TOP_ALIGNMENT: for(int x = start_x; x < end_x; ++x) { Vector p(pos_.x + x * image->get_width() - image->get_width() / 2.0f, pos_.y - parallax_image_size.height / 2.0f); context.draw_surface(image, p, layer); } break; case BOTTOM_ALIGNMENT: for(int x = start_x; x < end_x; ++x) { Vector p(pos_.x + x * image->get_width() - image->get_width() / 2.0f, pos_.y - image->get_height() + parallax_image_size.height / 2.0f); context.draw_surface(image, p, layer); } break; case NO_ALIGNMENT: for(int y = start_y; y < end_y; ++y) for(int x = start_x; x < end_x; ++x) { Vector p(pos_.x + x * image->get_width() - image->get_width()/2, pos_.y + y * image->get_height() - image->get_height()/2); if (image_top.get() != NULL && (y < 0)) { context.draw_surface(image_top, p, layer); } else if (image_bottom.get() != NULL && (y > 0)) { context.draw_surface(image_bottom, p, layer); } else { context.draw_surface(image, p, layer); } } break; } }
void TileMap::draw(DrawingContext& context) { // skip draw if current opacity is 0.0 if (m_current_alpha == 0.0f) return; context.push_transform(); if (m_flip != NO_FLIP) context.set_flip(m_flip); if (m_editor_active) { if (m_current_alpha != 1.0f) { context.set_alpha(m_current_alpha); } } else { context.set_alpha(m_current_alpha/2); } const float trans_x = context.get_translation().x; const float trans_y = context.get_translation().y; const bool normal_speed = m_editor_active && Editor::is_active(); context.set_translation(Vector(trans_x * (normal_speed ? 1.0f : m_speed_x), trans_y * (normal_speed ? 1.0f : m_speed_y))); Rectf draw_rect = context.get_cliprect(); 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; std::unordered_map<SurfacePtr, std::tuple<std::vector<Rectf>, std::vector<Rectf>>> batches; 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*m_width + tx; assert (index >= 0); assert (index < (m_width * m_height)); if (m_tiles[index] == 0) continue; const Tile& tile = m_tileset->get(m_tiles[index]); if (g_debug.show_collision_rects) { tile.draw_debug(context.color(), pos, LAYER_FOREGROUND1); } const SurfacePtr& surface = Editor::is_active() ? tile.get_current_editor_surface() : tile.get_current_surface(); if (surface) { std::get<0>(batches[surface]).emplace_back(surface->get_region()); std::get<1>(batches[surface]).emplace_back(pos, Sizef(static_cast<float>(surface->get_width()), static_cast<float>(surface->get_height()))); } } } Canvas& canvas = context.get_canvas(m_draw_target); for (auto& it : batches) { const SurfacePtr& surface = it.first; if (surface) { canvas.draw_surface_batch(surface, std::move(std::get<0>(it.second)), std::move(std::get<1>(it.second)), m_current_tint, m_z_pos); } } context.pop_transform(); }