converted hex calculations to fixed point instead of floating point

This commit is contained in:
Dave White 2004-04-28 15:26:42 +00:00
parent 7c6ecec04e
commit 2c78051d25
6 changed files with 101 additions and 110 deletions

View file

@ -41,7 +41,8 @@
std::map<gamemap::location,double> display::debugHighlights_;
namespace {
const double DefaultZoom = 70.0;
const int DefaultZoom = 70;
const int MaxZoom = 200;
const size_t SideBarGameStatus_x = 16;
const size_t SideBarGameStatus_y = 220;
@ -52,7 +53,7 @@ namespace {
display::display(unit_map& units, CVideo& video, const gamemap& map,
const gamestatus& status, const std::vector<team>& t, const config& theme_cfg,
const config& built_terrains)
: screen_(video), xpos_(0.0), ypos_(0.0),
: screen_(video), xpos_(0), ypos_(0),
zoom_(DefaultZoom), map_(map), units_(units),
minimap_(NULL), redrawMinimap_(false),
pathsList_(NULL), status_(status),
@ -227,34 +228,29 @@ void display::highlight_hex(gamemap::location hex)
gamemap::location display::hex_clicked_on(int xclick, int yclick)
{
const SDL_Rect& rect = map_area();
if(xclick < rect.x || xclick >= rect.x + rect.w ||
yclick < rect.y || yclick >= rect.y + rect.h)
if(point_in_rect(xclick,yclick,rect) == false) {
return gamemap::location();
}
xclick -= rect.x;
yclick -= rect.y;
const int tile_width = static_cast<int>(static_cast<int>(zoom_)*0.75) + 1;
const int tile_width = hex_width();
const double xtile = xpos_/tile_width +
static_cast<double>(xclick)/tile_width - 0.25;
const double ytile = ypos_/zoom_ + static_cast<double>(yclick)/zoom_
+ (is_odd(int(xtile)) ? -0.5:0.0);
const int xtile = (xpos_ + xclick)/tile_width;
const int ytile = (ypos_ + yclick - (is_odd(xtile) ? zoom_/2 : 0))/zoom_; //(yclick + is_odd(xtile) ? -yclick/2 : 0)/zoom_;
return gamemap::location(static_cast<int>(xtile),static_cast<int>(ytile));
return gamemap::location(xtile,ytile);
}
double display::get_location_x(const gamemap::location& loc) const
int display::get_location_x(const gamemap::location& loc) const
{
const int tile_width = static_cast<int>(static_cast<int>(zoom_)*0.75) + 1;
return map_area().x + loc.x*tile_width - xpos_;
return map_area().x + loc.x*hex_width() - xpos_;
}
double display::get_location_y(const gamemap::location& loc) const
int display::get_location_y(const gamemap::location& loc) const
{
return map_area().y + static_cast<double>(loc.y)*zoom_ - ypos_ +
(is_odd(loc.x) ? zoom_/2.0 : 0.0);
return map_area().y + loc.y*zoom_ - ypos_ + (is_odd(loc.x) ? zoom_/2 : 0);
}
gamemap::location display::minimap_location_on(int x, int y)
@ -272,20 +268,14 @@ gamemap::location display::minimap_location_on(int x, int y)
return gamemap::location(int((x - rect.x)/xdiv),int((y-rect.y)/ydiv));
}
void display::scroll(double xmove, double ymove)
void display::scroll(int xmove, int ymove)
{
const double orig_x = xpos_;
const double orig_y = ypos_;
const int orig_x = xpos_;
const int orig_y = ypos_;
xpos_ += xmove;
ypos_ += ymove;
bounds_check_position();
if(int(util::round(xpos_)) == int(util::round(orig_x)))
xpos_ = orig_x;
if(int(util::round(ypos_)) == int(util::round(orig_y)))
ypos_ = orig_y;
//only invalidate if we've actually moved
if(orig_x != xpos_ || orig_y != ypos_) {
map_labels_.scroll(orig_x - xpos_, orig_y - ypos_);
@ -295,30 +285,34 @@ void display::scroll(double xmove, double ymove)
int display::hex_size() const
{
return int(zoom_);
return zoom_;
}
double display::zoom(double amount)
int display::hex_width() const
{
if(amount == 0.0) {
return zoom_/DefaultZoom;
return (zoom_*3)/4;
}
double display::zoom(int amount)
{
if(amount == 0) {
return double(zoom_)/double(DefaultZoom);
}
const double orig_xpos = xpos_;
const double orig_ypos = ypos_;
const int orig_xpos = xpos_;
const int orig_ypos = ypos_;
xpos_ /= zoom_;
ypos_ /= zoom_;
const double max_zoom = 200.0;
const double orig_zoom = zoom_;
const int orig_zoom = zoom_;
zoom_ += amount;
if(zoom_ > max_zoom) {
if(zoom_ > MaxZoom) {
zoom_ = orig_zoom;
xpos_ = orig_xpos;
ypos_ = orig_ypos;
return zoom_/DefaultZoom;
return double(zoom_)/double(DefaultZoom);
}
xpos_ *= zoom_;
@ -327,7 +321,7 @@ double display::zoom(double amount)
xpos_ += amount*2;
ypos_ += amount*2;
const double prev_zoom = zoom_;
const int prev_zoom = zoom_;
bounds_check_position();
@ -335,16 +329,18 @@ double display::zoom(double amount)
xpos_ = orig_xpos;
ypos_ = orig_ypos;
zoom_ = orig_zoom;
return zoom_/DefaultZoom;
return double(zoom_)/double(DefaultZoom);
}
energy_bar_rect_.x = -1;
std::cerr << "zoomed to: " << zoom_ << "\n";
image::set_zoom(zoom_);
map_labels_.recalculate_labels();
invalidate_all();
return zoom_/DefaultZoom;
return double(zoom_)/double(DefaultZoom);
}
void display::default_zoom()
@ -357,47 +353,38 @@ void display::scroll_to_tile(int x, int y, SCROLL_TYPE scroll_type, bool check_f
if(update_locked() || (check_fogged && fogged(x,y)))
return;
if(map_.on_board(gamemap::location(x,y)) == false)
const gamemap::location loc(x,y);
if(map_.on_board(loc) == false)
return;
const double xpos = static_cast<double>(x)*zoom_*0.75 - xpos_;
const double ypos = static_cast<double>(y)*zoom_ - ypos_ +
((x % 2) == 1 ? zoom_/2.0 : 0.0);
const int xpos = get_location_x(loc);
const int ypos = get_location_y(loc);
const double speed = preferences::scroll_speed()*2.0;
const int speed = preferences::scroll_speed()*2;
const SDL_Rect& area = map_area();
const double desiredxpos = area.w/2.0 - zoom_/2.0;
const double desiredypos = area.h/2.0 - zoom_/2.0;
const int desiredxpos = area.w/2 - zoom_/2;
const int desiredypos = area.h/2 - zoom_/2;
const double xmove = xpos - desiredxpos;
const double ymove = ypos - desiredypos;
const int xmove = xpos - desiredxpos;
const int ymove = ypos - desiredypos;
int num_moves = static_cast<int>((fabs(xmove) > fabs(ymove) ?
fabs(xmove):fabs(ymove))/speed);
int num_moves = (abs(xmove) > abs(ymove) ? abs(xmove):abs(ymove))/speed;
if(scroll_type == WARP || turbo())
num_moves = 1;
const double divisor = static_cast<double>(num_moves);
double xdiff = 0.0, ydiff = 0.0;
for(int i = 0; i != num_moves; ++i) {
events::pump();
xdiff += xmove/divisor;
ydiff += ymove/divisor;
//accelerate scroll rate if either shift key is held down
if((i%4) != 0 && i != num_moves-1 && turbo()) {
continue;
}
scroll(xdiff,ydiff);
scroll(xmove/num_moves,ymove/num_moves);
draw();
xdiff = 0.0;
ydiff = 0.0;
}
invalidate_all();
@ -407,17 +394,16 @@ void display::scroll_to_tile(int x, int y, SCROLL_TYPE scroll_type, bool check_f
void display::scroll_to_tiles(int x1, int y1, int x2, int y2,
SCROLL_TYPE scroll_type, bool check_fogged)
{
const double xpos1 = static_cast<double>(x1)*zoom_*0.75 - xpos_;
const double ypos1 = static_cast<double>(y1)*zoom_ - ypos_ +
((x1 % 2) == 1 ? zoom_/2.0 : 0.0);
const double xpos2 = static_cast<double>(x2)*zoom_*0.75 - xpos_;
const double ypos2 = static_cast<double>(y2)*zoom_ - ypos_ +
((x2 % 2) == 1 ? zoom_/2.0 : 0.0);
const gamemap::location loc1(x1,y1), loc2(x2,y2);
const int xpos1 = get_location_x(loc1);
const int ypos1 = get_location_y(loc1);
const int xpos2 = get_location_x(loc2);;
const int ypos2 = get_location_y(loc2);;
const double diffx = fabs(xpos1 - xpos2);
const double diffy = fabs(ypos1 - ypos2);
const int diffx = abs(xpos1 - xpos2);
const int diffy = abs(ypos1 - ypos2);
if(diffx > map_area().w/(zoom_*0.75) || diffy > map_area().h/zoom_) {
if(diffx > map_area().w/hex_width() || diffy > map_area().h/zoom_) {
scroll_to_tile(x1,y1,scroll_type,check_fogged);
} else {
scroll_to_tile((x1+x2)/2,(y1+y2)/2,scroll_type,check_fogged);
@ -426,41 +412,38 @@ void display::scroll_to_tiles(int x1, int y1, int x2, int y2,
void display::bounds_check_position()
{
const double min_zoom1 = static_cast<double>(map_area().w/(map_.x()*0.75 + 0.25));
const double min_zoom2 = static_cast<double>(map_area().h/map_.y());
const double min_zoom = ceil(maximum<double>(min_zoom1,min_zoom2)/5.0)*5.0;
const double max_zoom = 200.0;
const int min_zoom1 = map_area().w/((map_.x()*3)/4);
const int min_zoom2 = map_area().h/map_.y();
const int min_zoom = maximum<int>(min_zoom1,min_zoom2);
const int orig_zoom = int(zoom_);
zoom_ = floor(zoom_);
const int orig_zoom = zoom_;
if(zoom_ < min_zoom) {
zoom_ = min_zoom;
}
if(zoom_ > max_zoom) {
zoom_ = max_zoom;
if(zoom_ > MaxZoom) {
zoom_ = MaxZoom;
}
const int tile_width = static_cast<int>(static_cast<int>(zoom_)*0.75) + 1;
const int tile_width = hex_width();
const double xend = tile_width*map_.x() + tile_width/3;
const double yend = zoom_*map_.y() + zoom_/2.0;
const int xend = tile_width*map_.x() + tile_width/3;
const int yend = zoom_*map_.y() + zoom_/2;
if(xpos_ + static_cast<double>(map_area().w) > xend)
xpos_ -= xpos_ + static_cast<double>(map_area().w) - xend;
if(xpos_ + map_area().w > xend)
xpos_ -= xpos_ + map_area().w - xend;
if(ypos_ + static_cast<double>(map_area().h) > yend)
ypos_ -= ypos_ + static_cast<double>(map_area().h) - yend;
if(ypos_ + map_area().h > yend)
ypos_ -= ypos_ + map_area().h - yend;
if(xpos_ < 0.0)
xpos_ = 0.0;
if(xpos_ < 0)
xpos_ = 0;
if(ypos_ < 0.0)
ypos_ = 0.0;
if(ypos_ < 0)
ypos_ = 0;
if(int(zoom_) != orig_zoom)
if(zoom_ != orig_zoom)
image::set_zoom(zoom_);
}
@ -1074,13 +1057,13 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
return;
const gamemap::location loc(x,y);
int xpos = int(get_location_x(loc));
int ypos = int(get_location_y(loc));
int xpos = get_location_x(loc);
int ypos = 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 + static_cast<int>(zoom_) < clip_rect.x || ypos + static_cast<int>(zoom_) < clip_rect.y) {
xpos + zoom_ < clip_rect.x || ypos + zoom_ < clip_rect.y) {
return;
}
@ -1209,7 +1192,7 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
}
const gamemap::TERRAIN terrain = map_.get_terrain(loc);
const int height_adjust = it->second.is_flying() ? 0 : int(map_.get_terrain_info(terrain).unit_height_adjust()*(zoom_/DefaultZoom));
const int height_adjust = it->second.is_flying() ? 0 : int(map_.get_terrain_info(terrain).unit_height_adjust()*zoom());
const double submerge = it->second.is_flying() ? 0.0 : map_.get_terrain_info(terrain).unit_submerge();
if(loc == advancingUnit_ && it != units_.end()) {
@ -1278,7 +1261,7 @@ void display::draw_tile_adjacent(int x, int y, image::TYPE image_type, ADJACENT_
SDL_Rect clip_rect = map_area();
if(xpos > clip_rect.x + clip_rect.w || ypos > clip_rect.y + clip_rect.h ||
xpos + static_cast<int>(zoom_) < clip_rect.x || ypos + static_cast<int>(zoom_) < clip_rect.y) {
xpos + zoom_ < clip_rect.x || ypos + zoom_ < clip_rect.y) {
return;
}
@ -1314,7 +1297,7 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image, double alpha, Uin
SDL_Rect clip_rect = map_area();
if(xpos >= clip_rect.x + clip_rect.w || ypos >= clip_rect.y + clip_rect.h ||
xpos + static_cast<int>(zoom_) < clip_rect.x || ypos + static_cast<int>(zoom_) < clip_rect.y) {
xpos + zoom_ < clip_rect.x || ypos + zoom_ < clip_rect.y) {
return;
}
@ -1522,8 +1505,8 @@ void display::draw_footstep(const gamemap::location& loc, int xloc, int yloc)
std::string str(1,'x');
str[0] = '1' + route_.move_left;
const SDL_Rect& text_area = font::draw_text(NULL,rect,18,text_colour,str,0,0);
const int x = xloc + int(zoom_/2.0) - text_area.w/2;
const int y = yloc + int(zoom_/2.0) - text_area.h/2;
const int x = xloc + zoom_/2 - text_area.w/2;
const int y = yloc + zoom_/2 - text_area.h/2;
font::draw_text(this,rect,18,text_colour,str,x,y);
}
}
@ -1805,7 +1788,7 @@ void display::float_label(const gamemap::location& loc, const std::string& text,
}
const SDL_Color colour = {red,green,blue,255};
font::add_floating_label(text,24,colour,get_location_x(loc)+zoom_*0.5,get_location_y(loc),
font::add_floating_label(text,24,colour,get_location_x(loc)+zoom_/2,get_location_y(loc),
0,-2,60,screen_area());
}

View file

@ -76,11 +76,11 @@ public:
//function which scrolls the display by xmov,ymov. Invalidation and
//redrawing will be scheduled.
void scroll(double xmov, double ymov);
void scroll(int xmov, int ymov);
//function which zooms the display by the specified amount. Negative
//valeus zoom out. Returns the current zoom ratio
double zoom(double amount=0.0);
//values zoom out. Returns the current zoom ratio
double zoom(int amount=0);
//function to take the zoom amount to the default.
void default_zoom();
@ -89,6 +89,8 @@ public:
//(from top tip to bottom tip or left edge to right edge)
int hex_size() const;
int hex_width() const;
enum SCROLL_TYPE { SCROLL, WARP };
//function which will scroll such that location x,y is on-screen.
@ -153,8 +155,8 @@ public:
void set_route(const paths::route* route);
//functions to get the on-screen positions of hexes.
double get_location_x(const gamemap::location& loc) const;
double get_location_y(const gamemap::location& loc) const;
int get_location_x(const gamemap::location& loc) const;
int get_location_y(const gamemap::location& loc) const;
//function to remove a footstep from a specific location
void remove_footstep(const gamemap::location& loc);
@ -348,7 +350,7 @@ private:
CVideo& screen_;
mutable CKey keys_;
double xpos_, ypos_, zoom_;
int xpos_, ypos_, zoom_;
const gamemap& map_;
gamemap::location selectedHex_;

View file

@ -28,7 +28,7 @@ std::string image_mask;
SDL_PixelFormat* pixel_format = NULL;
double zoom = 70.0;
int zoom = 70;
//we have to go through all this trickery on clear_surfaces because
//some compilers don't support 'typename type::iterator'
@ -147,7 +147,7 @@ void set_image_mask(const std::string& image)
}
void set_zoom(double amount)
void set_zoom(int amount)
{
if(amount != zoom) {
zoom = amount;
@ -226,8 +226,7 @@ SDL_Surface* get_image(const std::string& filename, TYPE type, COLOUR_ADJUSTMENT
result = i->second;
} else {
const int z = static_cast<int>(zoom);
const scoped_sdl_surface scaled_surf(scale_surface(i->second,z,z));
const scoped_sdl_surface scaled_surf(scale_surface(i->second,zoom,zoom));
if(scaled_surf == NULL) {
return NULL;

View file

@ -55,7 +55,7 @@ namespace image {
///sets the amount scaled images should be scaled. Invalidates all
///scaled images.
void set_zoom(double zoom);
void set_zoom(int zoom);
enum TYPE { UNSCALED, SCALED, UNMASKED, GREYED, BRIGHTENED };

View file

@ -22,6 +22,11 @@
#include "util.hpp"
#include "video.hpp"
bool point_in_rect(int x, int y, const SDL_Rect& rect)
{
return x >= rect.x && y >= rect.y && x < rect.x + rect.w && y < rect.y + rect.h;
}
namespace {
SDL_PixelFormat& get_neutral_pixel_format()
{

View file

@ -33,6 +33,8 @@
#define SDL_BUTTON_WHEELDOWN 5
#endif
bool point_in_rect(int x, int y, const SDL_Rect& rect);
struct free_sdl_surface {
void operator()(SDL_Surface* surface) const { SDL_FreeSurface(surface); }
};