Ejemplo n.º 1
0
void
TextObject::draw(DrawingContext& context)
{
  context.push_transform();
  context.set_translation(Vector(0, 0));
  if(fading > 0) {
    context.set_alpha((fadetime-fading) / fadetime);
  } else if(fading < 0) {
    context.set_alpha(-fading / fadetime);
  } else if(!visible) {
    context.pop_transform();
    return;
  }

  float width  = 500;
  float height = 70;
  Vector spos = pos + get_anchor_pos(Rectf(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),
                                     width, height, anchor);

  context.draw_filled_rect(spos, Vector(width, height),
                           Color(0.6f, 0.7f, 0.8f, 0.5f), LAYER_GUI-50);
  if (centered) {
    context.draw_center_text(font, text, spos, LAYER_GUI-40, TextObject::default_color);
  } else {
    context.draw_text(font, text, spos + Vector(10, 10), ALIGN_LEFT, LAYER_GUI-40, TextObject::default_color);
  }

  context.pop_transform();
}
Ejemplo n.º 2
0
void
TileMap::draw(DrawingContext& context)
{
  // skip draw if current opacity is 0.0
  if (current_alpha == 0.0) return;

  context.push_transform();
  if(draw_target != DrawingContext::NORMAL) {
    context.push_target();
    context.set_target(draw_target);
  }

  if(drawing_effect != 0) context.set_drawing_effect(drawing_effect);

  if (editor_active) {
    if(current_alpha != 1.0) {
      context.set_alpha(current_alpha);
    }
  } else {
    context.set_alpha(current_alpha/2);
  }

  /* 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)));

  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 = 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) */

  if(draw_target != DrawingContext::NORMAL) {
    context.pop_target();
  }
  context.pop_transform();
}
Ejemplo n.º 3
0
void
GhostTree::draw(DrawingContext& context)
{
  BadGuy::draw(context);

  context.push_target();
  context.push_transform();
  context.set_target(DrawingContext::LIGHTMAP);
  if (mystate == STATE_SUCKING) {
    context.set_alpha(0.5 + fmodf(game_time, 0.5));
  } else {
    context.set_alpha(0.5);
  }
  glow_sprite->draw(context, get_pos(), layer);
  context.pop_transform();
  context.pop_target();
}
Ejemplo n.º 4
0
void
Console::draw(DrawingContext& context)
{
  if (m_height == 0)
    return;

  int layer = LAYER_GUI + 1;

  context.push_transform();
  context.set_alpha(m_alpha);
  context.draw_surface(m_background2,
                       Vector(SCREEN_WIDTH/2 - m_background->get_width()/2 - m_background->get_width() + m_backgroundOffset,
                              m_height - m_background->get_height()),
                       layer);
  context.draw_surface(m_background2,
                       Vector(SCREEN_WIDTH/2 - m_background->get_width()/2 + m_backgroundOffset,
                              m_height - m_background->get_height()),
                       layer);
  for (int x = (SCREEN_WIDTH/2 - m_background->get_width()/2
                - (static_cast<int>(ceilf((float)SCREEN_WIDTH /
                                          (float)m_background->get_width()) - 1) * m_background->get_width()));
       x < SCREEN_WIDTH;
       x += m_background->get_width())
  {
    context.draw_surface(m_background, Vector(x, m_height - m_background->get_height()), layer);
  }
  m_backgroundOffset+=10;
  if (m_backgroundOffset > (int)m_background->get_width()) m_backgroundOffset -= (int)m_background->get_width();

  int lineNo = 0;

  if (m_focused) {
    lineNo++;
    float py = m_height-4-1 * m_font->get_height();
    context.draw_text(m_font, "> "+m_inputBuffer, Vector(4, py), ALIGN_LEFT, layer);
    if (SDL_GetTicks() % 1000 < 750) {
      int cursor_px = 2 + m_inputBufferPosition;
      context.draw_text(m_font, "_", Vector(4 + (cursor_px * m_font->get_text_width("X")), py), ALIGN_LEFT, layer);
    }
  }

  int skipLines = -m_offset;
  for (std::list<std::string>::iterator i = m_buffer.m_lines.begin(); i != m_buffer.m_lines.end(); i++)
  {
    if (skipLines-- > 0) continue;
    lineNo++;
    float py = m_height - 4 - lineNo * m_font->get_height();
    if (py < -m_font->get_height()) break;
    context.draw_text(m_font, *i, Vector(4, py), ALIGN_LEFT, layer);
  }
  context.pop_transform();
}
Ejemplo n.º 5
0
void
FloatingImage::draw(DrawingContext& context)
{
  context.push_transform();
  context.set_translation(Vector(0, 0));

  if(fading > 0) {
    context.set_alpha((fadetime-fading) / fadetime);
  } else if(fading < 0) {
    context.set_alpha(-fading / fadetime);
  } else if(!visible) {
    context.pop_transform();
    return;
  }

  Vector spos = pos + get_anchor_pos(Rectf(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),
                                     sprite->get_width(), sprite->get_height(), anchor);

  sprite->draw(context, spos, layer);

  context.pop_transform();
}
Ejemplo n.º 6
0
void
InfoBlock::draw(DrawingContext& context)
{
  Block::draw(context);

  if (shown_pct <= 0) return;

  context.push_transform();
  //context.set_translation(Vector(0, 0));
  context.set_alpha(shown_pct);

  //float x1 = SCREEN_WIDTH/2-200;
  //float y1 = SCREEN_HEIGHT/2-200;
  float border = 8;
  float width = 400; // this is the text width only
  float height = lines_height; // this is the text height only
  float x1 = (bbox.p1.x + bbox.p2.x)/2 - width/2;
  float x2 = (bbox.p1.x + bbox.p2.x)/2 + width/2;
  float y1 = original_y - height;

  if(x1 < 0) {
    x1 = 0;
    x2 = width;
  }

  if(x2 > Sector::current()->get_width()) {
    x2 = Sector::current()->get_width();
    x1 = x2 - width;
  }

  // lines_height includes one ITEMS_SPACE too much, so the bottom border is reduced by 4px
  context.draw_filled_rect(Vector(x1-border, y1-border), Vector(width+2*border, height+2*border-4), Color(0.6f, 0.7f, 0.8f, 0.5f), LAYER_GUI-50);

  float y = y1;
  for(size_t i = 0; i < lines.size(); ++i) {
    if(y >= y1 + height) {
      //log_warning << "Too many lines of text in InfoBlock" << std::endl;
      //dest_pct = 0;
      //shown_pct = 0;
      break;
    }

    lines[i]->draw(context, Rectf(x1, y, x2, y), LAYER_GUI-50+1);
    y += lines[i]->get_height();
  }

  context.pop_transform();
}
Ejemplo n.º 7
0
void
FloatingText::draw(DrawingContext& context)
{
  // make an alpha animation when disappearing
  int alpha;
  if(timer.get_timeleft() < FADING_TIME)
    alpha = int(timer.get_timeleft() * 255 / FADING_TIME);
  else
    alpha = 255;

  context.push_transform();
  context.set_alpha(alpha);

  context.draw_text(Resources::normal_font, text, position, ALIGN_LEFT, LAYER_OBJECTS+1, FloatingText::text_color);

  context.pop_transform();
}
Ejemplo n.º 8
0
void
BouncyCoin::draw(DrawingContext& context)
{
  float time_left = timer.get_timeleft();
  bool fading = time_left < FADE_TIME;
  if(fading) {
    float alpha = time_left/FADE_TIME;
    context.push_transform();
    context.set_alpha(alpha);
  }

  int layer;
  if(emerge_distance > 0) {
    layer = LAYER_OBJECTS - 5;
  } else {
    layer = LAYER_OBJECTS + 5;
  }
  sprite->draw(context, position, layer);

  if(fading) {
    context.pop_transform();
  }
}
Ejemplo n.º 9
0
void
Statistics::draw_worldmap_info(DrawingContext& context)
{
  // skip draw if level was never played
  if (coins == nv_coins) return;

  // skip draw if stats were declared invalid
  if (!valid) return;

  context.draw_text(white_small_text, std::string("- ") + _("Best Level Statistics") + " -", Vector((WMAP_INFO_LEFT_X + WMAP_INFO_RIGHT_X) / 2, WMAP_INFO_TOP_Y1), CENTER_ALLIGN, LAYER_GUI);

  float alpha;
  if(timer.get_timegone() < FADING_TIME)
    alpha = (timer.get_timegone() * 1.0f / FADING_TIME);
  else if(timer.get_timeleft() < FADING_TIME)
    alpha = (timer.get_timeleft() * 1.0f / FADING_TIME);
  else
    alpha = 1.0f;

  context.push_transform();
  context.set_alpha(alpha);

  char caption_buf[128];
  char stat_buf[128];
  switch (display_stat)
  {
    case 0:
      snprintf(caption_buf, sizeof(caption_buf), _("Max coins collected:"));
      snprintf(stat_buf, sizeof(stat_buf), "%d/%d", coins, total_coins);
      break;
    case 1:
      snprintf(caption_buf, sizeof(caption_buf), _("Max fragging:"));
      snprintf(stat_buf, sizeof(stat_buf), "%d/%d", badguys, total_badguys);
      break;
    case 2:
      snprintf(caption_buf, sizeof(caption_buf), _("Min time needed:"));
      {
	int csecs = (int)(time * 100);
	int mins = (int)(csecs / 6000);
	int secs = (csecs % 6000) / 100;
	snprintf(stat_buf, sizeof(stat_buf), "%02d:%02d", mins,secs);
      }
      break;
    case 3:
      snprintf(caption_buf, sizeof(caption_buf), _("Max secrets found:"));
      snprintf(stat_buf, sizeof(stat_buf), "%d/%d", secrets, total_secrets);
      break;
    default:
      log_debug << "Invalid stat requested to be drawn" << std::endl;
      break;
  }

  if (!timer.started())
  {
    timer.start(TOTAL_DISPLAY_TIME);
    display_stat++;
    if (display_stat > 3) display_stat = 0;
  }

  context.draw_text(white_small_text, caption_buf, Vector(WMAP_INFO_LEFT_X, WMAP_INFO_TOP_Y2), LEFT_ALLIGN, LAYER_GUI);
  context.draw_text(white_small_text, stat_buf, Vector(WMAP_INFO_RIGHT_X, WMAP_INFO_TOP_Y2), RIGHT_ALLIGN, LAYER_GUI);
  context.pop_transform();
}
Ejemplo n.º 10
0
void
Statistics::draw_endseq_panel(DrawingContext& context, Statistics* best_stats, Surface* backdrop)
{
  // skip draw if level was never played
  // TODO: do we need this?
  if (coins == nv_coins) return;

  // skip draw if stats were declared invalid
  if (!valid) return;

  // abort if we have no backdrop
  if (!backdrop) return;

  int box_w = 220+110+110;
  int box_h = 30+20+20+20;
  int box_x = (int)((SCREEN_WIDTH - box_w) / 2);
  int box_y = (int)(SCREEN_HEIGHT / 2) - box_h;

  int bd_w = (int)backdrop->get_width();
  int bd_h = (int)backdrop->get_height();
  int bd_x = (int)((SCREEN_WIDTH - bd_w) / 2);
  int bd_y = box_y + (box_h / 2) - (bd_h / 2);

  int col1_x = box_x;
  int col2_x = col1_x+200;
  int col3_x = col2_x+130;

  int row1_y = box_y;
  int row2_y = row1_y+30;
  int row3_y = row2_y+20;
  int row4_y = row3_y+20;

  context.push_transform();
  context.set_alpha(0.5);
  context.draw_surface(backdrop, Vector(bd_x, bd_y), LAYER_GUI);
  context.pop_transform();

  char buf[129];
  context.draw_text(white_text, _("You"), Vector(col2_x, row1_y), LEFT_ALLIGN, LAYER_GUI);
  context.draw_text(white_text, _("Best"), Vector(col3_x, row1_y), LEFT_ALLIGN, LAYER_GUI);

  context.draw_text(white_text, _("Coins"), Vector(col2_x-16, row2_y), RIGHT_ALLIGN, LAYER_GUI);
  snprintf(buf, sizeof(buf), "%d/%d", std::min(coins, 999), std::min(total_coins, 999));
  context.draw_text(gold_text, buf, Vector(col2_x, row2_y), LEFT_ALLIGN, LAYER_GUI);
  if (best_stats && (best_stats->coins > coins)) {
    snprintf(buf, sizeof(buf), "%d/%d", std::min(best_stats->coins, 999), std::min(best_stats->total_coins, 999));
  }
  context.draw_text(gold_text, buf, Vector(col3_x, row2_y), LEFT_ALLIGN, LAYER_GUI);

  context.draw_text(white_text, _("Secrets"), Vector(col2_x-16, row4_y), RIGHT_ALLIGN, LAYER_GUI);
  snprintf(buf, sizeof(buf), "%d/%d", secrets, total_secrets);
  context.draw_text(gold_text, buf, Vector(col2_x, row4_y), LEFT_ALLIGN, LAYER_GUI);
  if (best_stats && (best_stats->secrets > secrets)) {
    snprintf(buf, sizeof(buf), "%d/%d", best_stats->secrets, best_stats->total_secrets);
  }
  context.draw_text(gold_text, buf, Vector(col3_x, row4_y), LEFT_ALLIGN, LAYER_GUI);

  context.draw_text(white_text, _("Time"), Vector(col2_x-16, row3_y), RIGHT_ALLIGN, LAYER_GUI);
  int csecs = (int)(time * 100);
  int mins = (int)(csecs / 6000);
  int secs = (csecs % 6000) / 100;
  snprintf(buf, sizeof(buf), "%02d:%02d", mins,secs);
  context.draw_text(gold_text, buf, Vector(col2_x, row3_y), LEFT_ALLIGN, LAYER_GUI);
  if (best_stats && (best_stats->time < time)) {
    int csecs = (int)(best_stats->time * 100);
    int mins = (int)(csecs / 6000);
    int secs = (csecs % 6000) / 100;
    snprintf(buf, sizeof(buf), "%02d:%02d", mins,secs);
  }
  context.draw_text(gold_text, buf, Vector(col3_x, row3_y), LEFT_ALLIGN, LAYER_GUI);
}
Ejemplo n.º 11
0
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();
}
Ejemplo n.º 12
0
void
Statistics::draw_endseq_panel(DrawingContext& context, Statistics* best_stats, SurfacePtr backdrop)
{
  // skip draw if stats were declared invalid
  if (!valid) return;

  // abort if we have no backdrop
  if (!backdrop) return;

  // no sense drawing stats if there are none
  if (total_coins + total_badguys + total_secrets == 0) return;

  int box_w = 220+110+110;
  int box_h = 30+20+20+20;
  int box_x = (int)((SCREEN_WIDTH - box_w) / 2);
  int box_y = (int)(SCREEN_HEIGHT / 2) - box_h;

  int bd_w = (int)backdrop->get_width();
  int bd_h = (int)backdrop->get_height();
  int bd_x = (int)((SCREEN_WIDTH - bd_w) / 2);
  int bd_y = box_y + (box_h / 2) - (bd_h / 2);

  int col1_x = box_x;
  int col2_x = col1_x+200;
  int col3_x = col2_x+130;

  int row1_y = box_y;
  int row2_y = row1_y+30;
  int row3_y = row2_y+20;
  int row4_y = row3_y+20;
  int row5_y = row4_y+20;

  context.push_transform();
  context.set_alpha(0.5);
  context.draw_surface(backdrop, Vector(bd_x, bd_y), LAYER_HUD);
  context.pop_transform();

  context.draw_text(Resources::normal_font, _("You"), Vector(col2_x, row1_y), ALIGN_LEFT, LAYER_HUD, Statistics::header_color);
  if (best_stats)
    context.draw_text(Resources::normal_font, _("Best"), Vector(col3_x, row1_y), ALIGN_LEFT, LAYER_HUD, Statistics::header_color);

  context.draw_text(Resources::normal_font, _("Coins"), Vector(col2_x-16, row3_y), ALIGN_RIGHT, LAYER_HUD, Statistics::header_color);
  context.draw_text(Resources::normal_font, coins_to_string(coins, total_coins), Vector(col2_x, row3_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  if (best_stats) {
    int coins_best = (best_stats->coins > coins) ? best_stats->coins : coins;
    int total_coins_best = (best_stats->total_coins > total_coins) ? best_stats->total_coins : total_coins;
    context.draw_text(Resources::normal_font, coins_to_string(coins_best, total_coins_best), Vector(col3_x, row3_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  }

  context.draw_text(Resources::normal_font, _("Badguys"), Vector(col2_x-16, row4_y), ALIGN_RIGHT, LAYER_HUD, Statistics::header_color);
  context.draw_text(Resources::normal_font, frags_to_string(badguys, total_badguys), Vector(col2_x, row4_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  if (best_stats) {
	int badguys_best = (best_stats->badguys > badguys) ? best_stats->badguys : badguys;
	int total_badguys_best = (best_stats->total_badguys > total_badguys) ? best_stats->total_badguys : total_badguys;
	context.draw_text(Resources::normal_font, frags_to_string(badguys_best, total_badguys_best), Vector(col3_x, row4_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  }

  context.draw_text(Resources::normal_font, _("Secrets"), Vector(col2_x-16, row5_y), ALIGN_RIGHT, LAYER_HUD, Statistics::header_color);
  context.draw_text(Resources::normal_font, secrets_to_string(secrets, total_secrets), Vector(col2_x, row5_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  if (best_stats) {
    int secrets_best = (best_stats->secrets > secrets) ? best_stats->secrets : secrets;
    int total_secrets_best = (best_stats->total_secrets > total_secrets) ? best_stats->total_secrets : total_secrets;
    context.draw_text(Resources::normal_font, secrets_to_string(secrets_best, total_secrets_best), Vector(col3_x, row5_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  }

  context.draw_text(Resources::normal_font, _("Time"), Vector(col2_x-16, row2_y), ALIGN_RIGHT, LAYER_HUD, Statistics::header_color);
  context.draw_text(Resources::normal_font, time_to_string(time), Vector(col2_x, row2_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  if (best_stats) {
    float time_best = (best_stats->time < time) ? best_stats->time : time;
    context.draw_text(Resources::normal_font, time_to_string(time_best), Vector(col3_x, row2_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  }
}
Ejemplo n.º 13
0
void
TileMap::draw(DrawingContext& context)
{
  // skip draw if current opacity is 0.0
  if (current_alpha == 0.0) return;

  context.push_transform();
  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)));

  Rectf draw_rect = Rectf(context.get_translation(),
        context.get_translation() + Vector(SCREEN_WIDTH, SCREEN_HEIGHT));
  Rect t_draw_rect = get_tiles_overlapping(draw_rect);

  // Make sure the tilemap is within draw view
  if (t_draw_rect.is_valid()) {
    Vector start = get_tile_position(t_draw_rect.left, t_draw_rect.top);

    Vector pos;
    int tx, ty;

    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, current_tint);
      } /* for (pos y) */
    } /* for (pos x) */

    /* Make sure that tiles with images larger than 32x32 that overlap
     * the draw rect will be drawn, even if their tile position does
     * not fall within the draw rect. */
    static const int EXTENDING_TILES = 32;
    int ex_left = std::max(0, t_draw_rect.left-EXTENDING_TILES);
    int ex_top = std::max(0, t_draw_rect.top-EXTENDING_TILES);
    Vector ex_start = get_tile_position(ex_left, ex_top);

    for (pos.x = start.x, tx = t_draw_rect.left; tx < t_draw_rect.right; pos.x += 32, ++tx) {
      for (pos.y = ex_start.y, ty = ex_top; ty < t_draw_rect.top; 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);

        SurfacePtr image = tile->get_current_image();
        if (image) {
          int h = image->get_height();
          if (h <= 32) continue;

          if (pos.y + h > start.y)
            tile->draw(context, pos, z_pos, current_tint);
        }
      }
    }

    for (pos.x = ex_start.x, tx = ex_left; tx < t_draw_rect.right; pos.x += 32, ++tx) {
      for(pos.y = ex_start.y, ty = ex_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);

        SurfacePtr image = tile->get_current_image();
        if (image) {
          int w = image->get_width();
          int h = image->get_height();
          if (w <= 32 && h <= 32) continue;

          if (pos.x + w > start.x && pos.y + h > start.y)
            tile->draw(context, pos, z_pos, current_tint);
        }
      }
    }
  }

  if(draw_target != DrawingContext::NORMAL) {
    context.pop_target();
  }
  context.pop_transform();
}