better animation filtering criterias

This commit is contained in:
Jérémy Rosen 2006-05-08 09:11:58 +00:00
parent f53ce2d54d
commit ebe9c01ab2
10 changed files with 205 additions and 189 deletions

View file

@ -76,6 +76,7 @@ SVN trunk (1.1.2+svn):
* floating damage/heal or status can be printed over a modified unit using
the 'text', 'red', 'blue', and 'green' keys in [unstore_unit]
* store_locations now stores terrain as well as x,y
* more filtering criterias for animations
* multiplayer settings:
* two additional MP timer settings, time reservoir limit and action bonus:
* Reservoir prevents the turn timer from exceeding an upper limit.

View file

@ -159,7 +159,7 @@ std::string recruit_unit(const gamemap& map, int side,
un->second.set_hidden(true);
disp->scroll_to_tile(recruit_location.x,recruit_location.y,display::ONSCREEN);
un->second.set_hidden(false);
un->second.set_recruited(*disp);
un->second.set_recruited(*disp,recruit_location);
while(!un->second.get_animation()->animation_finished()) {
disp->invalidate(recruit_location);
disp->draw();
@ -167,7 +167,7 @@ std::string recruit_unit(const gamemap& map, int side,
if(!disp->turbo()) SDL_Delay(10);
}
un->second.set_standing(*disp);
un->second.set_standing(*disp,recruit_location);
}
}
LOG_NG << "firing recruit event\n";
@ -1781,7 +1781,7 @@ void calculate_healing(display& disp, const gamemap& map,
disp.select_hex(i->first);
for(std::vector<unit_map::iterator>::iterator heal_anim_it = healers.begin(); heal_anim_it != healers.end(); ++heal_anim_it) {
(*heal_anim_it)->second.set_healing(disp);
(*heal_anim_it)->second.set_healing(disp,(*heal_anim_it)->first);
if(start_time_set) {
start_time = minimum<int>(start_time,(*heal_anim_it)->second.get_animation()->get_first_frame_time());
} else {
@ -1789,13 +1789,13 @@ void calculate_healing(display& disp, const gamemap& map,
}
}
if (healing < 0) {
i->second.set_poisoned(disp, -healing);
i->second.set_poisoned(disp,i->first, -healing);
start_time = minimum<int>(start_time, i->second.get_animation()->get_first_frame_time());
// FIXME
sound::play_sound("groan.wav");
disp.float_label(i->first, lexical_cast<std::string>(-healing), 255,0,0);
} else {
i->second.set_healed(disp, healing);
i->second.set_healed(disp,i->first, healing);
start_time = minimum<int>(start_time, i->second.get_animation()->get_first_frame_time());
sound::play_sound("heal.wav");
disp.float_label(i->first, lexical_cast<std::string>(healing), 0,255,0);
@ -1827,9 +1827,9 @@ void calculate_healing(display& disp, const gamemap& map,
SDL_Delay(10);
} while (!finished);
i->second.set_standing(disp);
i->second.set_standing(disp,i->first);
for(std::vector<unit_map::iterator>::iterator heal_sanim_it = healers.begin(); heal_sanim_it != healers.end(); ++heal_sanim_it) {
(*heal_sanim_it)->second.set_standing(disp);
(*heal_sanim_it)->second.set_standing(disp,(*heal_sanim_it)->first);
}
disp.update_display();
events::pump();

View file

@ -133,7 +133,7 @@ bool animate_unit_advancement(const game_data& info,unit_map& units, gamemap::lo
//new unit, then fades back to the normal colour
if(!gui.update_locked()) {
u->second.set_leveling_out(gui);
u->second.set_leveling_out(gui,u->first);
while(!u->second.get_animation()->animation_finished()) {
gui.invalidate(loc);
gui.draw();
@ -156,14 +156,14 @@ bool animate_unit_advancement(const game_data& info,unit_map& units, gamemap::lo
gui.invalidate_unit();
if(!gui.update_locked()) {
u->second.set_leveling_in(gui);
u->second.set_leveling_in(gui,u->first);
while(!u->second.get_animation()->animation_finished()) {
gui.invalidate(loc);
gui.draw();
events::pump();
if(!gui.turbo()) SDL_Delay(10);
}
u->second.set_standing(gui);
u->second.set_standing(gui,u->first);
gui.invalidate(loc);
gui.draw();
events::pump();

View file

@ -195,7 +195,7 @@ public:
void float_label(const gamemap::location& loc, const std::string& text,
int red, int green, int blue);
const gamemap& get_map() { return map_;}
const gamemap& get_map()const { return map_;}
private:
enum ADJACENT_TERRAIN_TYPE { ADJACENT_BACKGROUND, ADJACENT_FOREGROUND, ADJACENT_FOGSHROUD };

View file

@ -1123,7 +1123,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
un->second.set_hidden(true);
screen->scroll_to_tile(loc.x,loc.y,display::ONSCREEN);
un->second.set_hidden(false);
un->second.set_recruited(*screen);
un->second.set_recruited(*screen,un->first);
while(!un->second.get_animation()->animation_finished()) {
screen->invalidate(loc);
screen->draw();
@ -1131,7 +1131,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
if(!screen->turbo()) SDL_Delay(10);
}
un->second.set_standing(*screen);
un->second.set_standing(*screen,un->first);
}
} else {
player_info* const player = state_of_game->get_player((*teams)[new_unit.side()-1].save_id());
@ -1666,7 +1666,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
screen->highlight_hex(u->first);
screen->scroll_to_tile(u->first.x,u->first.y);
u->second.set_extra_anim(*screen,cfg["flag"]);
u->second.set_extra_anim(*screen,u->first,cfg["flag"]);
while(!u->second.get_animation()->animation_finished()) {
screen->invalidate(u->first);
screen->draw();
@ -1674,7 +1674,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
if(!screen->turbo()) SDL_Delay(10);
}
u->second.set_standing(*screen);
u->second.set_standing(*screen,u->first);
screen->invalidate(u->first);
screen->draw();
events::pump();

View file

@ -1229,7 +1229,7 @@ const surface unit::still_image() const
surface unit_image(image::get_image(loc,image::UNSCALED));
return unit_image;
}
void unit::set_standing(const display &disp)
void unit::set_standing(const display &disp,const gamemap::location& loc)
{
state_ = STATE_STANDING;
draw_bars_ = true;
@ -1243,7 +1243,7 @@ void unit::set_standing(const display &disp)
frame_begin_time = anim_->get_first_frame_time() -1;
anim_->update_current_frame();
}
void unit::set_defending(const display &disp, int damage, std::string range)
void unit::set_defending(const display &disp,const gamemap::location& loc, int damage,const attack_type* attack)
{
state_ = STATE_DEFENDING;
draw_bars_ = true;
@ -1251,7 +1251,15 @@ void unit::set_defending(const display &disp, int damage, std::string range)
delete anim_;
anim_ = NULL;
}
anim_ = new defensive_animation(defend_animation(damage > 0?true:false,range));
fighting_animation::hit_type hit_type;
if(damage >= hitpoints()) {
hit_type = fighting_animation::KILL;
} else if(damage > 0) {
hit_type = fighting_animation::HIT;
}else {
hit_type = fighting_animation::MISS;
}
anim_ = new defensive_animation(defend_animation(disp.get_map().underlying_union_terrain(loc),hit_type,attack));
// add a blink on damage effect
int anim_time = anim_->get_last_frame_time();
@ -1270,7 +1278,7 @@ void unit::set_defending(const display &disp, int damage, std::string range)
anim_->update_current_frame();
}
void unit::set_extra_anim(const display &disp, std::string flag)
void unit::set_extra_anim(const display &disp,const gamemap::location& loc, std::string flag)
{
state_ = STATE_EXTRA;
draw_bars_ = false;
@ -1278,17 +1286,17 @@ void unit::set_extra_anim(const display &disp, std::string flag)
delete anim_;
anim_ = NULL;
}
if(!extra_animation(flag)) {
set_standing(disp);
if(!extra_animation(disp.get_map().underlying_union_terrain(loc),flag)) {
set_standing(disp,loc);
return;
}
anim_ = new unit_animation(*(extra_animation(flag)));
anim_ = new unit_animation(*(extra_animation(disp.get_map().underlying_union_terrain(loc),flag)));
anim_->start_animation(anim_->get_first_frame_time(),1,disp.turbo()?5:1);
frame_begin_time = anim_->get_first_frame_time() -1;
anim_->update_current_frame();
}
const unit_animation & unit::set_attacking(const display &disp,bool hit,const attack_type& type)
const unit_animation & unit::set_attacking(const display &disp,const gamemap::location& loc,bool hit,const attack_type& type)
{
state_ = STATE_ATTACKING;
draw_bars_ = false;
@ -1303,7 +1311,7 @@ const unit_animation & unit::set_attacking(const display &disp,bool hit,const at
anim_->update_current_frame();
return attack_anim.missile_animation;
}
void unit::set_leading(const display &disp)
void unit::set_leading(const display &disp,const gamemap::location& loc)
{
state_ = STATE_LEADING;
draw_bars_ = false;
@ -1316,7 +1324,7 @@ void unit::set_leading(const display &disp)
frame_begin_time = anim_->get_first_frame_time() -1;
anim_->update_current_frame();
}
void unit::set_leveling_in(const display &disp)
void unit::set_leveling_in(const display &disp,const gamemap::location& loc)
{
state_ = STATE_LEVELIN;
draw_bars_ = false;
@ -1340,7 +1348,7 @@ void unit::set_leveling_in(const display &disp)
frame_begin_time = anim_->get_first_frame_time() -1;
anim_->update_current_frame();
}
void unit::set_leveling_out(const display &disp)
void unit::set_leveling_out(const display &disp,const gamemap::location& loc)
{
state_ = STATE_LEVELOUT;
draw_bars_ = false;
@ -1364,7 +1372,7 @@ void unit::set_leveling_out(const display &disp)
frame_begin_time = anim_->get_first_frame_time() -1;
anim_->update_current_frame();
}
void unit::set_recruited(const display &disp)
void unit::set_recruited(const display &disp,const gamemap::location& loc)
{
state_ = STATE_RECRUITED;
draw_bars_ = false;
@ -1385,7 +1393,7 @@ void unit::set_recruited(const display &disp)
frame_begin_time = anim_->get_first_frame_time() -1;
anim_->update_current_frame();
}
void unit::set_healed(const display &disp, int healing)
void unit::set_healed(const display &disp,const gamemap::location& loc, int healing)
{
state_ = STATE_HEALED;
draw_bars_ = true;
@ -1410,7 +1418,7 @@ void unit::set_healed(const display &disp, int healing)
frame_begin_time = anim_->get_first_frame_time() -1;
anim_->update_current_frame();
}
void unit::set_poisoned(const display &disp, int damage)
void unit::set_poisoned(const display &disp,const gamemap::location& loc, int damage)
{
state_ = STATE_POISONED;
draw_bars_ = true;
@ -1436,7 +1444,7 @@ void unit::set_poisoned(const display &disp, int damage)
anim_->update_current_frame();
}
void unit::set_teleporting(const display &disp)
void unit::set_teleporting(const display &disp,const gamemap::location& loc)
{
state_ = STATE_TELEPORT;
draw_bars_ = false;
@ -1450,7 +1458,7 @@ void unit::set_teleporting(const display &disp)
anim_->update_current_frame();
}
void unit::set_dying(const display &disp, const attack_type* attack)
void unit::set_dying(const display &disp,const gamemap::location& loc,const attack_type* attack)
{
state_ = STATE_DYING;
draw_bars_ = false;
@ -1458,7 +1466,7 @@ void unit::set_dying(const display &disp, const attack_type* attack)
delete anim_;
anim_ = NULL;
}
anim_ = new death_animation(die_animation(attack));
anim_ = new death_animation(die_animation(disp.get_map().underlying_union_terrain(loc),fighting_animation::KILL,attack));
double blend_ratio = 1.0;
std::string tmp_image = anim_->get_last_frame().image;
int anim_time =anim_->get_last_frame_time();
@ -1471,7 +1479,7 @@ void unit::set_dying(const display &disp, const attack_type* attack)
frame_begin_time = anim_->get_first_frame_time() -1;
anim_->update_current_frame();
}
void unit::set_healing(const display &disp)
void unit::set_healing(const display &disp,const gamemap::location& loc)
{
state_ = STATE_HEALING;
draw_bars_ = true;
@ -1492,10 +1500,10 @@ void unit::set_healing(const display &disp)
anim_->update_current_frame();
}
void unit::set_walking(const display &disp, const std::string terrain)
void unit::set_walking(const display &disp,const gamemap::location& loc)
{
movement_animation* const anim = dynamic_cast<movement_animation*>(anim_);
if(state_ == STATE_WALKING && anim != NULL && anim->matches(terrain,facing_) >=0) {
if(state_ == STATE_WALKING && anim != NULL && anim->matches(disp.get_map().underlying_union_terrain(loc),facing_) >=0) {
return; // finish current animation, don't start a new one
}
state_ = STATE_WALKING;
@ -1504,7 +1512,7 @@ void unit::set_walking(const display &disp, const std::string terrain)
delete anim_;
anim_ = NULL;
}
anim_ = new movement_animation(move_animation(terrain,facing_));
anim_ = new movement_animation(move_animation(disp.get_map().underlying_union_terrain(loc),facing_));
anim_->start_animation(anim_->get_first_frame_time(),1,disp.turbo()?5:1);
frame_begin_time = anim_->get_first_frame_time() -1;
}
@ -1544,7 +1552,7 @@ void unit::redraw_unit(display& disp,gamemap::location hex)
const int x = int(offset_*xdst + (1.0-offset_)*xsrc);
const int y = int(offset_*ydst + (1.0-offset_)*ysrc);
if(!anim_) set_standing(disp);
if(!anim_) set_standing(disp,hex);
const gamemap::TERRAIN terrain = map.get_terrain(hex);
const double submerge = is_flying() ? 0.0 : map.get_terrain_info(terrain).unit_submerge() * disp.zoom();
const int height_adjust = is_flying() ? 0 : int(map.get_terrain_info(terrain).unit_height_adjust() * disp.zoom());
@ -2362,13 +2370,14 @@ const std::string& unit::race() const
return race_->name();
}
const defensive_animation& unit::defend_animation(bool hits, std::string range) const
const defensive_animation& unit::defend_animation(const std::string &terrain,
fighting_animation::hit_type hits, const attack_type* attack) const
{
//select one of the matching animations at random
std::vector<const defensive_animation*> options;
int max_val = -1;
for(std::vector<defensive_animation>::const_iterator i = defensive_animations_.begin(); i != defensive_animations_.end(); ++i) {
int matching = i->matches(hits,range);
int matching = i->matches(terrain,facing_,hits,attack);
if(matching == max_val) {
options.push_back(&*i);
} else if(matching > max_val) {
@ -2385,23 +2394,34 @@ const unit_animation& unit::teleport_animation() const
{
return teleport_animations_[rand() % teleport_animations_.size()];
}
const unit_animation* unit::extra_animation(std::string flag) const
const unit_animation* unit::extra_animation(const std::string &terrain,const std::string &flag) const
{
if (extra_animations_.count(flag) == 0) return NULL;
std::multimap<std::string,unit_animation>::const_iterator index = extra_animations_.lower_bound(flag);
int i = (rand()% extra_animations_.count(flag));
for(int j = 0 ; j < i ; j++) {
index++;
//select one of the matching animations at random
std::vector<const unit_animation*> options;
int max_val = -1;
std::multimap<std::string,unit_animation>::const_iterator i;
for(i = extra_animations_.lower_bound(flag); i != extra_animations_.upper_bound(flag); ++i) {
int matching = i->second.matches(terrain,facing_);
if(matching == max_val) {
options.push_back(&i->second);
} else if(matching > max_val) {
max_val = matching;
options.erase(options.begin(),options.end());
options.push_back(&i->second);
}
}
return &index->second;
if(extra_animations_.lower_bound(flag) == extra_animations_.end()) { return NULL;}
return options[rand()%options.size()];
}
const death_animation& unit::die_animation(const attack_type* attack) const
const death_animation& unit::die_animation(const std::string &terrain,
fighting_animation::hit_type hits,const attack_type* attack) const
{
//select one of the matching animations at random
std::vector<const death_animation*> options;
int max_val = -1;
for(std::vector<death_animation>::const_iterator i = death_animations_.begin(); i != death_animations_.end(); ++i) {
int matching = i->matches(attack);
int matching = i->matches(terrain,facing_,hits,attack);
if(matching == max_val) {
options.push_back(&*i);
} else if(matching > max_val) {

View file

@ -160,20 +160,20 @@ class unit
const surface still_image() const;
void redraw_unit(display& disp,gamemap::location hex);
void set_standing(const display& disp);
void set_defending(const display& disp, int damage, std::string range);
void set_leading(const display& disp);
void set_healing(const display& disp);
void set_leveling_in(const display& disp);
void set_leveling_out(const display& disp);
void set_teleporting (const display& disp);
void set_extra_anim(const display& disp, std::string flag);
void set_dying( const display& disp,const attack_type *attack);
void set_walking(const display& disp,const std::string terrain);
const unit_animation & set_attacking(const display& disp,bool hit,const attack_type& type);
void set_recruited(const display& disp);
void set_healed(const display& disp,int healing);
void set_poisoned(const display& disp,int damage);
void set_standing(const display& disp,const gamemap::location& loc);
void set_defending(const display &disp,const gamemap::location& loc, int damage,const attack_type* attack);
void set_leading(const display& disp,const gamemap::location& loc);
void set_healing(const display& disp,const gamemap::location& loc);
void set_leveling_in(const display& disp,const gamemap::location& loc);
void set_leveling_out(const display& disp,const gamemap::location& loc);
void set_teleporting (const display& disp,const gamemap::location& loc);
void set_extra_anim(const display& disp,const gamemap::location& loc, std::string flag);
void set_dying(const display &disp,const gamemap::location& loc,const attack_type* attack);
void set_walking(const display& disp,const gamemap::location& loc);
const unit_animation & set_attacking(const display& disp,const gamemap::location& loc,bool hit,const attack_type& type);
void set_recruited(const display& disp,const gamemap::location& loc);
void set_healed(const display& disp,const gamemap::location& loc,int healing);
void set_poisoned(const display& disp,const gamemap::location& loc,int damage);
void restart_animation(const display& disp,int start_time);
const unit_animation* get_animation() const { return anim_;};
void set_offset(double offset){offset_ = offset;}
@ -239,10 +239,12 @@ class unit
unit_type::ALIGNMENT alignment() const;
const std::string& race() const;
const defensive_animation& defend_animation(bool hits, std::string range) const;
const defensive_animation& defend_animation(const std::string &terrain,
fighting_animation::hit_type hits,const attack_type* attack) const;
const unit_animation& teleport_animation() const;
const unit_animation* extra_animation(std::string flag) const;
const death_animation& die_animation(const attack_type* attack) const;
const unit_animation* extra_animation(const std::string &terrain,const std::string &flag) const;
const death_animation& die_animation(const std::string &terrain,
fighting_animation::hit_type hits,const attack_type* attack) const;
const movement_animation& move_animation(const std::string terrain,gamemap::location::DIRECTION) const;
bool get_ability_bool(const std::string& ability, const gamemap::location& loc) const;

View file

@ -69,8 +69,8 @@ unit_animation::unit_animation(const std::string image )
{
add_frame(0,unit_frame(image));
}
unit_animation::unit_animation(const config& cfg,const std::string frame_string )
{
unit_animation::unit_animation(const config& cfg,const std::string frame_string ):terrain_types(utils::split(cfg["terrain"])){
config::const_child_itors range = cfg.child_range(frame_string);
int last_end = INT_MIN;
@ -80,6 +80,12 @@ unit_animation::unit_animation(const config& cfg,const std::string frame_string
}
add_frame(last_end);
const std::vector<std::string>& my_directions = utils::split(cfg["direction"]);
for(std::vector<std::string>::const_iterator i = my_directions.begin(); i != my_directions.end(); ++i) {
const gamemap::location::DIRECTION d = gamemap::location::parse_direction(*i);
directions.push_back(d);
}
/* warn on deprecated WML */
if(cfg.child("sound")) {
LOG_STREAM(err, config) << "an animation uses the deprecated [sound] tag, please include sound in the [frame] tag\n";
@ -93,29 +99,19 @@ unit_animation::unit_animation(const std::string image, int begin_at, int end_at
add_frame(end_at);
}
defensive_animation::defensive_animation(const config& cfg) :unit_animation(cfg), hits(HIT_OR_MISS), range(utils::split(cfg["range"]))
{
const std::string& hits_str = cfg["hits"];
if(hits_str.empty() == false) {
hits = (hits_str == "yes") ? HIT : MISS;
}
}
int defensive_animation::matches(bool h, std::string r) const
int unit_animation::matches(const std::string &terrain,const gamemap::location::DIRECTION dir) const
{
int result = 0;
if(hits != HIT_OR_MISS ) {
if(h && (hits == HIT)) {
result++;
} else if(!h && (hits == MISS)) {
result++;
} else {
if(terrain_types.empty()== false) {
if (std::find(terrain_types.begin(),terrain_types.end(),terrain)== terrain_types.end()) {
return -1;
} else {
result ++;
}
}
if(range.empty()== false) {
if (std::find(range.begin(),range.end(),r)== range.end()) {
if(directions.empty()== false) {
if (std::find(directions.begin(),directions.end(),dir)== directions.end()) {
return -1;
} else {
result ++;
@ -125,20 +121,48 @@ int defensive_animation::matches(bool h, std::string r) const
return result;
}
death_animation::death_animation(const config& cfg):unit_animation(cfg),
damage_type(utils::split(cfg["damage_type"])), special(utils::split(cfg["attack_special"]))
fighting_animation::fighting_animation(const config& cfg) :unit_animation(cfg), range(utils::split(cfg["range"])),
damage_type(utils::split(cfg["damage_type"])), special(utils::split(cfg["attack_special"]))
{
std::vector<std::string> hits_str = utils::split(cfg["hits"]);
std::vector<std::string>::iterator hit;
for(hit=hits_str.begin() ; hit != hits_str.end() ; hit++) {
if(*hit == "yes" || *hit == "hit") {
hits.push_back(HIT);
}
if(*hit == "no" || *hit == "miss") {
hits.push_back(MISS);
}
if(*hit == "kill" ) {
hits.push_back(KILL);
}
}
}
int death_animation::matches(const attack_type* attack) const
int fighting_animation::matches(const std::string &terrain,gamemap::location::DIRECTION dir,hit_type hit,const attack_type* attack) const
{
int result = 0;
if(attack == NULL) {
int result = unit_animation::matches(terrain,dir);
if(!attack) {
if(damage_type.empty() && special.empty())
return 0;
return result;
else
return -1;
}
if(hits.empty() == false ) {
if (std::find(hits.begin(),hits.end(),hit)== hits.end()) {
return -1;
} else {
result ++;
}
}
if(range.empty()== false) {
if (std::find(range.begin(),range.end(),attack->range())== range.end()) {
return -1;
} else {
result ++;
}
}
if(damage_type.empty()== false) {
if (std::find(damage_type.begin(),damage_type.end(),attack->type())== damage_type.end()) {
@ -161,45 +185,7 @@ int death_animation::matches(const attack_type* attack) const
return -1;
}
}
return result;
}
movement_animation::movement_animation(const config& cfg)
:unit_animation(cfg), terrain_types(utils::split(cfg["terrain"]))
{
const std::vector<std::string>& my_directions = utils::split(cfg["direction"]);
for(std::vector<std::string>::const_iterator i = my_directions.begin(); i != my_directions.end(); ++i) {
const gamemap::location::DIRECTION d = gamemap::location::parse_direction(*i);
directions.push_back(d);
}
}
movement_animation::movement_animation(const std::string& image,const std::string& terrain,gamemap::location::DIRECTION dir):unit_animation(image,0,150),terrain_types(utils::split(terrain))
{
if(dir !=gamemap::location::NDIRECTIONS) {
directions.push_back(dir);
}
}
int movement_animation::matches(const std::string &terrain,gamemap::location::DIRECTION dir) const
{
int result = 0;
if(terrain_types.empty()== false) {
if (std::find(terrain_types.begin(),terrain_types.end(),terrain)== terrain_types.end()) {
return -1;
} else {
result ++;
}
}
if(directions.empty()== false) {
if (std::find(directions.begin(),directions.end(),dir)== directions.end()) {
return -1;
} else {
result ++;
}
}
return result;
}

View file

@ -30,54 +30,63 @@ class unit_animation:public animated<unit_frame>
unit_animation(){};
explicit unit_animation(const config& cfg,const std::string frame_string ="frame");
explicit unit_animation(const std::string image, int begin_at, int end_at, const std::string image_diagonal = "",const std::string halo="",int halo_x=0,int halo_y=0);
explicit unit_animation(const std::string image, int begin_at, int end_at,
const std::string image_diagonal = "",const std::string halo="",int halo_x=0,int halo_y=0);
explicit unit_animation(const std::string image);
int matches(const std::string &terrain,const gamemap::location::DIRECTION dir) const;
enum FRAME_DIRECTION { VERTICAL, DIAGONAL };
private:
};
class defensive_animation:public unit_animation
{
public:
typedef enum { HIT, MISS, HIT_OR_MISS } hit_type;
explicit defensive_animation(const config& cfg);
explicit defensive_animation(const std::string &image, const std::string &range="",const hit_type for_hit= HIT_OR_MISS): unit_animation(image,-150,150),hits(for_hit),range(utils::split(range)) {};
int matches(bool hits, std::string range) const;
private:
hit_type hits;
std::vector<std::string> range;
};
class attack_type;
class death_animation:public unit_animation
{
public:
explicit death_animation(const config& cfg);
explicit death_animation(const std::string &image):unit_animation(image,0,10) {};
int matches(const attack_type* attack) const;
private:
std::vector<std::string> damage_type, special;
};
class movement_animation:public unit_animation
{
public:
explicit movement_animation(const config& cfg);
explicit movement_animation(const std::string& image,const std::string& terrain="",gamemap::location::DIRECTION dir=gamemap::location::NDIRECTIONS);
int matches(const std::string &terrain,gamemap::location::DIRECTION dir=gamemap::location::NDIRECTIONS) const;
private:
std::vector<std::string> terrain_types;
std::vector<gamemap::location::DIRECTION> directions;
};
class attack_type;
class fighting_animation:public unit_animation
{
public:
typedef enum { HIT, MISS, KILL} hit_type;
explicit fighting_animation(const config& cfg);
explicit fighting_animation(const std::string &image, const std::string &range="",int begin_at = -150, int end_at = 150):
unit_animation(image,begin_at,end_at),range(utils::split(range)) {};
int matches(const std::string &terrain,gamemap::location::DIRECTION dir,hit_type hit,const attack_type* attack) const;
private:
std::vector<hit_type> hits;
std::vector<std::string> range;
std::vector<std::string> damage_type, special;
};
class defensive_animation:public fighting_animation
{
public:
explicit defensive_animation(const config& cfg):fighting_animation(cfg){};
explicit defensive_animation(const std::string &image, const std::string &range="",int begin_at = -150, int end_at = 150):fighting_animation(image,range,begin_at,end_at){};
};
class death_animation:public fighting_animation
{
public:
explicit death_animation(const config& cfg):fighting_animation(cfg){};
explicit death_animation(const std::string &image):fighting_animation(image,"",0,10) {};
private:
};
class movement_animation:public unit_animation
{
public:
explicit movement_animation(const config& cfg):unit_animation(cfg){};
explicit movement_animation(const std::string& image):
unit_animation(image,0,150){};
private:
};
#endif

View file

@ -41,7 +41,7 @@ void teleport_unit_between(display& disp, const gamemap::location& a, const game
u.set_teleporting(disp);
u.set_teleporting(disp,a);
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) {
@ -64,7 +64,7 @@ void teleport_unit_between(display& disp, const gamemap::location& a, const game
if(!disp.turbo()) SDL_Delay(10);
}
}
u.set_standing(disp);
u.set_standing(disp,b);
disp.remove_temporary_unit();
disp.update_display();
events::pump();
@ -78,7 +78,6 @@ void move_unit_between(display& disp, const gamemap& map, const gamemap::locatio
return;
}
const gamemap::TERRAIN src_terrain = map.get_terrain(a);
const gamemap::TERRAIN dst_terrain = map.get_terrain(b);
const int acceleration = disp.turbo() ? 5:1;
@ -94,7 +93,7 @@ void move_unit_between(display& disp, const gamemap& map, const gamemap::locatio
int mvt_time = SDL_GetTicks() -start_time;
disp.scroll_to_tiles(a.x,a.y,b.x,b.y,display::ONSCREEN);
while(mvt_time < total_mvt_time) {
u.set_walking(disp,map.underlying_mvt_terrain(src_terrain));
u.set_walking(disp,a);
const double pos =double(mvt_time)/total_mvt_time;
disp.invalidate(a);
disp.place_temporary_unit(u,a);
@ -157,7 +156,7 @@ void move_unit(display& disp, const gamemap& map, const std::vector<gamemap::loc
disp.draw();
}
}
u.set_standing(disp);
u.set_standing(disp,path[path.size()-1]);
//make sure the entire path is cleaned properly
for(std::vector<gamemap::location>::const_iterator it = path.begin(); it != path.end(); ++it) {
@ -175,7 +174,7 @@ void unit_die(display& disp,const gamemap::location& loc, unit& u, const attack_
if(die_sound != "" && die_sound != "null") {
sound::play_sound(die_sound);
}
u.set_dying(disp,attack);
u.set_dying(disp,loc,attack);
while(!u.get_animation()->animation_finished()) {
@ -185,10 +184,9 @@ void unit_die(display& disp,const gamemap::location& loc, unit& u, const attack_
events::pump();
if(!disp.turbo()) SDL_Delay(10);
}
u.set_standing(disp);
u.set_standing(disp,loc);
disp.update_display();
events::pump();
}
namespace {
@ -229,14 +227,14 @@ bool unit_attack_ranged(display& disp, unit_map& units,
// start leader and attacker animation, wait for attacker animation to end
unit_animation missile_animation = attacker.set_attacking(disp,hits,attack);
unit_animation missile_animation = attacker.set_attacking(disp,a,hits,attack);
const gamemap::location leader_loc = under_leadership(units,a);
unit_map::iterator leader = units.end();
if(leader_loc.valid()){
LOG_DP << "found leader at " << leader_loc << '\n';
leader = units.find(leader_loc);
wassert(leader != units.end());
leader->second.set_leading(disp);
leader->second.set_leading(disp,leader_loc);
}
while(!attacker.get_animation()->animation_finished() ) {
disp.invalidate(a);
@ -254,7 +252,7 @@ bool unit_attack_ranged(display& disp, unit_map& units,
const bool hflip = b.x < a.x;
const unit_animation::FRAME_DIRECTION dir = (a.x == b.x) ? unit_animation::VERTICAL:unit_animation::DIAGONAL;
defender.set_defending(disp,damage,attack.range());
defender.set_defending(disp,b,damage,&attack);
const int start_time = minimum<int>(minimum<int>(defender.get_animation()->get_first_frame_time(),
missile_animation.get_first_frame_time()),-200);
missile_animation.start_animation(start_time,acceleration);
@ -331,10 +329,10 @@ bool unit_attack_ranged(display& disp, unit_map& units,
if(dead) {
unit_display::unit_die(disp,def->first,def->second,&attack);
} else {
def->second.set_standing(disp);
def->second.set_standing(disp,b);
}
if(leader_loc.valid()) leader->second.set_standing(disp);
att->second.set_standing(disp);
if(leader_loc.valid()) leader->second.set_standing(disp,leader_loc);
att->second.set_standing(disp,a);
disp.update_display();
events::pump();
@ -379,11 +377,11 @@ bool unit_attack(display& disp, unit_map& units,
int end_time = 0;
attacker.set_attacking(disp,hits,attack);
attacker.set_attacking(disp,a,hits,attack);
start_time=minimum<int>(start_time,attacker.get_animation()->get_first_frame_time());
end_time=maximum<int>(end_time,attacker.get_animation()->get_last_frame_time());
defender.set_defending(disp,damage,attack.range());
defender.set_defending(disp,b,damage,&attack);
start_time=minimum<int>(start_time,defender.get_animation()->get_first_frame_time());
end_time=maximum<int>(end_time,defender.get_animation()->get_last_frame_time());
@ -394,7 +392,7 @@ bool unit_attack(display& disp, unit_map& units,
LOG_DP << "found leader at " << leader_loc << '\n';
leader = units.find(leader_loc);
wassert(leader != units.end());
leader->second.set_leading(disp);
leader->second.set_leading(disp,leader_loc);
start_time=minimum<int>(start_time,leader->second.get_animation()->get_first_frame_time());
end_time=maximum<int>(end_time,leader->second.get_animation()->get_last_frame_time());
}
@ -453,10 +451,10 @@ bool unit_attack(display& disp, unit_map& units,
if(dead) {
unit_display::unit_die(disp,def->first,def->second,&attack);
} else {
def->second.set_standing(disp);
def->second.set_standing(disp,b);
}
if(leader_loc.valid()) leader->second.set_standing(disp);
att->second.set_standing(disp);
if(leader_loc.valid()) leader->second.set_standing(disp,leader_loc);
att->second.set_standing(disp,a);
disp.update_display();
events::pump();