added experimental xp bars next to hp bars
This commit is contained in:
parent
3858092314
commit
b74679f079
6 changed files with 140 additions and 69 deletions
148
src/display.cpp
148
src/display.cpp
|
@ -71,8 +71,6 @@ display::display(unit_map& units, CVideo& video, const gamemap& map,
|
|||
if(non_interactive())
|
||||
updatesLocked_++;
|
||||
|
||||
energy_bar_rect_.x = -1;
|
||||
|
||||
std::fill(reportRects_,reportRects_+reports::NUM_REPORTS,empty_rect);
|
||||
|
||||
image::set_zoom(zoom_);
|
||||
|
@ -313,7 +311,7 @@ double display::zoom(int amount)
|
|||
return double(zoom_)/double(DefaultZoom);
|
||||
}
|
||||
|
||||
energy_bar_rect_.x = -1;
|
||||
energy_bar_rects_.clear();
|
||||
|
||||
std::cerr << "zoomed to: " << zoom_ << "\n";
|
||||
|
||||
|
@ -1058,22 +1056,27 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
|
||||
double unit_energy = 0.0;
|
||||
|
||||
Uint16 energy_colour = 0;
|
||||
|
||||
const int max_energy = 80;
|
||||
double energy_size = 1.0;
|
||||
SDL_Color energy_colour = {0,0,0,0};
|
||||
|
||||
if(unit_image_override != NULL)
|
||||
sdl_add_ref(unit_image_override);
|
||||
|
||||
scoped_sdl_surface unit_image(unit_image_override);
|
||||
scoped_sdl_surface energy_image(NULL);
|
||||
|
||||
const std::string* energy_file = NULL;
|
||||
|
||||
//see if there is a unit on this tile
|
||||
const unit_map::const_iterator it = units_.find(gamemap::location(x,y));
|
||||
if(it != units_.end() && (loc != hiddenUnit_ || !hideEnergy_)) {
|
||||
if(unit_image == NULL)
|
||||
if(it == units_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unit& u = it->second;
|
||||
|
||||
if(loc != hiddenUnit_ || !hideEnergy_) {
|
||||
if(unit_image == NULL) {
|
||||
unit_image.assign(image::get_image(it->second.image(),it->second.stone() ? image::GREYED : image::SCALED));
|
||||
}
|
||||
|
||||
if(unit_image == NULL) {
|
||||
return;
|
||||
|
@ -1082,9 +1085,7 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
const int unit_move = it->second.movement_left();
|
||||
const int unit_total_move = it->second.total_movement();
|
||||
|
||||
const std::string* energy_file = NULL;
|
||||
|
||||
if(size_t(it->second.side()) != currentTeam_+1) {
|
||||
if(size_t(u.side()) != currentTeam_+1) {
|
||||
if(team_valid() &&
|
||||
teams_[currentTeam_].is_enemy(it->second.side())) {
|
||||
energy_file = &game_config::enemy_energy_image;
|
||||
|
@ -1107,19 +1108,10 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
return;
|
||||
}
|
||||
|
||||
energy_image.assign(image::get_image(*energy_file,image::SCALED,image::NO_ADJUST_COLOUR));
|
||||
|
||||
if(energy_image.get() == NULL) {
|
||||
std::cerr << "failed to get energy image: '" << *energy_file << "'\n";
|
||||
return;
|
||||
}
|
||||
|
||||
unit_energy = minimum<double>(1.0,double(it->second.hitpoints()) / double(it->second.max_hitpoints()));
|
||||
|
||||
if(highlight_ratio == 1.0)
|
||||
highlight_ratio = it->second.alpha();
|
||||
|
||||
if(it->second.invisible(map_.underlying_terrain(map_[x][y]),
|
||||
if(u.invisible(map_.underlying_terrain(map_[x][y]),
|
||||
status_.get_time_of_day().lawful_bonus,loc,
|
||||
units_,teams_) &&
|
||||
highlight_ratio > 0.5) {
|
||||
|
@ -1131,27 +1123,25 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
blend_with = rgb(255,255,255);
|
||||
}
|
||||
|
||||
{
|
||||
int er = 0;
|
||||
int eg = 0;
|
||||
int eb = 0;
|
||||
if(unit_energy < 0.33) {
|
||||
er = 200;
|
||||
} else if(unit_energy < 0.66) {
|
||||
er = 200;
|
||||
eg = 200;
|
||||
} else {
|
||||
eg = 200;
|
||||
}
|
||||
|
||||
energy_colour = ::SDL_MapRGB(screen_.getSurface()->format,er,eg,eb);
|
||||
if(u.max_hitpoints() > 0) {
|
||||
unit_energy = double(u.hitpoints())/double(u.max_hitpoints());
|
||||
}
|
||||
|
||||
if(it->second.max_hitpoints() < max_energy) {
|
||||
energy_size = double(it->second.max_hitpoints())/double(max_energy);
|
||||
if(unit_energy < 0.33) {
|
||||
energy_colour.r = 200;
|
||||
energy_colour.g = 0;
|
||||
energy_colour.b = 0;
|
||||
} else if(unit_energy < 0.66) {
|
||||
energy_colour.r = 200;
|
||||
energy_colour.g = 200;
|
||||
energy_colour.b = 0;
|
||||
} else {
|
||||
energy_colour.r = 0;
|
||||
energy_colour.g = 200;
|
||||
energy_colour.b = 0;
|
||||
}
|
||||
|
||||
if(it->second.facing_left() == false) {
|
||||
if(u.facing_left() == false) {
|
||||
//reverse the image here. image::reverse_image is more efficient, however
|
||||
//it can be used only if we are sure that unit_image came from image::get_image.
|
||||
//Since we aren't sure of that in the case of overrides, use the less efficient
|
||||
|
@ -1168,7 +1158,7 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
highlight_ratio = deadAmount_;
|
||||
}
|
||||
|
||||
if(unit_image == NULL || energy_image == NULL || fogged(x,y) ||
|
||||
if(unit_image == NULL || fogged(x,y) ||
|
||||
(teams_[currentTeam_].is_enemy(it->second.side()) &&
|
||||
it->second.invisible(map_.underlying_terrain(map_[x][y]),
|
||||
status_.get_time_of_day().lawful_bonus,loc,
|
||||
|
@ -1192,8 +1182,6 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
highlight_ratio = 0.75;
|
||||
}
|
||||
|
||||
const bool energy_uses_alpha = highlight_ratio < 1.0 && blend_with == 0;
|
||||
|
||||
if(loc != hiddenUnit_) {
|
||||
scoped_sdl_surface ellipse_front(NULL);
|
||||
scoped_sdl_surface ellipse_back(NULL);
|
||||
|
@ -1210,6 +1198,23 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
highlight_ratio,blend_with,submerge,ellipse_back,ellipse_front);
|
||||
}
|
||||
|
||||
const double bar_alpha = highlight_ratio < 1.0 && blend_with == 0 ? highlight_ratio : 1.0;
|
||||
if(energy_file != NULL) {
|
||||
draw_bar(*energy_file,xpos,ypos,(u.max_hitpoints()*2)/3,unit_energy,energy_colour,bar_alpha);
|
||||
}
|
||||
|
||||
if(u.experience() > 0 && u.type().can_advance()) {
|
||||
const double filled = double(u.experience())/double(u.max_experience());
|
||||
const int level = maximum<int>(u.type().level(),1);
|
||||
const SDL_Color normal_colour = {200,200,0,0}, near_advance_colour = {255,255,255,0};
|
||||
const bool near_advance = u.max_experience() - u.experience() <= game_config::kill_experience*level;
|
||||
const SDL_Color colour = near_advance ? near_advance_colour : normal_colour;
|
||||
|
||||
draw_bar("enemy-energy.png",xpos+5,ypos,u.max_experience()/(level*2),filled,colour,bar_alpha);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
const SDL_Rect& energy_bar_loc = calculate_energy_bar();
|
||||
double total_energy = double(energy_bar_loc.h);
|
||||
|
||||
|
@ -1256,7 +1261,7 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
SDL_FillRect(dst,&filled_xp_area,xp_colour);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
const std::vector<std::string>& overlays = it->second.overlays();
|
||||
for(std::vector<std::string>::const_iterator ov = overlays.begin(); ov != overlays.end(); ++ov) {
|
||||
const scoped_sdl_surface img(image::get_image(*ov));
|
||||
|
@ -1268,6 +1273,46 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
}
|
||||
}
|
||||
|
||||
void display::draw_bar(const std::string& image, int xpos, int ypos, size_t height, double filled, const SDL_Color& col, double alpha)
|
||||
{
|
||||
filled = minimum<double>(maximum<double>(filled,0.0),1.0);
|
||||
|
||||
scoped_sdl_surface surf(image::get_image(image,image::SCALED,image::NO_ADJUST_COLOUR));
|
||||
scoped_sdl_surface unmoved_surf(image::get_image("unmoved-energy.png",image::SCALED,image::NO_ADJUST_COLOUR));
|
||||
if(surf == NULL || unmoved_surf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SDL_Rect& bar_loc = calculate_energy_bar(unmoved_surf);
|
||||
if(height > bar_loc.h) {
|
||||
height = bar_loc.h;
|
||||
}
|
||||
|
||||
if(alpha != 1.0) {
|
||||
surf.assign(adjust_surface_alpha(surf,alpha));
|
||||
if(surf == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t skip_rows = bar_loc.h - height;
|
||||
|
||||
SDL_Rect top = {0,0,surf->w,bar_loc.y};
|
||||
SDL_Rect bot = {0,bar_loc.y+skip_rows,surf->w,0};
|
||||
bot.h = surf->w - bot.y;
|
||||
|
||||
blit_surface(xpos,ypos,surf,&top);
|
||||
blit_surface(xpos,ypos+top.h,surf,&bot);
|
||||
|
||||
const size_t unfilled = height*(1.0 - filled);
|
||||
|
||||
if(unfilled < height) {
|
||||
SDL_Rect filled_area = {xpos+bar_loc.x,ypos+bar_loc.y+unfilled,bar_loc.w,height-unfilled};
|
||||
const Uint16 colour = SDL_MapRGB(video().getSurface()->format,col.r,col.g,col.b);
|
||||
SDL_FillRect(video().getSurface(),&filled_area,colour);
|
||||
}
|
||||
}
|
||||
|
||||
void display::draw_tile_adjacent(int x, int y, image::TYPE image_type, ADJACENT_TERRAIN_TYPE type)
|
||||
{
|
||||
const gamemap::location loc(x,y);
|
||||
|
@ -1874,16 +1919,16 @@ struct is_energy_colour {
|
|||
(colour&0x000000FF) > 0x00000099; }
|
||||
};
|
||||
|
||||
const SDL_Rect& display::calculate_energy_bar()
|
||||
const SDL_Rect& display::calculate_energy_bar(SDL_Surface* surf)
|
||||
{
|
||||
if(energy_bar_rect_.x != -1) {
|
||||
return energy_bar_rect_;
|
||||
const std::map<SDL_Surface*,SDL_Rect>::const_iterator i = energy_bar_rects_.find(surf);
|
||||
if(i != energy_bar_rects_.end()) {
|
||||
return i->second;
|
||||
}
|
||||
|
||||
int first_row = -1, last_row = -1, first_col = -1, last_col = -1;
|
||||
|
||||
scoped_sdl_surface image(image::get_image(game_config::unmoved_energy_image,image::SCALED));
|
||||
image.assign(make_neutral_surface(image));
|
||||
scoped_sdl_surface image(make_neutral_surface(surf));
|
||||
|
||||
surface_lock image_lock(image);
|
||||
const Uint32* const begin = image_lock.pixels();
|
||||
|
@ -1905,9 +1950,8 @@ const SDL_Rect& display::calculate_energy_bar()
|
|||
}
|
||||
|
||||
const SDL_Rect res = {first_col,first_row,last_col-first_col,last_row+1-first_row};
|
||||
|
||||
energy_bar_rect_ = res;
|
||||
return energy_bar_rect_;
|
||||
energy_bar_rects_.insert(std::pair<SDL_Surface*,SDL_Rect>(surf,res));
|
||||
return calculate_energy_bar(surf);
|
||||
}
|
||||
|
||||
void display::invalidate(const gamemap::location& loc)
|
||||
|
|
|
@ -372,10 +372,12 @@ private:
|
|||
|
||||
unit_map& units_;
|
||||
|
||||
void draw_bar(const std::string& image, int xpos, int ypos, size_t height, double filled, const SDL_Color& col, double alpha);
|
||||
|
||||
//function which finds the start and end rows on the energy bar image
|
||||
//where white pixels are substituted for the colour of the energy
|
||||
const SDL_Rect& calculate_energy_bar();
|
||||
SDL_Rect energy_bar_rect_;
|
||||
const SDL_Rect& calculate_energy_bar(SDL_Surface* surf);
|
||||
std::map<SDL_Surface*,SDL_Rect> energy_bar_rects_;
|
||||
|
||||
SDL_Surface* minimap_;
|
||||
bool redrawMinimap_;
|
||||
|
|
19
src/game.cpp
19
src/game.cpp
|
@ -586,7 +586,7 @@ int play_game(int argc, char** argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
side_parameters[side][name_value.front()] = name_value.back();
|
||||
side_parameters[side][name_value.front()] = name_value.back();
|
||||
} else {
|
||||
std::cerr << "unrecognized option: '" << name << "'\n";
|
||||
return 0;
|
||||
|
@ -632,7 +632,14 @@ int play_game(int argc, char** argv)
|
|||
|
||||
const config* side = type == side_types.end() ? era_cfg->child("multiplayer_side") :
|
||||
era_cfg->find_child("multiplayer_side","type",type->second);
|
||||
if(side == NULL) {
|
||||
|
||||
size_t tries = 0;
|
||||
while(side != NULL && (*side)["type"] == "random" && ++tries < 100) {
|
||||
const config::child_list& v = era_cfg->get_children("multiplayer_side");
|
||||
side = v[rand()%v.size()];
|
||||
}
|
||||
|
||||
if(side == NULL || (*side)["type"] == "random") {
|
||||
std::string side_name = (type == side_types.end() ? "default" : type->second);
|
||||
std::cerr << "Could not find side '" << side_name << "' for side " << side_num << "\n";
|
||||
return 0;
|
||||
|
@ -656,16 +663,22 @@ int play_game(int argc, char** argv)
|
|||
(*itors.first)->values["ai_algorithm"] = algorithm->second;
|
||||
}
|
||||
|
||||
config& ai_params = (*itors.first)->add_child("ai");
|
||||
|
||||
//now add in any arbitrary parameters given to the side
|
||||
for(string_map::const_iterator j = side_parameters[side_num].begin(); j != side_parameters[side_num].end(); ++j) {
|
||||
(*itors.first)->values[j->first] = j->second;
|
||||
ai_params[j->first] = j->second;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
play_level(units_data,game_config,&level,video,state,story);
|
||||
} catch(gamestatus::error& e) {
|
||||
std::cerr << "caught error: '" << e.message << "'\n";
|
||||
return 0;
|
||||
} catch(...) {
|
||||
std::cerr << "caught error playing level...\n";
|
||||
std::cerr << "caught unknown error playing level...\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,27 +63,30 @@ public:
|
|||
//has expired.
|
||||
bool next_turn();
|
||||
|
||||
//an exception object used when loading a game fails.
|
||||
struct load_game_failed {
|
||||
load_game_failed() {}
|
||||
load_game_failed(const std::string& msg) : message(msg) {}
|
||||
struct error {
|
||||
error() {}
|
||||
error(const std::string& msg) : message(msg)
|
||||
{}
|
||||
|
||||
std::string message;
|
||||
};
|
||||
|
||||
//an exception object used when saving a game fails.
|
||||
struct save_game_failed {
|
||||
save_game_failed() {}
|
||||
save_game_failed(const std::string& msg) : message(msg) {}
|
||||
//an exception object used when loading a game fails.
|
||||
struct load_game_failed : public error {
|
||||
load_game_failed() {}
|
||||
load_game_failed(const std::string& msg) : error("load_game_failed: " + msg) {}
|
||||
};
|
||||
|
||||
std::string message;
|
||||
//an exception object used when saving a game fails.
|
||||
struct save_game_failed : public error {
|
||||
save_game_failed() {}
|
||||
save_game_failed(const std::string& msg) : error("save_game_failed: " + msg) {}
|
||||
};
|
||||
|
||||
//an exception object used for any general game error.
|
||||
//e.g. data files are corrupt.
|
||||
struct game_error {
|
||||
game_error(const std::string& msg) : message(msg) {}
|
||||
std::string message;
|
||||
struct game_error : public error {
|
||||
game_error(const std::string& msg) : error("game_error: " + msg) {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -508,6 +508,8 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
|
|||
movementType_.set_parent(&(it->second));
|
||||
}
|
||||
|
||||
can_advance_ = advances_to().empty() == false;
|
||||
|
||||
//check if the images necessary for units exist
|
||||
#ifdef linux
|
||||
struct stat stat_buf;
|
||||
|
@ -794,6 +796,11 @@ bool unit_type::not_living() const
|
|||
return race_->not_living();
|
||||
}
|
||||
|
||||
bool unit_type::can_advance() const
|
||||
{
|
||||
return can_advance_;
|
||||
}
|
||||
|
||||
bool unit_type::has_ability(const std::string& ability) const
|
||||
{
|
||||
return std::find(abilities_.begin(),abilities_.end(),ability) != abilities_.end();
|
||||
|
|
|
@ -203,6 +203,7 @@ public:
|
|||
bool teleports() const;
|
||||
bool nightvision() const;
|
||||
bool not_living() const;
|
||||
bool can_advance() const;
|
||||
|
||||
bool has_ability(const std::string& ability) const;
|
||||
|
||||
|
@ -229,6 +230,7 @@ private:
|
|||
bool skirmish_;
|
||||
bool teleport_;
|
||||
bool nightvision_;
|
||||
bool can_advance_;
|
||||
|
||||
unit_movement_type movementType_;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue