Simplify display updating:

...always use display::invalidate() then display::draw(), not
display::draw_tile().

This means display needs to be told about moving units (can't be on
map, because can overlap).  This means there is only one caller of
draw_tile (draw), so it can figure out all the drawing which needs
doing and do units right at end, dealing with overlap.  We currently
invalidate all hexes around any unit: if this is too slow, we should
ask the unit itself what hexes it overlaps.
This commit is contained in:
Rusty Russell 2006-04-29 13:31:07 +00:00
parent 21c83c48c1
commit 43e16b7f96
9 changed files with 154 additions and 143 deletions

View file

@ -161,8 +161,8 @@ std::string recruit_unit(const gamemap& map, int side,
un->second.set_hidden(false);
un->second.set_recruited(*disp);
while(!un->second.get_animation()->animation_finished()) {
disp->draw_tile(recruit_location.x,recruit_location.y);
disp->update_display();
disp->invalidate(recruit_location);
disp->draw();
events::pump();
if(!disp->turbo()) SDL_Delay(10);
@ -1238,7 +1238,7 @@ void attack(display& gui, const gamemap& map,
units.insert(std::pair<gamemap::location,unit>(loc,newunit));
if (update_display){
gui.draw_tile(loc.x,loc.y);
gui.invalidate(loc);
}
}else{
LOG_NG<<"unit not reanimated"<<std::endl;
@ -1247,7 +1247,7 @@ void attack(display& gui, const gamemap& map,
if (update_display){
recalculate_fog(map,state,info,units,teams,defender_side-1);
gui.recalculate_minimap();
gui.update_display();
gui.draw();
}
break;
} else if(hits) {
@ -1479,7 +1479,7 @@ void attack(display& gui, const gamemap& map,
units.insert(std::pair<gamemap::location,unit>(loc,newunit));
if (update_display){
gui.draw_tile(loc.x,loc.y);
gui.invalidate(loc);
}
}else{
LOG_NG<<"unit not reanimated"<<std::endl;
@ -1487,7 +1487,7 @@ void attack(display& gui, const gamemap& map,
}
if (update_display){
gui.recalculate_minimap();
gui.update_display();
gui.draw();
recalculate_fog(map,state,info,units,teams,attacker_side-1);
}
break;
@ -1807,10 +1807,10 @@ void calculate_healing(display& disp, const gamestatus& status, const gamemap& m
bool finished;
do {
finished = (i->second.get_animation()->animation_finished());
disp.draw_tile(i->first.x, i->first.y);
disp.invalidate(i->first);
for(std::vector<unit_map::iterator>::iterator heal_fanim_it = healers.begin(); heal_fanim_it != healers.end(); ++heal_fanim_it) {
finished &= (*heal_fanim_it)->second.get_animation()->animation_finished();
disp.draw_tile((*heal_fanim_it)->first.x,(*heal_fanim_it)->first.y);
disp.invalidate((*heal_fanim_it)->first);
}
if (healing > 0) {
i->second.heal(1);
@ -1820,7 +1820,7 @@ void calculate_healing(display& disp, const gamestatus& status, const gamemap& m
++healing;
}
finished &= (!healing);
disp.update_display();
disp.draw();
events::pump();
SDL_Delay(10);
} while (!finished);
@ -2250,7 +2250,7 @@ size_t move_unit(display* disp, const game_data& gamedata,
//still display the correct number of units.
if(disp != NULL) {
ui->second.set_hidden(true);
disp->draw_tile(ui->first.x,ui->first.y);
disp->invalidate(ui->first);
unit_display::move_unit(*disp,map,steps,u,status.get_time_of_day(),units,teams);
ui->second.set_hidden(false);
}
@ -2263,6 +2263,7 @@ size_t move_unit(display* disp, const game_data& gamedata,
if(disp != NULL) {
disp->invalidate_unit();
disp->invalidate(steps.back());
disp->draw();
}
if(move_recorder != NULL) {

View file

@ -480,7 +480,7 @@ gamemap::location ai_interface::move_unit_partial(location from, location to, st
}
if(show_move) {
info_.disp.draw_tile(to.x,to.y);
info_.disp.invalidate(to);
info_.disp.draw();
}

View file

@ -135,8 +135,8 @@ bool animate_unit_advancement(const game_data& info,unit_map& units, gamemap::lo
if(!gui.update_locked()) {
u->second.set_leveling_out(gui);
while(!u->second.get_animation()->animation_finished()) {
gui.draw_tile(loc.x,loc.y);
gui.update_display();
gui.invalidate(loc);
gui.draw();
events::pump();
if(!gui.turbo()) SDL_Delay(10);
}
@ -158,14 +158,14 @@ bool animate_unit_advancement(const game_data& info,unit_map& units, gamemap::lo
if(!gui.update_locked()) {
u->second.set_leveling_in(gui);
while(!u->second.get_animation()->animation_finished()) {
gui.draw_tile(loc.x,loc.y);
gui.update_display();
gui.invalidate(loc);
gui.draw();
events::pump();
if(!gui.turbo()) SDL_Delay(10);
}
u->second.set_standing(gui);
gui.draw_tile(loc.x,loc.y);
gui.update_display();
gui.invalidate(loc);
gui.draw();
events::pump();
}

View file

@ -80,6 +80,7 @@ display::display(unit_map& units, CVideo& video, const gamemap& map,
const config& theme_cfg, const config& cfg, const config& level) :
screen_(video), xpos_(0), ypos_(0),
zoom_(DefaultZoom), map_(map), units_(units),
temp_unit_(NULL),
minimap_(NULL), redrawMinimap_(false),
status_(status),
teams_(t), lastDraw_(0), drawSkips_(0),
@ -831,28 +832,43 @@ void display::draw(bool update,bool force)
get_visible_hex_bounds(topleft, bottomright);
for(int x = topleft.x; x <= bottomright.x; ++x)
for(int y = topleft.y; y <= bottomright.y; ++y)
draw_tile(x,y);
invalidated_.insert(gamemap::location(x,y));
invalidateAll_ = false;
redrawMinimap_ = true;
}
if(!map_.empty() && !invalidated_.empty()) {
changed = true;
} else if(!map_.empty()) {
if(!invalidated_.empty()) {
changed = true;
// Units can overlap multiple hexes, so we need to (1) redraw
// them last, and (2) redraw them if they are adjacent existing hexes.
std::set<gamemap::location> unit_invals;
std::set<gamemap::location>::const_iterator it;
for(it = invalidated_.begin(); it != invalidated_.end(); ++it) {
if (units_.find(*it) != units_.end()) {
unit_invals.insert(*it);
}
draw_tile(*it);
gamemap::location adjacent[6];
get_adjacent_tiles(*it, adjacent);
for (int i = 0; i < 6; i++) {
if (units_.find(adjacent[i]) != units_.end())
unit_invals.insert(adjacent[i]);
}
}
std::set<gamemap::location> invalidated_temp = invalidated_;
/*
for (std::set<gamemap::location>::const_iterator it =
invalidated_.begin(); it != invalidated_.end(); ++it){
invalidated_temp.insert(it);
for(it = unit_invals.begin(); it != unit_invals.end(); ++it) {
unit &u = units_.find(*it)->second;
u.refresh();
u.refresh_unit(*this, *it, true);
}
*/
for(std::set<gamemap::location>::const_iterator it =
invalidated_temp.begin(); it != invalidated_temp.end(); ++it) {
draw_tile(it->x,it->y);
if (temp_unit_ && invalidated_.find(temp_unit_loc_) != invalidated_.end()) {
temp_unit_->refresh();
temp_unit_->refresh_unit(*this, temp_unit_loc_, false);
}
invalidated_.clear();
}
@ -1331,25 +1347,10 @@ void display::draw_terrain_on_tile(int x, int y, image::TYPE image_type, ADJACEN
}
}
void display::draw_tile(int x, int y)
void display::draw_tile(const gamemap::location &loc)
{
// list of tiles in the process of being redrawn (protect from recursion problems
static int recursion_level = 0;
static std::set<gamemap::location> redrawn;
reach_map::iterator reach = reach_map_.end();
const gamemap::location loc(x,y);
if (redrawn.find(loc) != redrawn.end()) {
//this tile has already redrawn the terrain and is waiting to redraw the "upper half" (unit)
return;
}
unit_map::iterator it = units_.find(loc);
if(it != units_.end()) {
it->second.refresh();
}
if(screen_.update_locked()) {
return;
}
@ -1369,7 +1370,7 @@ void display::draw_tile(int x, int y)
clip_rect_setter set_clip_rect(dst,clip_rect);
const bool is_shrouded = shrouded(x,y);
const bool is_shrouded = shrouded(loc.x, loc.y);
gamemap::TERRAIN terrain = gamemap::VOID_TERRAIN;
if(!is_shrouded) {
@ -1388,7 +1389,7 @@ void display::draw_tile(int x, int y)
//find if this tile should be darkened or bightened (reach of a unit)
if (!reach_map_.empty()) {
reach = reach_map_.find(gamemap::location(x,y));
reach = reach_map_.find(loc);
if (reach == reach_map_.end()) {
image_type = image::DARKENED;
} else {
@ -1407,9 +1408,9 @@ void display::draw_tile(int x, int y)
}
if(!is_shrouded) {
draw_terrain_on_tile(x,y,image_type,ADJACENT_BACKGROUND);
draw_terrain_on_tile(loc.x,loc.y,image_type,ADJACENT_BACKGROUND);
surface flag(get_flag(terrain,x,y));
surface flag(get_flag(terrain,loc.x,loc.y));
if(flag != NULL) {
SDL_Rect dstrect = { xpos, ypos, 0, 0 };
SDL_BlitSurface(flag,NULL,dst,&dstrect);
@ -1446,42 +1447,11 @@ void display::draw_tile(int x, int y)
draw_footstep(loc,xpos,ypos);
if(!is_shrouded) {
draw_terrain_on_tile(x,y,image_type,ADJACENT_FOREGROUND);
draw_terrain_on_tile(loc.x,loc.y,image_type,ADJACENT_FOREGROUND);
draw_movement_info(loc,xpos,ypos);
}
//first half is done, mark ourselves as half refreshed
//redrawn.insert(loc);
gamemap::location adjacent[6];
get_adjacent_tiles(loc, adjacent);
for(int tile = 0; tile != 6; ++tile) {
if ((units_.find(adjacent[tile]) != units_.end()) && (recursion_level < 2)) {
// neighbour contains a unit, since its unit could overlap on us, we must redraw it
recursion_level++;
//std::cerr << "recursion_level: " << recursion_level << "\n";
draw_tile(adjacent[tile].x, adjacent[tile].y);
recursion_level--;
}
}
if(it != units_.end()) {
//Is this really necessary? If we overlap on an adjacent tile, there should be nothing
//essential to be redrawn i guess
/*
// neighbours must be redrawn because we overlap on them
for(int tile = 0; tile != 6; ++tile) {
recursion_level++;
if (recursion_level < 2){
draw_tile(adjacent[tile].x, adjacent[tile].y);
}
recursion_level--;
}
*/
it->second.refresh_unit(*this,loc,true);
}
if(fogged(x,y) && shrouded(x,y) == false) {
if(fogged(loc.x,loc.y) && shrouded(loc.x,loc.y) == false) {
const surface fog_surface(image::get_image("terrain/fog.png"));
if(fog_surface != NULL) {
SDL_Rect dstrect = { xpos, ypos, 0, 0 };
@ -1489,8 +1459,8 @@ void display::draw_tile(int x, int y)
}
}
if(!shrouded(x,y)) {
draw_terrain_on_tile(x,y,image_type,ADJACENT_FOGSHROUD);
if(!shrouded(loc.x,loc.y)) {
draw_terrain_on_tile(loc.x,loc.y,image_type,ADJACENT_FOGSHROUD);
if (reach != reach_map_.end())
draw_enemies_reach(reach->second,xpos,ypos);
}
@ -1522,7 +1492,7 @@ void display::draw_tile(int x, int y)
}
}
if(game_config::debug && debugHighlights_.count(gamemap::location(x,y))) {
if(game_config::debug && debugHighlights_.count(loc)) {
const surface cross(image::get_image(game_config::cross_image));
if(cross != NULL) {
draw_unit(xpos,ypos,cross,false,debugHighlights_[loc],0);
@ -1530,10 +1500,6 @@ void display::draw_tile(int x, int y)
}
update_rect(xpos,ypos,zoom_,zoom_);
//redrawing is done
redrawn.erase(loc);
//avoid useless redrawin
invalidated_.erase(loc);
}
void display::draw_enemies_reach(unsigned int num, int xloc, int yloc)
@ -2035,7 +2001,16 @@ const SDL_Rect& display::calculate_energy_bar(surface surf)
void display::invalidate(const gamemap::location& loc)
{
if(!invalidateAll_) {
invalidated_.insert(loc);
if (invalidated_.insert(loc).second) {
// Units can overlap adjacent tiles.
if (units_.find(loc) != units_.end()) {
gamemap::location adjacent[6];
get_adjacent_tiles(loc, adjacent);
for (int i = 0; i < 6; i++) {
invalidated_.insert(adjacent[i]);
}
}
}
}
}
@ -2091,6 +2066,29 @@ void display::redraw_minimap()
redrawMinimap_ = true;
}
void display::place_temporary_unit(unit &u, const gamemap::location& loc)
{
temp_unit_ = &u;
temp_unit_loc_ = loc;
gamemap::location adjacent[6];
get_adjacent_tiles(loc, adjacent);
for (int i = 0; i < 6; i++) {
invalidated_.insert(adjacent[i]);
}
}
void display::remove_temporary_unit()
{
temp_unit_ = NULL;
gamemap::location adjacent[6];
get_adjacent_tiles(temp_unit_loc_, adjacent);
for (int i = 0; i < 6; i++) {
invalidated_.insert(adjacent[i]);
}
}
void display::invalidate_game_status()
{
invalidateGameStatus_ = true;

View file

@ -191,12 +191,6 @@ public:
//function to remove a footstep from a specific location
void remove_footstep(const gamemap::location& loc);
//function to draw the tile at location (x,y). If unit_image is not NULL,
//then it will be used, otherwise the unit's default image will be used.
//alpha controls how faded the unit is. If blend_to is not 0, then the
//unit will be alpha-blended to blend_to instead of the background colour
void draw_tile(int x, int y);
//function to float a label above a tile
void float_label(const gamemap::location& loc, const std::string& text,
int red, int green, int blue);
@ -232,7 +226,7 @@ public:
//function to invalidate all tiles.
void invalidate_all();
//function to invalidate a specific tile
//function to invalidate a specific tile for redrawing
void invalidate(const gamemap::location& loc);
//function to invalidate the game status displayed on the sidebar.
@ -253,6 +247,10 @@ public:
//have moved about on the map
void redraw_minimap();
//temporarily place a unit on map (moving: can overlap others)
void place_temporary_unit(unit &u, const gamemap::location& loc);
void remove_temporary_unit();
//functions to add and remove overlays from locations. An overlay is an
//image that is displayed on top of the tile. One tile may have multiple
//overlays. remove_overlay will remove all overlays on a tile.
@ -378,6 +376,7 @@ private:
display(const display&);
void operator=(const display&);
void draw_tile(const gamemap::location &loc);
void draw_sidebar();
void draw_minimap(int x, int y, int w, int h);
void draw_game_status();
@ -410,6 +409,8 @@ private:
unit_map& units_;
unit *temp_unit_;
gamemap::location temp_unit_loc_;
//function which finds the start and end rows on the energy bar image
//where white pixels are substituted for the colour of the energy

View file

@ -1016,7 +1016,8 @@ bool event_handler::handle_event_command(const queued_event& event_info,
unit_map::iterator u = units->find(loc);
if(u != units->end()) {
u->second.set_hidden(true);
screen->draw_tile(loc.x,loc.y);
screen->invalidate(loc);
screen->draw();
}
}
@ -1026,7 +1027,8 @@ bool event_handler::handle_event_command(const queued_event& event_info,
// unhide all for backward compatibility
for(u = units->begin(); u != units->end() ; u++) {
u->second.set_hidden(false);
screen->draw_tile(loc.x,loc.y);
screen->invalidate(loc);
screen->draw();
}
}
@ -1037,7 +1039,8 @@ bool event_handler::handle_event_command(const queued_event& event_info,
const std::string& halo = cfg["halo"];
if(!img.empty() || !halo.empty()) {
screen->add_overlay(loc,img,cfg["halo"]);
screen->draw_tile(loc.x,loc.y);
screen->invalidate(loc);
screen->draw();
}
}
@ -1119,8 +1122,8 @@ bool event_handler::handle_event_command(const queued_event& event_info,
un->second.set_hidden(false);
un->second.set_recruited(*screen);
while(!un->second.get_animation()->animation_finished()) {
screen->draw_tile(loc.x,loc.y);
screen->update_display();
screen->invalidate(loc);
screen->draw();
events::pump();
if(!screen->turbo()) SDL_Delay(10);
@ -1662,15 +1665,15 @@ bool event_handler::handle_event_command(const queued_event& event_info,
u->second.set_extra_anim(*screen,cfg["flag"]);
while(!u->second.get_animation()->animation_finished()) {
screen->draw_tile(u->first.x,u->first.y);
screen->update_display();
screen->invalidate(u->first);
screen->draw();
events::pump();
if(!screen->turbo()) SDL_Delay(10);
}
u->second.set_standing(*screen);
screen->draw_tile(u->first.x,u->first.y);
screen->update_display();
screen->invalidate(u->first);
screen->draw();
events::pump();
}
} else if(cmd == "label") {

View file

@ -748,7 +748,8 @@ namespace events{
std::vector<unit>& recall_list = player->available_units;
recall_list.insert(recall_list.begin()+action.recall_pos,un);
units_.erase(action.recall_loc);
gui_->draw_tile(action.recall_loc.x,action.recall_loc.y);
gui_->invalidate(action.recall_loc);
gui_->draw();
}
} else {
// Undo a move action
@ -783,8 +784,8 @@ namespace events{
units_.erase(u);
un.set_movement(starting_moves);
units_.insert(std::pair<gamemap::location,unit>(route.back(),un));
gui_->draw_tile(route.back().x,route.back().y);
gui_->update_display();
gui_->invalidate(route.back());
gui_->draw();
}
gui_->invalidate_unit();
@ -837,7 +838,8 @@ namespace events{
teams_[team_num - 1].spend_gold(game_config::recall_cost);
recall_list.erase(recall_list.begin()+action.recall_pos);
gui_->draw_tile(action.recall_loc.x,action.recall_loc.y);
gui_->invalidate(action.recall_loc);
gui_->draw();
} else {
recorder.undo();
gui::show_dialog(*gui_,NULL,"",msg,gui::OK_ONLY);
@ -875,7 +877,8 @@ namespace events{
}
}
gui_->draw_tile(route.back().x,route.back().y);
gui_->invalidate(route.back());
gui_->draw();
recorder.add_movement(route.front(),route.back());
}
@ -1170,7 +1173,7 @@ namespace events{
const unit_map::iterator un = units_.find(mousehandler.get_selected_hex());
if(un != units_.end() && un->second.side() == team_num && un->second.movement_left() >= 0) {
un->second.set_hold_position(!un->second.hold_position());
gui_->draw_tile(mousehandler.get_selected_hex().x, mousehandler.get_selected_hex().y);
gui_->invalidate(mousehandler.get_selected_hex());
mousehandler.set_current_paths(paths());
gui_->draw();
@ -1190,7 +1193,7 @@ namespace events{
if(un->second.hold_position() && !un->second.user_end_turn()){
un->second.set_hold_position(false);
}
gui_->draw_tile(mousehandler.get_selected_hex().x, mousehandler.get_selected_hex().y);
gui_->invalidate(mousehandler.get_selected_hex());
mousehandler.set_current_paths(paths());
gui_->draw();

View file

@ -854,8 +854,8 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
}
if(!replayer.is_skipping()) {
disp.draw_tile(dst.x,dst.y);
disp.update_display();
disp.invalidate(dst);
disp.draw();
}
game_events::fire("moveto",dst);

View file

@ -45,8 +45,9 @@ void teleport_unit_between(display& disp, const gamemap& map, const gamemap::loc
if (!disp.fogged(a.x, a.y)) { // teleport
disp.scroll_to_tile(a.x,a.y,display::ONSCREEN);
while(!u.get_animation()->animation_finished() && u.get_animation()->get_animation_time() < 0) {
disp.draw_tile(a.x,a.y);
disp.update_display();
disp.invalidate(a);
disp.place_temporary_unit(u, a);
disp.draw();
events::pump();
if(!disp.turbo()) SDL_Delay(10);
@ -56,13 +57,15 @@ void teleport_unit_between(display& disp, const gamemap& map, const gamemap::loc
u.restart_animation(disp,0);
disp.scroll_to_tile(b.x,b.y,display::ONSCREEN);
while(!u.get_animation()->animation_finished()) {
disp.draw_tile(b.x,b.y);
disp.update_display();
disp.invalidate(b);
disp.place_temporary_unit(u, b);
disp.draw();
events::pump();
if(!disp.turbo()) SDL_Delay(10);
}
}
u.set_standing(disp);
disp.remove_temporary_unit();
disp.update_display();
events::pump();
}
@ -93,15 +96,16 @@ void move_unit_between(display& disp, const gamemap& map, const gamemap::locatio
while(mvt_time < total_mvt_time) {
u.set_walking(disp,map.underlying_mvt_terrain(src_terrain));
const double pos =double(mvt_time)/total_mvt_time;
disp.draw_tile(a.x,a.y);
disp.invalidate(a);
disp.place_temporary_unit(u,a);
u.set_offset(pos);
u.refresh_unit(disp,a);
disp.update_display();
disp.draw();
events::pump();
if(!disp.turbo()) SDL_Delay(10);
mvt_time = SDL_GetTicks() -start_time;
}
disp.remove_temporary_unit();
}
}
@ -149,14 +153,15 @@ void move_unit(display& disp, const gamemap& map, const std::vector<gamemap::loc
}
previous_visible = true;
} else if(previous_visible) {
disp.draw_tile(path[i].x,path[i].y);
disp.invalidate(path[i]);
disp.draw();
}
}
u.set_standing(disp);
//make sure the entire path is cleaned properly
for(std::vector<gamemap::location>::const_iterator it = path.begin(); it != path.end(); ++it) {
disp.draw_tile(it->x,it->y);
disp.invalidate(*it);
}
}
@ -175,8 +180,8 @@ void unit_die(display& disp, const gamemap &map,const gamemap::location& loc, un
while(!u.get_animation()->animation_finished()) {
disp.draw_tile(loc.x,loc.y);
disp.update_display();
disp.invalidate(loc);
disp.draw();
events::pump();
if(!disp.turbo()) SDL_Delay(10);
}
@ -234,9 +239,9 @@ bool unit_attack_ranged(display& disp,const gamemap& map, unit_map& units,
leader->second.set_leading(disp);
}
while(!attacker.get_animation()->animation_finished() ) {
disp.draw_tile(a.x,a.y);
if(leader_loc.valid()) disp.draw_tile(leader_loc.x,leader_loc.y);
disp.update_display();
disp.invalidate(a);
if(leader_loc.valid()) disp.invalidate(leader_loc);
disp.draw();
events::pump();
if(!disp.turbo()) SDL_Delay(10);
}
@ -263,9 +268,9 @@ bool unit_attack_ranged(display& disp,const gamemap& map, unit_map& units,
double(animation_time)/double(missile_animation.get_first_frame_time());
const int posx = int(pos*xsrc + (1.0-pos)*xdst);
const int posy = int(pos*ysrc + (1.0-pos)*ydst);
disp.draw_tile(b.x,b.y);
disp.draw_tile(a.x,a.y);
if(leader_loc.valid()) disp.draw_tile(leader_loc.x,leader_loc.y);
disp.invalidate(b);
disp.invalidate(a);
if(leader_loc.valid()) disp.invalidate(leader_loc);
halo::remove(missile_halo);
missile_halo = 0;
if(pos > 0.0 && pos < 1.0 && (!disp.fogged(b.x,b.y) || !disp.fogged(a.x,a.y))) {
@ -313,7 +318,7 @@ bool unit_attack_ranged(display& disp,const gamemap& map, unit_map& units,
sound::play_sound(def->second.get_hit_sound());
disp.float_label(b,lexical_cast<std::string>(damage),255,0,0);
}
disp.update_display();
disp.draw();
events::pump();
if(!disp.turbo()) SDL_Delay(10);
animation_time = defender.get_animation()->get_animation_time();
@ -413,10 +418,10 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
const double pos = animation_time < attacker.get_animation()->get_first_frame_time()?0.0:
(1.0 - double(animation_time)/double(attacker.get_animation()->get_first_frame_time()));
attacker.set_offset(pos*0.6);
disp.draw_tile(b.x,b.y);
disp.draw_tile(a.x,a.y);
if(leader_loc.valid()) disp.draw_tile(leader_loc.x,leader_loc.y);
disp.update_display();
disp.invalidate(b);
disp.invalidate(a);
if(leader_loc.valid()) disp.invalidate(leader_loc);
disp.draw();
events::pump();
if(!disp.turbo()) SDL_Delay(10);
@ -434,10 +439,10 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
(leader_loc.valid() && !leader->second.get_animation()->animation_finished() )) {
const double pos = (1.0-double(animation_time)/double(end_time));
attacker.set_offset(pos*0.6);
disp.draw_tile(b.x,b.y);
disp.draw_tile(a.x,a.y);
if(leader_loc.valid()) disp.draw_tile(leader_loc.x,leader_loc.y);
disp.update_display();
disp.invalidate(b);
disp.invalidate(a);
if(leader_loc.valid()) disp.invalidate(leader_loc);
disp.draw();
events::pump();
if(!disp.turbo()) SDL_Delay(10);