added support for animated deaths

This commit is contained in:
Dave White 2005-03-22 01:14:14 +00:00
parent df5a3bf920
commit d63773ebc1
9 changed files with 101 additions and 8 deletions

View File

@ -1,4 +1,5 @@
CVS HEAD:
* Added support for animated deaths, and added animations for skeleton and revenant
* Balancing of water units: swimmer units (merfolk) have defense on water and swamp reduced by 10%. Merman Hunter cost: 13 -> 15. Melee attack: 5-2 -> 4-2. Naga have defense on shallow water reduced by 10%. Deep sea creatures have defense on water reduced by 10%. Naga Fighter cost: 13 -> 14.
* Added UNIT and PLACE_IMAGE macros to utils.cfg
* terrain improvements

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
images/undead-revenant-dying.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/undead-skeleton-dying.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -267,7 +267,7 @@ void move_unit(display& disp, const gamemap& map, const std::vector<gamemap::loc
}
}
void unit_die(display& disp, const gamemap::location& loc, const unit& u)
void unit_die(display& disp, const gamemap::location& loc, const unit& u, const attack_type* attack)
{
if(disp.update_locked() || disp.fogged(loc.x,loc.y) || preferences::show_combat() == false) {
return;
@ -278,11 +278,34 @@ void unit_die(display& disp, const gamemap::location& loc, const unit& u)
sound::play_sound(die_sound);
}
surface unit_image(NULL);
const unit_animation* const anim_ptr = u.type().die_animation(attack);
if(anim_ptr != NULL) {
unit_animation anim(*anim_ptr);
anim.start_animation(anim.get_first_frame_time(),unit_animation::UNIT_FRAME,disp.turbo() ? 5:1);
anim.update_current_frames();
while(!anim.animation_finished()) {
const unit_animation::frame& frame = anim.get_current_frame();
unit_image = surface(image::get_image(frame.image));
disp.draw_tile(loc.x,loc.y,unit_image);
disp.update_display();
SDL_Delay(10);
anim.update_current_frames();
}
}
const int frame_time = 30;
int ticks = SDL_GetTicks();
for(fixed_t alpha = ftofxp(1.0); alpha > ftofxp(0.0); alpha -= ftofxp(0.05)) {
disp.draw_tile(loc.x,loc.y,NULL,alpha);
disp.draw_tile(loc.x,loc.y,unit_image,alpha);
const int wait_time = ticks + frame_time - SDL_GetTicks();
@ -294,7 +317,7 @@ void unit_die(display& disp, const gamemap::location& loc, const unit& u)
disp.update_display();
}
disp.draw_tile(loc.x,loc.y,NULL,ftofxp(0.0));
disp.draw_tile(loc.x,loc.y,unit_image,ftofxp(0.0));
disp.update_display();
}
@ -591,7 +614,7 @@ bool unit_attack_ranged(display& disp, unit_map& units,
}
if(dead) {
unit_die(disp,def->first,def->second);
unit_die(disp,def->first,def->second,&attack);
}
return dead;
@ -853,7 +876,7 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
def->second.set_standing();
if(dead) {
unit_display::unit_die(disp,def->first,def->second);
unit_display::unit_die(disp,def->first,def->second,&attack);
}
return dead;

View File

@ -17,7 +17,7 @@ void move_unit(display& disp, const gamemap& map, const std::vector<gamemap::loc
///a function to show a unit fading out. Note that this only shows the effect, it doesn't
///actually kill the unit.
void unit_die(display& disp, const gamemap::location& loc, const unit& u);
void unit_die(display& disp, const gamemap::location& loc, const unit& u, const attack_type* attack=NULL);
///a function to make the unit on tile 'a' attack the unit on tile 'b'.
///the 'damage' will be subtracted from the unit's hitpoints, and a die effect will be

View File

@ -531,7 +531,7 @@ unit_type::unit_type(const unit_type& o)
can_advance_(o.can_advance_), alignment_(o.alignment_),
movementType_(o.movementType_), possibleTraits_(o.possibleTraits_),
genders_(o.genders_), defensive_animations_(o.defensive_animations_),
teleport_animations_(o.teleport_animations_)
teleport_animations_(o.teleport_animations_), death_animations_(o.death_animations_)
{
gender_types_[0] = o.gender_types_[0] != NULL ? new unit_type(*o.gender_types_[0]) : NULL;
gender_types_[1] = o.gender_types_[1] != NULL ? new unit_type(*o.gender_types_[1]) : NULL;
@ -658,6 +658,11 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
for(config::child_list::const_iterator t = teleports.begin(); t != teleports.end(); ++t) {
teleport_animations_.push_back(unit_animation(**t));
}
const config::child_list& deaths = cfg_.get_children("death");
for(config::child_list::const_iterator death = deaths.begin(); death != deaths.end(); ++death) {
death_animations_.push_back(death_animation(**death));
}
}
unit_type::~unit_type()
@ -1038,6 +1043,28 @@ bool unit_type::defensive_animation::matches(bool h, attack_type::RANGE r) const
}
}
unit_type::death_animation::death_animation(const config& cfg)
: damage_type(utils::split(cfg["damage_type"])), special(utils::split(cfg["attack_special"])), animation(cfg)
{
}
bool unit_type::death_animation::matches(const attack_type* attack) const
{
if(attack == NULL) {
return true;
}
if(damage_type.empty() == false && std::find(damage_type.begin(),damage_type.end(),attack->type()) == damage_type.end()) {
return false;
}
if(special.empty() == false && std::find(special.begin(),special.end(),attack->special()) == special.end()) {
return false;
}
return true;
}
const unit_animation* unit_type::defend_animation(bool hits, attack_type::RANGE range) const
{
//select one of the matching animations at random
@ -1067,6 +1094,36 @@ const unit_animation* unit_type::teleport_animation( ) const
return &teleport_animations_[rand() % teleport_animations_.size()];
}
const unit_animation* unit_type::die_animation(const attack_type* attack) const
{
if(death_animations_.empty()) {
return NULL;
}
if(attack == NULL) {
return &death_animations_[rand()%death_animations_.size()].animation;
}
const unit_animation* res = NULL;
std::vector<const unit_animation*> options;
for(std::vector<death_animation>::const_iterator i = death_animations_.begin(); i != death_animations_.end(); ++i) {
if(i->matches(attack)) {
if(res != NULL) {
options.push_back(res);
}
res = &i->animation;
}
}
if(options.empty()) {
return res;
} else {
options.push_back(res);
return options[rand()%options.size()];
}
}
game_data::game_data()
{}

View File

@ -245,6 +245,7 @@ public:
const unit_animation* defend_animation(bool hits, attack_type::RANGE range) const;
const unit_animation* teleport_animation() const;
const unit_animation* die_animation(const attack_type* attack) const;
private:
void operator=(const unit_type& o);
@ -284,7 +285,7 @@ private:
struct defensive_animation
{
defensive_animation(const config& cfg);
explicit defensive_animation(const config& cfg);
bool matches(bool hits, attack_type::RANGE range) const;
enum { HIT, MISS, HIT_OR_MISS } hits;
@ -295,6 +296,17 @@ private:
std::vector<defensive_animation> defensive_animations_;
std::vector<unit_animation> teleport_animations_;
struct death_animation
{
explicit death_animation(const config& cfg);
bool matches(const attack_type* attack) const;
std::vector<std::string> damage_type, special;
unit_animation animation;
};
std::vector<death_animation> death_animations_;
};
struct game_data