allow multiple sub-animations, in all animations (not just missile in fight)
This commit is contained in:
parent
bdab825b22
commit
dd48d3d8db
11 changed files with 257 additions and 114 deletions
|
@ -41,6 +41,9 @@ Version 1.3.9+svn:
|
||||||
are now deleted (rather than just autosaves as formerly). This
|
are now deleted (rather than just autosaves as formerly). This
|
||||||
is done before replay saving, if that is enabled. The preference
|
is done before replay saving, if that is enabled. The preference
|
||||||
name has changed from delete_autosaves to delete_saves.
|
name has changed from delete_autosaves to delete_saves.
|
||||||
|
* Animation engine allow multiple type of frames (a la "missile frames")
|
||||||
|
for all types of anims, you can have multiple such anims using different
|
||||||
|
frame names
|
||||||
* miscellaneous and bug fixes:
|
* miscellaneous and bug fixes:
|
||||||
|
|
||||||
Version 1.3.9:
|
Version 1.3.9:
|
||||||
|
|
|
@ -112,6 +112,7 @@ private:
|
||||||
double acceleration_;
|
double acceleration_;
|
||||||
int last_update_tick_;
|
int last_update_tick_;
|
||||||
int current_frame_key_;
|
int current_frame_key_;
|
||||||
|
int last_frame_key_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,8 @@ animated<T,T_void_value>::animated(int start_time) :
|
||||||
cycles_(false),
|
cycles_(false),
|
||||||
acceleration_(1),
|
acceleration_(1),
|
||||||
last_update_tick_(0),
|
last_update_tick_(0),
|
||||||
current_frame_key_(0)
|
current_frame_key_(0),
|
||||||
|
last_frame_key_(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +65,8 @@ animated<T,T_void_value>::animated(const std::vector<std::pair<int,T> > &cfg, in
|
||||||
cycles_(false),
|
cycles_(false),
|
||||||
acceleration_(1),
|
acceleration_(1),
|
||||||
last_update_tick_(0),
|
last_update_tick_(0),
|
||||||
current_frame_key_(0)
|
current_frame_key_(0),
|
||||||
|
last_frame_key_(-1)
|
||||||
{
|
{
|
||||||
|
|
||||||
typename std::vector< std::pair<int,T> >::const_iterator itor = cfg.begin();
|
typename std::vector< std::pair<int,T> >::const_iterator itor = cfg.begin();
|
||||||
|
@ -101,6 +103,8 @@ void animated<T,T_void_value>::start_animation(int start_time, bool cycles, doub
|
||||||
if(acceleration_ <=0) acceleration_ = 1;
|
if(acceleration_ <=0) acceleration_ = 1;
|
||||||
current_frame_key_= 0;
|
current_frame_key_= 0;
|
||||||
update_last_draw_time();
|
update_last_draw_time();
|
||||||
|
// need to force last frame key in the case of starting anim...
|
||||||
|
last_frame_key_ = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,6 +112,7 @@ template<typename T, typename T_void_value>
|
||||||
void animated<T,T_void_value>::update_last_draw_time()
|
void animated<T,T_void_value>::update_last_draw_time()
|
||||||
{
|
{
|
||||||
last_update_tick_ = current_ticks;
|
last_update_tick_ = current_ticks;
|
||||||
|
last_frame_key_ = current_frame_key_;
|
||||||
if(does_not_change_)
|
if(does_not_change_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -124,6 +129,7 @@ void animated<T,T_void_value>::update_last_draw_time()
|
||||||
while(get_animation_time() > get_end_time()){ // cut extra time
|
while(get_animation_time() > get_end_time()){ // cut extra time
|
||||||
start_tick_ += static_cast<int>(get_end_time()/acceleration_);
|
start_tick_ += static_cast<int>(get_end_time()/acceleration_);
|
||||||
current_frame_key_ = 0;
|
current_frame_key_ = 0;
|
||||||
|
last_frame_key_ = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(get_current_frame_end_time() < get_animation_time() && // catch up
|
if(get_current_frame_end_time() < get_animation_time() && // catch up
|
||||||
|
|
|
@ -829,8 +829,8 @@ void display::clear_hex_overlay(const gamemap::location& loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
void display::render_unit_image(int x, int y, surface image,
|
void display::render_unit_image(int x, int y, surface image,
|
||||||
bool reverse, bool greyscale, fixed_t alpha,
|
bool hreverse, bool greyscale, fixed_t alpha,
|
||||||
Uint32 blendto, double blend_ratio, double submerged)
|
Uint32 blendto, double blend_ratio, double submerged,bool vreverse)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (image==NULL)
|
if (image==NULL)
|
||||||
|
@ -843,9 +843,12 @@ void display::render_unit_image(int x, int y, surface image,
|
||||||
|
|
||||||
surface surf(image);
|
surface surf(image);
|
||||||
|
|
||||||
if(reverse) {
|
if(hreverse) {
|
||||||
surf = image::reverse_image(surf);
|
surf = image::reverse_image(surf);
|
||||||
}
|
}
|
||||||
|
if(vreverse) {
|
||||||
|
surf = flop_surface(surf);
|
||||||
|
}
|
||||||
|
|
||||||
if(greyscale) {
|
if(greyscale) {
|
||||||
surf = greyscale_image(surf);
|
surf = greyscale_image(surf);
|
||||||
|
|
|
@ -234,9 +234,9 @@ public:
|
||||||
//! submerged: the amount of the unit out of 1.0 that is submerged
|
//! submerged: the amount of the unit out of 1.0 that is submerged
|
||||||
//! (presumably under water) and thus shouldn't be drawn
|
//! (presumably under water) and thus shouldn't be drawn
|
||||||
void render_unit_image(int x, int y, surface image,
|
void render_unit_image(int x, int y, surface image,
|
||||||
bool reverse=false, bool greyscale=false,
|
bool hreverse=false, bool greyscale=false,
|
||||||
fixed_t alpha=ftofxp(1.0), Uint32 blendto=0,
|
fixed_t alpha=ftofxp(1.0), Uint32 blendto=0,
|
||||||
double blend_ratio=0, double submerged=0.0);
|
double blend_ratio=0, double submerged=0.0,bool vreverse =false);
|
||||||
|
|
||||||
const theme::menu* menu_pressed();
|
const theme::menu* menu_pressed();
|
||||||
|
|
||||||
|
|
22
src/unit.cpp
22
src/unit.cpp
|
@ -1320,12 +1320,7 @@ void unit::read(const config& cfg, bool use_traits)
|
||||||
animations_ = ut->animations_;
|
animations_ = ut->animations_;
|
||||||
cfg_.clear_children("animation");
|
cfg_.clear_children("animation");
|
||||||
} else {
|
} else {
|
||||||
const config::child_list& animations = cfg_.get_children("animation");
|
unit_animation::initialize_anims(animations_,cfg_,type()->attacks(true));
|
||||||
config::child_list::const_iterator d;
|
|
||||||
for(d = animations.begin(); d != animations.end(); ++d) {
|
|
||||||
animations_.push_back(unit_animation(**d));
|
|
||||||
}
|
|
||||||
unit_animation::back_compat_initialize_anims(animations_,cfg_,type()->attacks(true));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Remove animations from private cfg, since they're not needed there now
|
// Remove animations from private cfg, since they're not needed there now
|
||||||
|
@ -1614,7 +1609,7 @@ void unit::start_animation(const game_display &disp, const gamemap::location &lo
|
||||||
offset_=0;
|
offset_=0;
|
||||||
if(anim_) delete anim_;
|
if(anim_) delete anim_;
|
||||||
anim_ = new unit_animation(*animation);
|
anim_ = new unit_animation(*animation);
|
||||||
anim_->start_animation(anim_->get_begin_time(), cycles, disp.turbo_speed());
|
anim_->start_animation(anim_->get_begin_time(),loc, loc.get_direction(facing_), cycles, disp.turbo_speed());
|
||||||
frame_begin_time_ = anim_->get_begin_time() -1;
|
frame_begin_time_ = anim_->get_begin_time() -1;
|
||||||
if (disp.idle_anim()) {
|
if (disp.idle_anim()) {
|
||||||
next_idling_ = get_current_animation_tick()
|
next_idling_ = get_current_animation_tick()
|
||||||
|
@ -1624,9 +1619,9 @@ void unit::start_animation(const game_display &disp, const gamemap::location &lo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void unit::restart_animation(const game_display& disp,int start_time) {
|
void unit::restart_animation(const game_display& disp,int start_time, bool cycles) {
|
||||||
if(!anim_) return;
|
if(!anim_) return;
|
||||||
anim_->start_animation(start_time,false,disp.turbo_speed());
|
anim_->start_animation(start_time,gamemap::location::null_location, gamemap::location::null_location, cycles, disp.turbo_speed());
|
||||||
frame_begin_time_ = start_time -1;
|
frame_begin_time_ = start_time -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1868,6 +1863,7 @@ void unit::redraw_unit(game_display& disp, const gamemap::location& loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
anim_->redraw();
|
||||||
refreshing_ = false;
|
refreshing_ = false;
|
||||||
anim_->update_last_draw_time();
|
anim_->update_last_draw_time();
|
||||||
}
|
}
|
||||||
|
@ -2590,13 +2586,7 @@ void unit::add_modification(const std::string& type, const config& mod, bool no_
|
||||||
game_config::add_color_info(**i.first);
|
game_config::add_color_info(**i.first);
|
||||||
LOG_UT << "applying image_mod \n";
|
LOG_UT << "applying image_mod \n";
|
||||||
} else if (apply_to == "new_animation") {
|
} else if (apply_to == "new_animation") {
|
||||||
// TODO most of this is to keep backward compatibility, to be removed in due time...
|
unit_animation::initialize_anims(animations_,**i.first,std::vector<attack_type>());
|
||||||
const config::child_list& animations = (**i.first).get_children("animation");
|
|
||||||
config::child_list::const_iterator d;
|
|
||||||
for(d = animations.begin(); d != animations.end(); ++d) {
|
|
||||||
animations_.push_back(unit_animation(**d));
|
|
||||||
}
|
|
||||||
unit_animation::back_compat_initialize_anims(animations_,**i.first,std::vector<attack_type>());
|
|
||||||
}
|
}
|
||||||
} // end while
|
} // end while
|
||||||
} else { // for times = per level & level = 0 we still need to rebuild the descriptions
|
} else { // for times = per level & level = 0 we still need to rebuild the descriptions
|
||||||
|
|
|
@ -190,7 +190,7 @@ public:
|
||||||
void set_victorious(const game_display &disp,const gamemap::location& loc,const attack_type* attack,const attack_type* secondary_attack);
|
void set_victorious(const game_display &disp,const gamemap::location& loc,const attack_type* attack,const attack_type* secondary_attack);
|
||||||
void set_poisoned(const game_display& disp,const gamemap::location& loc,int damage);
|
void set_poisoned(const game_display& disp,const gamemap::location& loc,int damage);
|
||||||
void set_idling(const game_display& disp,const gamemap::location& loc);
|
void set_idling(const game_display& disp,const gamemap::location& loc);
|
||||||
void restart_animation(const game_display& disp,int start_time);
|
void restart_animation(const game_display& disp,int start_time, bool cycles = false);
|
||||||
const unit_animation* get_animation() const { return anim_;};
|
const unit_animation* get_animation() const { return anim_;};
|
||||||
void set_offset(double offset){offset_ = offset;}
|
void set_offset(double offset){offset_ = offset;}
|
||||||
void set_facing(gamemap::location::DIRECTION dir);
|
void set_facing(gamemap::location::DIRECTION dir);
|
||||||
|
|
|
@ -19,12 +19,14 @@
|
||||||
#include "game_config.hpp"
|
#include "game_config.hpp"
|
||||||
#include "gettext.hpp"
|
#include "gettext.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
#include "halo.hpp"
|
||||||
#include "pathutils.hpp"
|
#include "pathutils.hpp"
|
||||||
#include "unit.hpp"
|
#include "unit.hpp"
|
||||||
#include "unit_animation.hpp"
|
#include "unit_animation.hpp"
|
||||||
#include "unit_types.hpp"
|
#include "unit_types.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "variable.hpp"
|
#include "variable.hpp"
|
||||||
|
#include "sound.hpp"
|
||||||
#include "wassert.hpp"
|
#include "wassert.hpp"
|
||||||
#include "serialization/string_utils.hpp"
|
#include "serialization/string_utils.hpp"
|
||||||
|
|
||||||
|
@ -104,8 +106,14 @@ unit_animation::unit_animation(int start_time,const unit_frame & frame , const s
|
||||||
|
|
||||||
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_(t_translation::read_list(cfg["terrain"])),base_score_(0),
|
terrain_types_(t_translation::read_list(cfg["terrain"])),base_score_(0),
|
||||||
missile_anim_(cfg,"missile_"),unit_anim_(cfg,frame_string)
|
unit_anim_(cfg,frame_string)
|
||||||
{
|
{
|
||||||
|
config::child_map::const_iterator frame_itor =cfg.all_children().begin();
|
||||||
|
for( /*null*/; frame_itor != cfg.all_children().end() ; frame_itor++) {
|
||||||
|
if(frame_itor->first == frame_string) continue;
|
||||||
|
if(frame_itor->first.find("_frame",frame_itor->first.size() -6 ) == std::string::npos) continue;
|
||||||
|
sub_anims_[frame_itor->first] = crude_animation(cfg,frame_itor->first.substr(0,frame_itor->first.size() -5));
|
||||||
|
}
|
||||||
event_ =utils::split(cfg["apply_to"]);
|
event_ =utils::split(cfg["apply_to"]);
|
||||||
|
|
||||||
const std::vector<std::string>& my_directions = utils::split(cfg["direction"]);
|
const std::vector<std::string>& my_directions = utils::split(cfg["direction"]);
|
||||||
|
@ -266,10 +274,18 @@ void unit_animation::back_compat_add_name(const std::string name,const std::stri
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void unit_animation::back_compat_initialize_anims( std::vector<unit_animation> & animations, const config & cfg, std::vector<attack_type> tmp_attacks)
|
void unit_animation::initialize_anims( std::vector<unit_animation> & animations, const config & cfg, std::vector<attack_type> tmp_attacks)
|
||||||
{
|
{
|
||||||
config expanded_cfg;
|
config expanded_cfg;
|
||||||
config::child_list::const_iterator anim_itor;
|
config::child_list::const_iterator anim_itor;
|
||||||
|
|
||||||
|
expanded_cfg = unit_animation::prepare_animation(cfg,"animation");
|
||||||
|
const config::child_list& parsed_animations = expanded_cfg.get_children("animation");
|
||||||
|
for(anim_itor = parsed_animations.begin(); anim_itor != parsed_animations.end(); ++anim_itor) {
|
||||||
|
animations.push_back(unit_animation(**anim_itor));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
expanded_cfg = unit_animation::prepare_animation(cfg,"leading_anim");
|
expanded_cfg = unit_animation::prepare_animation(cfg,"leading_anim");
|
||||||
const config::child_list& leading_anims = expanded_cfg.get_children("leading_anim");
|
const config::child_list& leading_anims = expanded_cfg.get_children("leading_anim");
|
||||||
for(anim_itor = leading_anims.begin(); anim_itor != leading_anims.end(); ++anim_itor) {
|
for(anim_itor = leading_anims.begin(); anim_itor != leading_anims.end(); ++anim_itor) {
|
||||||
|
@ -513,6 +529,10 @@ unit_animation::crude_animation::crude_animation(const config& cfg,const std::st
|
||||||
} else {
|
} else {
|
||||||
starting_frame_time_ = atoi(cfg[frame_string+"start_time"].c_str());
|
starting_frame_time_ = atoi(cfg[frame_string+"start_time"].c_str());
|
||||||
}
|
}
|
||||||
|
if(frame_string == "missile_") {
|
||||||
|
// lg::wml_error To be deprecated eventually
|
||||||
|
add_frame(1,unit_frame("",1),true);
|
||||||
|
}
|
||||||
|
|
||||||
for(; range.first != range.second; ++range.first) {
|
for(; range.first != range.second; ++range.first) {
|
||||||
unit_frame tmp_frame(**range.first);
|
unit_frame tmp_frame(**range.first);
|
||||||
|
@ -526,6 +546,14 @@ unit_animation::crude_animation::crude_animation(const config& cfg,const std::st
|
||||||
blend_ratio_ = progressive_double(cfg[frame_string+"blend_ratio"],get_animation_duration());
|
blend_ratio_ = progressive_double(cfg[frame_string+"blend_ratio"],get_animation_duration());
|
||||||
highlight_ratio_ = progressive_double(cfg[frame_string+"alpha"],get_animation_duration());
|
highlight_ratio_ = progressive_double(cfg[frame_string+"alpha"],get_animation_duration());
|
||||||
offset_ = progressive_double(cfg[frame_string+"offset"],get_animation_duration());
|
offset_ = progressive_double(cfg[frame_string+"offset"],get_animation_duration());
|
||||||
|
if(offset_.does_not_change() && frame_string == "missile_") {
|
||||||
|
// lg::wml_error To be deprecated eventually
|
||||||
|
offset_=progressive_double("0~0.8",get_animation_duration());
|
||||||
|
}
|
||||||
|
if( frame_string == "missile_") {
|
||||||
|
// lg::wml_error To be deprecated eventually
|
||||||
|
add_frame(1,unit_frame("",1),true);
|
||||||
|
}
|
||||||
|
|
||||||
if(!halo_.does_not_change() ||
|
if(!halo_.does_not_change() ||
|
||||||
!halo_x_.does_not_change() ||
|
!halo_x_.does_not_change() ||
|
||||||
|
@ -539,3 +567,166 @@ unit_animation::crude_animation::crude_animation(const config& cfg,const std::st
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool unit_animation::need_update() const
|
||||||
|
{
|
||||||
|
if(unit_anim_.need_update()) return true;
|
||||||
|
std::map<std::string,crude_animation>::const_iterator anim_itor =sub_anims_.begin();
|
||||||
|
for( /*null*/; anim_itor != sub_anims_.end() ; anim_itor++) {
|
||||||
|
if(anim_itor->second.need_update()) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
bool unit_animation::animation_finished() const
|
||||||
|
{
|
||||||
|
if(!unit_anim_.animation_finished()) return false;
|
||||||
|
std::map<std::string,crude_animation>::const_iterator anim_itor =sub_anims_.begin();
|
||||||
|
for( /*null*/; anim_itor != sub_anims_.end() ; anim_itor++) {
|
||||||
|
if(!anim_itor->second.animation_finished()) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
bool unit_animation::animation_would_finish() const
|
||||||
|
{
|
||||||
|
if(!unit_anim_.animation_would_finish()) return false;
|
||||||
|
std::map<std::string,crude_animation>::const_iterator anim_itor =sub_anims_.begin();
|
||||||
|
for( /*null*/; anim_itor != sub_anims_.end() ; anim_itor++) {
|
||||||
|
if(!anim_itor->second.animation_would_finish()) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
void unit_animation::update_last_draw_time()
|
||||||
|
{
|
||||||
|
unit_anim_.update_last_draw_time();
|
||||||
|
std::map<std::string,crude_animation>::iterator anim_itor =sub_anims_.begin();
|
||||||
|
for( /*null*/; anim_itor != sub_anims_.end() ; anim_itor++) {
|
||||||
|
anim_itor->second.update_last_draw_time();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
int unit_animation::get_end_time() const
|
||||||
|
{
|
||||||
|
int result = unit_anim_.get_end_time();
|
||||||
|
std::map<std::string,crude_animation>::const_iterator anim_itor =sub_anims_.end();
|
||||||
|
for( /*null*/; anim_itor != sub_anims_.end() ; anim_itor++) {
|
||||||
|
result= minimum<int>(result,anim_itor->second.get_end_time());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
int unit_animation::get_begin_time() const
|
||||||
|
{
|
||||||
|
int result = unit_anim_.get_begin_time();
|
||||||
|
std::map<std::string,crude_animation>::const_iterator anim_itor =sub_anims_.begin();
|
||||||
|
for( /*null*/; anim_itor != sub_anims_.end() ; anim_itor++) {
|
||||||
|
result= minimum<int>(result,anim_itor->second.get_begin_time());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
void unit_animation::start_animation(int start_time,const gamemap::location &src, const gamemap::location &dst, bool cycles, double acceleration)
|
||||||
|
{
|
||||||
|
unit_anim_.start_animation(start_time, src, dst, cycles, acceleration);
|
||||||
|
std::map<std::string,crude_animation>::iterator anim_itor =sub_anims_.begin();
|
||||||
|
for( /*null*/; anim_itor != sub_anims_.end() ; anim_itor++) {
|
||||||
|
anim_itor->second.start_animation(start_time,src,dst,cycles,acceleration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void unit_animation::redraw()
|
||||||
|
{
|
||||||
|
std::map<std::string,crude_animation>::iterator anim_itor =sub_anims_.begin();
|
||||||
|
for( /*null*/; anim_itor != sub_anims_.end() ; anim_itor++) {
|
||||||
|
anim_itor->second.redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void unit_animation::crude_animation::redraw()
|
||||||
|
{
|
||||||
|
const int xsrc = game_display::get_singleton()->get_location_x(src_);
|
||||||
|
const int ysrc = game_display::get_singleton()->get_location_y(src_);
|
||||||
|
const int xdst = game_display::get_singleton()->get_location_x(dst_);
|
||||||
|
const int ydst = game_display::get_singleton()->get_location_y(dst_);
|
||||||
|
const gamemap::location::DIRECTION direction = src_.get_relative_dir(dst_);
|
||||||
|
|
||||||
|
double tmp_offset = offset();
|
||||||
|
int d2 = game_display::get_singleton()->hex_size() / 2;
|
||||||
|
const unit_frame& current_frame= get_current_frame();
|
||||||
|
if(!current_frame.sound().empty() && get_current_frame_begin_time() != last_frame_begin_time_ ) {
|
||||||
|
sound::play_sound(current_frame.sound());
|
||||||
|
}
|
||||||
|
last_frame_begin_time_ = get_current_frame_begin_time();
|
||||||
|
image::locator image_loc;
|
||||||
|
if(direction != gamemap::location::NORTH && direction != gamemap::location::SOUTH) {
|
||||||
|
image_loc = current_frame.image_diagonal();
|
||||||
|
}
|
||||||
|
if(image_loc.is_void()) { // invalid diag image, or not diagonal
|
||||||
|
image_loc = current_frame.image();
|
||||||
|
}
|
||||||
|
|
||||||
|
surface image;
|
||||||
|
if(!image_loc.is_void() && image_loc.get_filename() != "") { // invalid diag image, or not diagonal
|
||||||
|
image=image::get_image(image_loc,
|
||||||
|
image::SCALED_TO_ZOOM,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const int x = static_cast<int>(tmp_offset * xdst + (1.0-tmp_offset) * xsrc) + d2 ;
|
||||||
|
const int y = static_cast<int>(tmp_offset * ydst + (1.0-tmp_offset) * ysrc) + d2;
|
||||||
|
if (image != NULL) {
|
||||||
|
bool facing_west = direction == gamemap::location::NORTH_WEST || direction == gamemap::location::SOUTH_WEST;
|
||||||
|
bool facing_north = direction == gamemap::location::NORTH_WEST || direction == gamemap::location::NORTH || direction == gamemap::location::NORTH_EAST;
|
||||||
|
game_display::get_singleton()->render_unit_image(x- image->w/2, y - image->h/2, image, facing_west, false,
|
||||||
|
highlight_ratio(), blend_with_, blend_ratio(),0,!facing_north);
|
||||||
|
}
|
||||||
|
halo::remove(halo_id_);
|
||||||
|
halo_id_ = halo::NO_HALO;
|
||||||
|
if(!halo().empty()) {
|
||||||
|
halo::ORIENTATION orientation;
|
||||||
|
switch(direction)
|
||||||
|
{
|
||||||
|
case gamemap::location::NORTH:
|
||||||
|
case gamemap::location::NORTH_EAST:
|
||||||
|
orientation = halo::NORMAL;
|
||||||
|
break;
|
||||||
|
case gamemap::location::SOUTH_EAST:
|
||||||
|
case gamemap::location::SOUTH:
|
||||||
|
orientation = halo::VREVERSE;
|
||||||
|
break;
|
||||||
|
case gamemap::location::SOUTH_WEST:
|
||||||
|
orientation = halo::HVREVERSE;
|
||||||
|
break;
|
||||||
|
case gamemap::location::NORTH_WEST:
|
||||||
|
orientation = halo::HREVERSE;
|
||||||
|
break;
|
||||||
|
case gamemap::location::NDIRECTIONS:
|
||||||
|
default:
|
||||||
|
orientation = halo::NORMAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(direction != gamemap::location::SOUTH_WEST && direction != gamemap::location::NORTH_WEST) {
|
||||||
|
halo_id_ = halo::add(x+halo_x(),
|
||||||
|
y+halo_y(),
|
||||||
|
halo(),
|
||||||
|
gamemap::location(-1, -1),
|
||||||
|
orientation);
|
||||||
|
} else {
|
||||||
|
halo_id_ = halo::add(x-halo_x(),
|
||||||
|
y+halo_y(),
|
||||||
|
halo(),
|
||||||
|
gamemap::location(-1, -1),
|
||||||
|
orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_last_draw_time();
|
||||||
|
}
|
||||||
|
unit_animation::crude_animation::~crude_animation()
|
||||||
|
{
|
||||||
|
halo::remove(halo_id_);
|
||||||
|
halo_id_ = halo::NO_HALO;
|
||||||
|
}
|
||||||
|
void unit_animation::crude_animation::start_animation(int start_time,const gamemap::location &src,const gamemap::location &dst, bool cycles, double acceleration)
|
||||||
|
{
|
||||||
|
halo::remove(halo_id_);
|
||||||
|
halo_id_ = halo::NO_HALO;
|
||||||
|
animated<unit_frame>::start_animation(start_time,cycles,acceleration);
|
||||||
|
last_frame_begin_time_ = get_begin_time() -1;
|
||||||
|
if(src != gamemap::location::null_location || dst != gamemap::location::null_location) {
|
||||||
|
src_ = src;
|
||||||
|
dst_ = dst;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -34,13 +34,33 @@ class unit_animation
|
||||||
public:
|
public:
|
||||||
typedef enum { MATCH_FAIL=-2 , DEFAULT_ANIM=-1};
|
typedef enum { MATCH_FAIL=-2 , DEFAULT_ANIM=-1};
|
||||||
typedef enum { HIT, MISS, KILL, INVALID} hit_type;
|
typedef enum { HIT, MISS, KILL, INVALID} hit_type;
|
||||||
static config prepare_animation(const config &cfg,const std::string animation_tag);
|
static void initialize_anims( std::vector<unit_animation> & animations, const config & cfg, std::vector<attack_type> tmp_attacks);
|
||||||
|
|
||||||
unit_animation(){};
|
|
||||||
explicit unit_animation(const config& cfg,const std::string frame_string ="");
|
|
||||||
explicit unit_animation(int start_time,const unit_frame &frame,const std::string& even="",const int variation=0);
|
|
||||||
int matches(const game_display &disp,const gamemap::location& loc,const unit* my_unit,const std::string & event="",const int value=0,hit_type hit=INVALID,const attack_type* attack=NULL,const attack_type* second_attack = NULL, int swing_num =0) const;
|
int matches(const game_display &disp,const gamemap::location& loc,const unit* my_unit,const std::string & event="",const int value=0,hit_type hit=INVALID,const attack_type* attack=NULL,const attack_type* second_attack = NULL, int swing_num =0) const;
|
||||||
|
|
||||||
|
|
||||||
|
const unit_frame& get_last_frame() const{ return unit_anim_.get_last_frame() ; };
|
||||||
|
void add_frame(int duration, const unit_frame& value,bool force_change =false){ unit_anim_.add_frame(duration,value,force_change) ; };
|
||||||
|
|
||||||
|
bool need_update() const;
|
||||||
|
bool animation_finished() const;
|
||||||
|
bool animation_would_finish() const;
|
||||||
|
void update_last_draw_time();
|
||||||
|
int get_begin_time() const;
|
||||||
|
int get_end_time() const;
|
||||||
|
int get_animation_time() const{ return unit_anim_.get_animation_time() ; };
|
||||||
|
void start_animation(int start_time,const gamemap::location &src = gamemap::location::null_location, const gamemap::location &dst = gamemap::location::null_location , bool cycles=false, double acceleration=1);
|
||||||
|
const int get_current_frame_begin_time() const{ return unit_anim_.get_current_frame_begin_time() ; };
|
||||||
|
void redraw();
|
||||||
|
|
||||||
|
// only to support all [attack_anim] format, to remove at 1.3.10 time
|
||||||
|
void back_compat_add_name(const std::string name="",const std::string range ="");
|
||||||
|
// to be privatized post 1.3.10
|
||||||
|
static config prepare_animation(const config &cfg,const std::string animation_tag);
|
||||||
|
explicit unit_animation(const config& cfg,const std::string frame_string ="");
|
||||||
|
friend class unit;
|
||||||
|
protected:
|
||||||
|
// reserved to class unit, for the special case of redrawing the unit base frame
|
||||||
image::locator image() const { return unit_anim_.get_current_frame().image() ; }
|
image::locator image() const { return unit_anim_.get_current_frame().image() ; }
|
||||||
image::locator image_diagonal() const { return unit_anim_.get_current_frame().image_diagonal() ; }
|
image::locator image_diagonal() const { return unit_anim_.get_current_frame().image_diagonal() ; }
|
||||||
std::string sound() const { return unit_anim_.get_current_frame().sound() ; };
|
std::string sound() const { return unit_anim_.get_current_frame().sound() ; };
|
||||||
|
@ -51,29 +71,15 @@ class unit_animation
|
||||||
double blend_ratio(const double default_val = 0) const{ return unit_anim_.blend_ratio(default_val); };
|
double blend_ratio(const double default_val = 0) const{ return unit_anim_.blend_ratio(default_val); };
|
||||||
fixed_t highlight_ratio(const float default_val = 1.0) const{ return unit_anim_.highlight_ratio(default_val); };
|
fixed_t highlight_ratio(const float default_val = 1.0) const{ return unit_anim_.highlight_ratio(default_val); };
|
||||||
double offset(double default_val =0.0) const{ return unit_anim_.offset(default_val); };
|
double offset(double default_val =0.0) const{ return unit_anim_.offset(default_val); };
|
||||||
|
|
||||||
bool need_update() const{return unit_anim_.need_update();};
|
|
||||||
bool animation_finished() const{ return unit_anim_.animation_finished() ; };
|
|
||||||
bool animation_would_finish() const{ return unit_anim_.animation_would_finish() ; };
|
|
||||||
const unit_frame& get_last_frame() const{ return unit_anim_.get_last_frame() ; };
|
|
||||||
void add_frame(int duration, const unit_frame& value,bool force_change =false){ unit_anim_.add_frame(duration,value,force_change) ; };
|
|
||||||
void start_animation(int start_time, bool cycles=false, double acceleration=1){ unit_anim_.start_animation(start_time, cycles, acceleration);};
|
|
||||||
int get_begin_time() const{ return unit_anim_.get_begin_time() ; };
|
|
||||||
void update_last_draw_time(){unit_anim_.update_last_draw_time();};
|
|
||||||
const int get_current_frame_begin_time() const{ return unit_anim_.get_current_frame_begin_time() ; };
|
|
||||||
int get_animation_time() const{ return unit_anim_.get_animation_time() ; };
|
|
||||||
int get_end_time() const{ return unit_anim_.get_end_time() ; };
|
|
||||||
|
|
||||||
// only to support all [attack_anim] format, to remove at 1.3.10 time
|
|
||||||
void back_compat_add_name(const std::string name="",const std::string range ="");
|
|
||||||
const animated<unit_frame> &get_missile_anim() const {return missile_anim_;}
|
|
||||||
static void back_compat_initialize_anims( std::vector<unit_animation> & animations, const config & cfg, std::vector<attack_type> tmp_attacks);
|
|
||||||
private:
|
private:
|
||||||
|
unit_animation(){};
|
||||||
|
explicit unit_animation(int start_time,const unit_frame &frame,const std::string& even="",const int variation=0);
|
||||||
class crude_animation:public animated<unit_frame>
|
class crude_animation:public animated<unit_frame>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit crude_animation(int start_time=0):animated<unit_frame>(start_time){};
|
explicit crude_animation(int start_time=0):animated<unit_frame>(start_time){};
|
||||||
explicit crude_animation(const config& cfg,const std::string frame_string ="frame");
|
explicit crude_animation(const config& cfg,const std::string frame_string ="frame");
|
||||||
|
virtual ~crude_animation();
|
||||||
bool need_update() const;
|
bool need_update() const;
|
||||||
const std::string &halo(const std::string&default_val ="") const;
|
const std::string &halo(const std::string&default_val ="") const;
|
||||||
int halo_x(const int default_val = 0) const;
|
int halo_x(const int default_val = 0) const;
|
||||||
|
@ -81,6 +87,8 @@ class unit_animation
|
||||||
double blend_ratio(const double default_val = 0) const;
|
double blend_ratio(const double default_val = 0) const;
|
||||||
fixed_t highlight_ratio(const float default_val = 1.0) const;
|
fixed_t highlight_ratio(const float default_val = 1.0) const;
|
||||||
double offset(double default_val =0.0) const;
|
double offset(double default_val =0.0) const;
|
||||||
|
void redraw( );
|
||||||
|
void start_animation(int start_time,const gamemap::location& src,const gamemap::location& dst, bool cycles=false, double acceleration=1);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//animation params that can be locally overridden by frames
|
//animation params that can be locally overridden by frames
|
||||||
|
@ -91,6 +99,10 @@ class unit_animation
|
||||||
Uint32 blend_with_;
|
Uint32 blend_with_;
|
||||||
progressive_double blend_ratio_;
|
progressive_double blend_ratio_;
|
||||||
progressive_double highlight_ratio_;
|
progressive_double highlight_ratio_;
|
||||||
|
gamemap::location src_;
|
||||||
|
gamemap::location dst_;
|
||||||
|
int halo_id_;
|
||||||
|
int last_frame_begin_time_;
|
||||||
|
|
||||||
};
|
};
|
||||||
t_translation::t_list terrain_types_;
|
t_translation::t_list terrain_types_;
|
||||||
|
@ -105,7 +117,7 @@ class unit_animation
|
||||||
std::vector<config> secondary_attack_filter_;
|
std::vector<config> secondary_attack_filter_;
|
||||||
std::vector<hit_type> hits_;
|
std::vector<hit_type> hits_;
|
||||||
std::vector<int> swing_num_;
|
std::vector<int> swing_num_;
|
||||||
crude_animation missile_anim_;
|
std::map<std::string,crude_animation> sub_anims_;
|
||||||
crude_animation unit_anim_;
|
crude_animation unit_anim_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -236,14 +236,8 @@ static void unit_attack_ranged(
|
||||||
disp->place_temporary_unit(defender,b);
|
disp->place_temporary_unit(defender,b);
|
||||||
defender.set_hidden(false);
|
defender.set_hidden(false);
|
||||||
|
|
||||||
const double acceleration = disp->turbo_speed();
|
|
||||||
|
|
||||||
|
|
||||||
// More damage shown for longer, but 1s at most for this factor
|
|
||||||
const double xsrc = disp->get_location_x(a);
|
|
||||||
const double ysrc = disp->get_location_y(a) - (attacker.is_flying() ? 0 : disp->get_map().get_terrain_info(disp->get_map().get_terrain(a)).unit_height_adjust());
|
|
||||||
const double xdst = disp->get_location_x(b);
|
|
||||||
const double ydst = disp->get_location_y(b) -( defender.is_flying() ? 0 : disp->get_map().get_terrain_info(disp->get_map().get_terrain(b)).unit_height_adjust());
|
|
||||||
|
|
||||||
gamemap::location update_tiles[6];
|
gamemap::location update_tiles[6];
|
||||||
get_adjacent_tiles(b,update_tiles);
|
get_adjacent_tiles(b,update_tiles);
|
||||||
|
@ -253,7 +247,6 @@ static void unit_attack_ranged(
|
||||||
|
|
||||||
// Start leader and attacker animation, wait for attacker animation to end
|
// Start leader and attacker animation, wait for attacker animation to end
|
||||||
attacker.set_attacking(*disp,a,damage,attack,secondary_attack,swing);
|
attacker.set_attacking(*disp,a,damage,attack,secondary_attack,swing);
|
||||||
animated<unit_frame> missile_animation = attacker.get_animation()->get_missile_anim();
|
|
||||||
const gamemap::location leader_loc = under_leadership(units,a);
|
const gamemap::location leader_loc = under_leadership(units,a);
|
||||||
unit_map::iterator leader = units.end();
|
unit_map::iterator leader = units.end();
|
||||||
if(leader_loc.valid()){
|
if(leader_loc.valid()){
|
||||||
|
@ -289,15 +282,12 @@ static void unit_attack_ranged(
|
||||||
orientation = halo::NORMAL;
|
orientation = halo::NORMAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const bool vertical_dir = (a.x == b.x) ? true:false;
|
|
||||||
|
|
||||||
defender.set_defending(*disp,b,damage,&attack,secondary_attack,swing);
|
defender.set_defending(*disp,b,damage,&attack,secondary_attack,swing);
|
||||||
// Min of attacker, defender, missile and -200
|
// Min of attacker, defender, missile and -200
|
||||||
int start_time = -200;
|
int start_time = -200;
|
||||||
start_time = minimum<int>(start_time,defender.get_animation()->get_begin_time());
|
start_time = minimum<int>(start_time,defender.get_animation()->get_begin_time());
|
||||||
start_time = minimum<int>(start_time,missile_animation.get_begin_time());
|
|
||||||
start_time = minimum<int>(start_time,attacker.get_animation()->get_begin_time());
|
start_time = minimum<int>(start_time,attacker.get_animation()->get_begin_time());
|
||||||
missile_animation.start_animation(start_time,false,acceleration);
|
|
||||||
defender.restart_animation(*disp,start_time);
|
defender.restart_animation(*disp,start_time);
|
||||||
attacker.restart_animation(*disp,start_time);
|
attacker.restart_animation(*disp,start_time);
|
||||||
animation_time = defender.get_animation()->get_animation_time();
|
animation_time = defender.get_animation()->get_animation_time();
|
||||||
|
@ -307,56 +297,9 @@ static void unit_attack_ranged(
|
||||||
while(!hide && (
|
while(!hide && (
|
||||||
!attacker.get_animation()->animation_would_finish() ||
|
!attacker.get_animation()->animation_would_finish() ||
|
||||||
!defender.get_animation()->animation_would_finish() ||
|
!defender.get_animation()->animation_would_finish() ||
|
||||||
!missile_animation.animation_finished() ||
|
|
||||||
(leader_loc.valid() && !leader->second.get_animation()->animation_finished()) ||
|
(leader_loc.valid() && !leader->second.get_animation()->animation_finished()) ||
|
||||||
damage >0)
|
damage >0)
|
||||||
){
|
){
|
||||||
const unit_frame& missile_frame = missile_animation.get_current_frame();
|
|
||||||
double pos = missile_frame.offset(missile_animation.get_current_frame_time(),
|
|
||||||
double(animation_time -missile_animation.get_begin_time())/
|
|
||||||
double(missile_animation.get_end_time()-missile_animation.get_begin_time()));
|
|
||||||
disp->invalidate(b);
|
|
||||||
disp->invalidate(a);
|
|
||||||
if(leader_loc.valid()) disp->invalidate(leader_loc);
|
|
||||||
halo::remove(missile_halo);
|
|
||||||
halo::remove(missile_frame_halo);
|
|
||||||
missile_halo = halo::NO_HALO;
|
|
||||||
missile_frame_halo = halo::NO_HALO;
|
|
||||||
if(animation_time > missile_animation.get_begin_time() &&
|
|
||||||
animation_time < missile_animation.get_end_time() &&
|
|
||||||
(!disp->fogged(b) || !disp->fogged(a))) {
|
|
||||||
const int posx = int(pos*xdst + (1.0-pos)*xsrc);
|
|
||||||
const int posy = int(pos*ydst + (1.0-pos)*ysrc);
|
|
||||||
|
|
||||||
image::locator missile_image= missile_frame.image();
|
|
||||||
const int d = disp->hex_size() / 2;
|
|
||||||
if(vertical_dir) {
|
|
||||||
missile_image = missile_frame.image();
|
|
||||||
} else {
|
|
||||||
missile_image = missile_frame.image_diagonal();
|
|
||||||
}
|
|
||||||
if(!missile_frame.halo(missile_animation.get_current_frame_time()).empty()) {
|
|
||||||
if(attack_ori != gamemap::location::SOUTH_WEST && attack_ori != gamemap::location::NORTH_WEST) {
|
|
||||||
missile_halo = halo::add(posx+d+missile_frame.halo_x(missile_animation.get_current_frame_time()),
|
|
||||||
posy+d+missile_frame.halo_y(missile_animation.get_current_frame_time()),
|
|
||||||
missile_frame.halo(missile_animation.get_current_frame_time()),
|
|
||||||
gamemap::location(-1, -1),
|
|
||||||
orientation);
|
|
||||||
} else {
|
|
||||||
missile_halo = halo::add(posx+d-missile_frame.halo_x(missile_animation.get_current_frame_time()),
|
|
||||||
posy+d+missile_frame.halo_y(missile_animation.get_current_frame_time()),
|
|
||||||
missile_frame.halo(missile_animation.get_current_frame_time()),
|
|
||||||
gamemap::location(-1, -1),
|
|
||||||
orientation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
missile_frame_halo = halo::add(posx+d,
|
|
||||||
posy+d,
|
|
||||||
missile_image.get_filename(),
|
|
||||||
gamemap::location(-1, -1),
|
|
||||||
orientation);
|
|
||||||
|
|
||||||
}
|
|
||||||
if(!sound_played && animation_time > 0) {
|
if(!sound_played && animation_time > 0) {
|
||||||
sound_played = true;
|
sound_played = true;
|
||||||
std::string text ;
|
std::string text ;
|
||||||
|
@ -376,11 +319,10 @@ static void unit_attack_ranged(
|
||||||
}
|
}
|
||||||
disp->draw();
|
disp->draw();
|
||||||
events::pump();
|
events::pump();
|
||||||
missile_animation.update_last_draw_time();
|
|
||||||
disp->delay(10);
|
disp->delay(10);
|
||||||
// We use missile animation because it's the only one
|
// We use missile animation because it's the only one
|
||||||
// not reseted in the middle to go to standing
|
// not reseted in the middle to go to standing
|
||||||
animation_time = missile_animation.get_animation_time();
|
animation_time = attacker.get_animation()->get_animation_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
halo::remove(missile_halo);
|
halo::remove(missile_halo);
|
||||||
|
|
|
@ -44,6 +44,7 @@ attack_type::attack_type(const config& cfg,const std::string& id, bool with_anim
|
||||||
}
|
}
|
||||||
if (with_animations) {
|
if (with_animations) {
|
||||||
const config expanded_cfg = unit_animation::prepare_animation(cfg,"animation");
|
const config expanded_cfg = unit_animation::prepare_animation(cfg,"animation");
|
||||||
|
// TODO: prepare animation should be privatized once the code is removed
|
||||||
const config::child_list& animations = expanded_cfg.get_children("animation");
|
const config::child_list& animations = expanded_cfg.get_children("animation");
|
||||||
for(config::child_list::const_iterator d = animations.begin(); d != animations.end(); ++d) {
|
for(config::child_list::const_iterator d = animations.begin(); d != animations.end(); ++d) {
|
||||||
lg::wml_error<<"attack animation directly in attack is deprecated, support will be removed in 1.3.10 (in unit "<<id<<")\n";
|
lg::wml_error<<"attack animation directly in attack is deprecated, support will be removed in 1.3.10 (in unit "<<id<<")\n";
|
||||||
|
@ -627,13 +628,7 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
|
||||||
|
|
||||||
experience_needed_=lexical_cast_default<int>(cfg_["experience"],500);
|
experience_needed_=lexical_cast_default<int>(cfg_["experience"],500);
|
||||||
|
|
||||||
config expanded_cfg = unit_animation::prepare_animation(cfg,"animation");
|
unit_animation::initialize_anims(animations_,cfg,attacks(true));
|
||||||
const config::child_list& animations = expanded_cfg.get_children("animation");
|
|
||||||
config::child_list::const_iterator anim_itor;
|
|
||||||
for(anim_itor = animations.begin(); anim_itor != animations.end(); ++anim_itor) {
|
|
||||||
animations_.push_back(unit_animation(**anim_itor));
|
|
||||||
}
|
|
||||||
unit_animation::back_compat_initialize_anims(animations_,cfg,attacks(true));
|
|
||||||
flag_rgb_ = cfg["flag_rgb"];
|
flag_rgb_ = cfg["flag_rgb"];
|
||||||
game_config::add_color_info(cfg);
|
game_config::add_color_info(cfg);
|
||||||
// Deprecation messages, only seen when unit is parsed for the first time.
|
// Deprecation messages, only seen when unit is parsed for the first time.
|
||||||
|
|
Loading…
Add table
Reference in a new issue