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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); } }
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(); }
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); }
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(); }
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); } }
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(); }