Lift the lower end of the terrain-tile drawing code.

This commit is contained in:
Eric S. Raymond 2007-06-23 20:58:51 +00:00
parent beb9db4c82
commit c29be324fc
2 changed files with 190 additions and 183 deletions

View file

@ -379,6 +379,171 @@ gui::button::TYPE map_display::string_to_button_type(std::string type)
return res;
}
static const std::string& get_direction(size_t n)
{
static std::string const dirs[6] = { "-n", "-ne", "-se", "-s", "-sw", "-nw" };
return dirs[n >= sizeof(dirs)/sizeof(*dirs) ? 0 : n];
}
std::vector<std::string> map_display::get_fog_shroud_graphics(const gamemap::location& loc)
{
std::vector<std::string> res;
gamemap::location adjacent[6];
get_adjacent_tiles(loc,adjacent);
t_translation::t_letter tiles[6];
static const t_translation::t_letter terrain_types[] =
{ t_translation::FOGGED, t_translation::VOID_TERRAIN, t_translation::NONE_TERRAIN };
for(int i = 0; i != 6; ++i) {
if(shrouded(adjacent[i])) {
tiles[i] = t_translation::VOID_TERRAIN;
} else if(!fogged(loc) && fogged(adjacent[i])) {
tiles[i] = t_translation::FOGGED;
} else {
tiles[i] = t_translation::NONE_TERRAIN;
}
}
for(const t_translation::t_letter *terrain = terrain_types;
*terrain != t_translation::NONE_TERRAIN; terrain ++) {
//find somewhere that doesn't have overlap to use as a starting point
int start;
for(start = 0; start != 6; ++start) {
if(tiles[start] != *terrain) {
break;
}
}
if(start == 6) {
start = 0;
}
//find all the directions overlap occurs from
for(int i = (start+1)%6, n = 0; i != start && n != 6; ++n) {
if(tiles[i] == *terrain) {
std::ostringstream stream;
std::string name;
// if(*terrain == terrain_type::VOID_TERRAIN)
// stream << "void";
//else
// stream << "fog";
stream << "terrain/" << map_.get_terrain_info(*terrain).symbol_image();
for(int n = 0; *terrain == tiles[i] && n != 6; i = (i+1)%6, ++n) {
stream << get_direction(i);
if(!image::exists(stream.str() + ".png")) {
//if we don't have any surface at all,
//then move onto the next overlapped area
if(name.empty()) {
i = (i+1)%6;
}
break;
} else {
name = stream.str();
}
}
if(!name.empty()) {
res.push_back(name + ".png");
}
} else {
i = (i+1)%6;
}
}
}
return res;
}
std::vector<surface> map_display::get_terrain_images(const gamemap::location &loc,
const time_of_day& tod,
image::TYPE image_type,
ADJACENT_TERRAIN_TYPE terrain_type)
{
std::vector<surface> res;
if(terrain_type == ADJACENT_FOGSHROUD) {
const std::vector<std::string> fog_shroud = get_fog_shroud_graphics(loc);
if(!fog_shroud.empty()) {
for(std::vector<std::string>::const_iterator it = fog_shroud.begin(); it != fog_shroud.end(); ++it) {
image::locator image(*it);
// image.filename = "terrain/" + *it;
const surface surface(image::get_image(image, image_type));
if (!surface.null()) {
res.push_back(surface);
}
}
}
return res;
}
terrain_builder::ADJACENT_TERRAIN_TYPE builder_terrain_type =
(terrain_type == ADJACENT_FOREGROUND ?
terrain_builder::ADJACENT_FOREGROUND : terrain_builder::ADJACENT_BACKGROUND);
const terrain_builder::imagelist* const terrains = builder_.get_terrain_at(loc,
tod.id, builder_terrain_type);
if(terrains != NULL) {
for(std::vector<animated<image::locator> >::const_iterator it = terrains->begin(); it != terrains->end(); ++it) {
// it->update_current_frame();
image::locator image = it->get_current_frame();
// image.filename = "terrain/" + image.filename;
const surface surface(image::get_image(image, image_type));
if (!surface.null()) {
res.push_back(surface);
}
}
} else if(terrain_type == ADJACENT_BACKGROUND){
// this should only happen with the off map tiles and now
// return the void image. NOTE this is a temp hack
const surface surface(image::get_image("terrain/off-map/alpha.png"));
wassert(!surface.null());
if (!surface.null()) {
res.push_back(surface);
}
}
return res;
}
void map_display::draw_terrain_on_tile(const gamemap::location& loc,
const time_of_day& tod,
image::TYPE image_type,
ADJACENT_TERRAIN_TYPE type)
{
int xpos = int(get_location_x(loc));
int ypos = int(get_location_y(loc));
SDL_Rect clip_rect = map_area();
if(xpos > clip_rect.x + clip_rect.w || ypos > clip_rect.y + clip_rect.h ||
xpos + zoom_ < clip_rect.x || ypos + zoom_ < clip_rect.y) {
return;
}
surface const dst(screen_.getSurface());
clip_rect_setter set_clip_rect(dst,clip_rect);
const std::vector<surface>& images = get_terrain_images(loc,tod,image_type,type);
std::vector<surface>::const_iterator itor;
for(itor = images.begin(); itor != images.end(); ++itor) {
SDL_Rect dstrect = { xpos, ypos, 0, 0 };
SDL_BlitSurface(*itor,NULL,dst,&dstrect);
}
}
// Methods for superclass aware of units go here
std::map<gamemap::location,fixed_t> display::debugHighlights_;
@ -1002,6 +1167,7 @@ static void draw_background(surface screen, const SDL_Rect& area)
void display::draw(bool update,bool force)
{
bool changed = false;
//log_scope("Drawing");
invalidate_animations();
@ -1076,7 +1242,9 @@ void display::draw(bool update,bool force)
if (units_.find(*it) != units_.end()) {
unit_invals.insert(*it);
}
draw_tile(*it, clip_rect);
const time_of_day& tod = status_.get_time_of_day();
const time_of_day& tod_at = timeofday_at(status_,units_,*it,map_);
draw_tile(*it, tod, tod_at, clip_rect);
simulate_delay += 1;
}
@ -1562,32 +1730,7 @@ void display::draw_bar(const std::string& image, int xpos, int ypos, size_t heig
}
}
void display::draw_terrain_on_tile(const gamemap::location& loc, image::TYPE image_type, ADJACENT_TERRAIN_TYPE type)
{
int xpos = int(get_location_x(loc));
int ypos = int(get_location_y(loc));
SDL_Rect clip_rect = map_area();
if(xpos > clip_rect.x + clip_rect.w || ypos > clip_rect.y + clip_rect.h ||
xpos + zoom_ < clip_rect.x || ypos + zoom_ < clip_rect.y) {
return;
}
surface const dst(screen_.getSurface());
clip_rect_setter set_clip_rect(dst,clip_rect);
const std::vector<surface>& images = get_terrain_images(loc,image_type,type);
std::vector<surface>::const_iterator itor;
for(itor = images.begin(); itor != images.end(); ++itor) {
SDL_Rect dstrect = { xpos, ypos, 0, 0 };
SDL_BlitSurface(*itor,NULL,dst,&dstrect);
}
}
void display::draw_tile(const gamemap::location &loc, const SDL_Rect &clip_rect)
void display::draw_tile(const gamemap::location &loc, const time_of_day& tod, const time_of_day & tod_at, const SDL_Rect &clip_rect)
{
if(screen_.update_locked()) {
return;
@ -1620,8 +1763,6 @@ void display::draw_tile(const gamemap::location &loc, const SDL_Rect &clip_rect)
image::TYPE image_type = image::SCALED_TO_HEX;
const time_of_day& tod = status_.get_time_of_day();
const time_of_day& tod_at = timeofday_at(status_,units_,loc,map_);
std::string mask = tod_at.image_mask;
if(tod_hex_mask1 != NULL || tod_hex_mask2 != NULL || tod.image_mask != tod_at.image_mask) {
image_type = image::SCALED_TO_HEX;
@ -1640,7 +1781,7 @@ void display::draw_tile(const gamemap::location &loc, const SDL_Rect &clip_rect)
}
if(!is_shrouded /*|| !on_map*/) {
draw_terrain_on_tile(loc,image_type,ADJACENT_BACKGROUND);
draw_terrain_on_tile(loc, tod, image_type, ADJACENT_BACKGROUND);
surface flag(get_flag(terrain,loc));
if(flag != NULL) {
@ -1679,7 +1820,7 @@ void display::draw_tile(const gamemap::location &loc, const SDL_Rect &clip_rect)
draw_footstep(loc,xpos,ypos);
if(!is_shrouded /*|| !on_map*/) {
draw_terrain_on_tile(loc,image_type,ADJACENT_FOREGROUND);
draw_terrain_on_tile(loc,tod,image_type,ADJACENT_FOREGROUND);
}
if(fogged(loc) && on_map && !is_shrouded) {
@ -1691,7 +1832,7 @@ void display::draw_tile(const gamemap::location &loc, const SDL_Rect &clip_rect)
}
if(!is_shrouded && on_map) {
draw_terrain_on_tile(loc,image_type,ADJACENT_FOGSHROUD);
draw_terrain_on_tile(loc,tod,image_type,ADJACENT_FOGSHROUD);
}
//draw the time-of-day mask on top of the hex
@ -1920,146 +2061,6 @@ void display::draw_movement_info(const gamemap::location& loc)
}
}
static const std::string& get_direction(size_t n)
{
static std::string const dirs[6] = { "-n", "-ne", "-se", "-s", "-sw", "-nw" };
return dirs[n >= sizeof(dirs)/sizeof(*dirs) ? 0 : n];
}
std::vector<std::string> display::get_fog_shroud_graphics(const gamemap::location& loc)
{
std::vector<std::string> res;
gamemap::location adjacent[6];
get_adjacent_tiles(loc,adjacent);
t_translation::t_letter tiles[6];
static const t_translation::t_letter terrain_types[] =
{ t_translation::FOGGED, t_translation::VOID_TERRAIN, t_translation::NONE_TERRAIN };
for(int i = 0; i != 6; ++i) {
if(shrouded(adjacent[i])) {
tiles[i] = t_translation::VOID_TERRAIN;
} else if(!fogged(loc) && fogged(adjacent[i])) {
tiles[i] = t_translation::FOGGED;
} else {
tiles[i] = t_translation::NONE_TERRAIN;
}
}
for(const t_translation::t_letter *terrain = terrain_types;
*terrain != t_translation::NONE_TERRAIN; terrain ++) {
//find somewhere that doesn't have overlap to use as a starting point
int start;
for(start = 0; start != 6; ++start) {
if(tiles[start] != *terrain) {
break;
}
}
if(start == 6) {
start = 0;
}
//find all the directions overlap occurs from
for(int i = (start+1)%6, n = 0; i != start && n != 6; ++n) {
if(tiles[i] == *terrain) {
std::ostringstream stream;
std::string name;
// if(*terrain == terrain_type::VOID_TERRAIN)
// stream << "void";
//else
// stream << "fog";
stream << "terrain/" << map_.get_terrain_info(*terrain).symbol_image();
for(int n = 0; *terrain == tiles[i] && n != 6; i = (i+1)%6, ++n) {
stream << get_direction(i);
if(!image::exists(stream.str() + ".png")) {
//if we don't have any surface at all,
//then move onto the next overlapped area
if(name.empty()) {
i = (i+1)%6;
}
break;
} else {
name = stream.str();
}
}
if(!name.empty()) {
res.push_back(name + ".png");
}
} else {
i = (i+1)%6;
}
}
}
return res;
}
std::vector<surface> display::get_terrain_images(const gamemap::location &loc,
image::TYPE image_type, ADJACENT_TERRAIN_TYPE terrain_type)
{
std::vector<surface> res;
if(terrain_type == ADJACENT_FOGSHROUD) {
const std::vector<std::string> fog_shroud = get_fog_shroud_graphics(loc);
if(!fog_shroud.empty()) {
for(std::vector<std::string>::const_iterator it = fog_shroud.begin(); it != fog_shroud.end(); ++it) {
image::locator image(*it);
// image.filename = "terrain/" + *it;
const surface surface(image::get_image(image, image_type));
if (!surface.null()) {
res.push_back(surface);
}
}
}
return res;
}
const time_of_day& tod = status_.get_time_of_day();
// const time_of_day& tod_at = timeofday_at(status_,units_,gamemap::location(x,y));
terrain_builder::ADJACENT_TERRAIN_TYPE builder_terrain_type =
(terrain_type == ADJACENT_FOREGROUND ?
terrain_builder::ADJACENT_FOREGROUND : terrain_builder::ADJACENT_BACKGROUND);
const terrain_builder::imagelist* const terrains = builder_.get_terrain_at(loc,
tod.id, builder_terrain_type);
if(terrains != NULL) {
for(std::vector<animated<image::locator> >::const_iterator it = terrains->begin(); it != terrains->end(); ++it) {
// it->update_current_frame();
image::locator image = it->get_current_frame();
// image.filename = "terrain/" + image.filename;
const surface surface(image::get_image(image, image_type));
if (!surface.null()) {
res.push_back(surface);
}
}
} else if(terrain_type == ADJACENT_BACKGROUND){
// this should only happen with the off map tiles and now
// return the void image. NOTE this is a temp hack
const surface surface(image::get_image("terrain/off-map/alpha.png"));
wassert(!surface.null());
if (!surface.null()) {
res.push_back(surface);
}
}
return res;
}
surface display::get_flag(const t_translation::t_letter& terrain, const gamemap::location& loc)
{
if(!map_.is_village(terrain)) {

View file

@ -144,6 +144,17 @@ public:
// Will be overridden in the display subclass
bool fogged(const gamemap::location& loc UNUSED) const {return false;};
bool shrouded(const gamemap::location& loc UNUSED) const {return false;};
protected:
enum ADJACENT_TERRAIN_TYPE { ADJACENT_BACKGROUND, ADJACENT_FOREGROUND, ADJACENT_FOGSHROUD };
std::vector<surface> get_terrain_images(const gamemap::location &loc,
const time_of_day& tod,
image::TYPE type,
ADJACENT_TERRAIN_TYPE terrain_type);
std::vector<std::string> get_fog_shroud_graphics(const gamemap::location& loc);
protected:
CVideo& screen_;
@ -158,6 +169,11 @@ protected:
// Not set by the initializer
std::vector<gui::button> buttons_;
//composes and draws the terrains on a tile
void draw_terrain_on_tile(const gamemap::location& loc,
const time_of_day& tod,
image::TYPE image_type,
ADJACENT_TERRAIN_TYPE type);
};
class display : public map_display
@ -283,11 +299,6 @@ public:
void clear_mouseover_hex_overlay() { mouseover_hex_overlay_ = NULL; }
private:
enum ADJACENT_TERRAIN_TYPE { ADJACENT_BACKGROUND, ADJACENT_FOREGROUND, ADJACENT_FOGSHROUD };
//composes and draws the terrains on a tile
void draw_terrain_on_tile(const gamemap::location& loc, image::TYPE image_type, ADJACENT_TERRAIN_TYPE type);
// event raised when the map is being scrolled
mutable events::generic_event _scroll_event;
@ -465,7 +476,7 @@ private:
display(const display&);
void operator=(const display&);
void draw_tile(const gamemap::location &loc, const SDL_Rect &clip_rect);
void draw_tile(const gamemap::location &loc, const time_of_day& tod, const time_of_day& tod_at, const SDL_Rect &clip_rect);
void draw_sidebar();
void draw_minimap(int x, int y, int w, int h);
void draw_game_status();
@ -479,11 +490,6 @@ private:
void bounds_check_position();
void bounds_check_position(int& xpos, int& ypos);
std::vector<surface> get_terrain_images(const gamemap::location &loc,
image::TYPE type, ADJACENT_TERRAIN_TYPE terrain_type);
std::vector<std::string> get_fog_shroud_graphics(const gamemap::location& loc);
//this surface must be freed by the caller
surface get_flag(const t_translation::t_letter& terrain, const gamemap::location& loc);