than 80x24. Also allow moving the PC around the viewport without scrolling the viewport if the viewport is large enough.
This is not tested on DOS and Windows yet.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1524 c06c8d41-db1a-0410-9941-cceddc491573
EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC
KTNZIWQ7HRC2YKQEQ5SAM3UOYJPJY5JGWKMFGALBPRDZUJSFH2YQC
B4X67DGLW77QLGPTMORE2EJ5K5VA3TWIU23HFUF4TZDODXQSFLRQC
CTTZKXEF5P64ZO2UNJZIAKKZH7ZWZ54C5E27ATXKGZJFRJJC6FJAC
SVKXVPIRSLANKYBFFZ5OTGQAB6GXSLSMGQEBWAE7ATSITBACOCFQC
DTLQUII6XUFN6LMIOFGUX2MVWYJ22UKCFQGFXVR3CPTODFIEANNQC
SCNVGV5WCDZK5OAJBYCAGSINHGIDANF3WXQCM5JVITL2I6RWMLMAC
2B4AQJIATJ4E7RFN6OTQITZNDBAPQ2VWWXLBCVYSORAFG2GIIDNQC
CEK6M777MI5JVDC3KHE3JD3FETVSJ4VN6DGATBI5P3O6P5XHY4DAC
XYJ5Y635KCRCTL2BFPP53NWQRK3NUHS6T3ARPIXV5A3CHWBW7VCQC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
TZ643KHSE5CUPXFSQ7VYVOCM5MTQ7F4SENEYQX2RNFHGHLQVS3RQC
GCIZIUXO5TYROKDUYB3HAY7H7MRDTJNM7HR7DGSH7KXDIZC2LCDAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
GVCGKTH5IJ4VSQEIN4CRC7ZFVZW26JPIYNCPTO7GY66CSZZEW3ZQC
ASFH3NFXSJ6AWVLIBJNTIC35HCOSHY42YQG2ELGPEYAULZUIRRRQC
YIIILIV4ZPRIPWWT4GL7YWSJCUVH6RJJLXV4XIHY6SF3H7Y3EAYAC
5ASC3STDYCNLZFEBN6UTMUCGDETHBR2OCBZCF5VIAZ5RRWLOTDYQC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
Q5SFQO7ANODRI6OXKHPFQ4QWKGQ367S64DPURQW2TWK7ANTYO4NQC
JR2RAQ523LOWNDYJNK6AZVKI6WVMI622PIV72XWOVZYPXPUKSQWAC
UPJVSMMMHGRDUIJG4MZX6IBLQ4ODBF5Z3PF3RHDYTSAEOCVDZM5AC
SH6NU4H5TG4O7CRXRHZ7MDHABZLWWXQ77NJDBHI7KCVHXHQYK46QC
TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC
74LQ7JXVLAFSHLI7LCBKFX47CNTYSKGUQSXNX5FCIUIGCC2JTR3QC
LIBWXPN6HLJAIGEFJYLOL4HLIUD236U3WM5QPHIZ3DSB4CCUJERAC
YWYXUCZKGNIAWAUKUESIPFCAL5HZOKOEWHUEUW7X4DMAX2HG2FSAC
22RFWMSJGG26Z2MQEEXGKVTFSTLREHQIG46WYOTMDRKI5YVMRNVAC
CIPVRZGLOZHCERK6YPOBV3P2E4IAB4H6D5EHLRQE2O5E4P4VCBUAC
6HQB2N6N75R2RGKJFWRUN7WAC2PNGWQFXTII5DTRLTHZ2BOTMTVAC
ID2OZJTHFXL74RVUCS3JCMDQEUHAXCQFZU7235VU6IEVAAUWD2FAC
2BCSCMJ5FRMEZNX7C4WIP3M6WSFFKTIG22C57VV4VXFJPXT6JBJAC
SW3RLYFNRT3IJBK6LYKHKP2J2YDU7SXQWAJZX7U6S7ICYW43OMNQC
MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
TJRYL3NXPW5IUGEV3YOC7JYWEXCZDBFPLT4AUG4P227WVKVB72ZAC
UF4ODJOCV3ZL7DXRLLOFVWHUKKJX34FO4ZM6VJAWEJ3QVP3XZ2AAC
RVST2QHYJ757ZHK4AUJ5NGPDZ44AD6RVFVXYPKQIBJXZBDNUCHXQC
EHSY6DVGUMI6C67WKET3GDJVLWJWGYBYQONNDK5JVT7BCTHBEZVAC
V6REAY6RCAG2QQ4BO54GHYOVTNCYHTLERJCIZJPSANXFBINZOTXAC
XPCGZBHHSL6MB3ORMUJI64BAERU6AZTIY6RK56BBW7SNB3IK24IAC
E5GFDGV5XJVVDZGWFQIIZ47FGGF7AEJLGGBWRUZ34HPLNFJTNLLQC
NZFU5APXZZDBRYJGE57F43JKBBPWC33TIZNK6K4OZYSI47PFJMQQC
2ZFV5PKZU3HDHMLJWVWPPFV43NUNUON6YSAITHB26D7L4XIVWUHQC
gotoxy(40, 3); cprintf("HP:");
gotoxy(40, 4); cprintf("Magic:");
gotoxy(40, 5); cprintf("AC:");
gotoxy(40, 6); cprintf("EV:");
gotoxy(40, 7); cprintf("Str:");
gotoxy(40, 8); cprintf("Int:");
gotoxy(40, 9); cprintf("Dex:");
gotoxy(40, 10); cprintf("Gold:");
gotoxy(xcol, 3); cprintf("HP:");
gotoxy(xcol, 4); cprintf("Magic:");
gotoxy(xcol, 5); cprintf("AC:");
gotoxy(xcol, 6); cprintf("EV:");
gotoxy(xcol, 7); cprintf("Str:");
gotoxy(xcol, 8); cprintf("Int:");
gotoxy(xcol, 9); cprintf("Dex:");
gotoxy(xcol, 10); cprintf("Gold:");
int ch = (!map_bounds(gx, gy))
? 0
: (count_x < 8 || count_x > 24)
? get_envmap_char(gx, gy)
: (gx == you.x_pos && gy == you.y_pos)
? you.symbol
: get_screen_glyph(gx, gy);
int ch =
(!map_bounds(gc)) ? 0
: (!crawl_view.in_grid_los(gc)) ? get_envmap_char(gc.x, gc.y)
: (gc == you.pos()) ? you.symbol
: get_screen_glyph(gc.x, gc.y);
char *curr = lines[i];
while (*curr && curr - lines[i] < firstnonspace)
curr++;
ss += curr;
ss += EOL;
const std::string &ref = lines[i - 1];
if (firstnonspace < (int) ref.length())
ss << ref.substr(firstnonspace);
ss << EOL;
const int X_SIZE = VIEW_WIDTH;
const int Y_SIZE = VIEW_HEIGHT;
const int BUFFER_SIZE = 1550;
FixedVector < screen_buffer_t, BUFFER_SIZE > buffy;
std::vector<screen_buffer_t> buffy(
crawl_view.viewsz.y * crawl_view.viewsz.x * 2);
//////////////////////////////////////////////////////////////////////////////
// crawl_view_geometry
const int crawl_view_geometry::message_min_lines;
const int crawl_view_geometry::hud_min_width;
const int crawl_view_geometry::hud_min_gutter;
const int crawl_view_geometry::hud_max_gutter;
crawl_view_geometry::crawl_view_geometry()
: termsz(80, 24), viewp(1, 1), viewsz(33, 17),
hudp(40, 1), hudsz(41, 17),
msgp(1, viewp.y + viewsz.y), msgsz(80, 7)
{
}
void crawl_view_geometry::init_view()
{
set_player_at(you.pos(), true);
}
void crawl_view_geometry::set_player_at(const coord_def &c, bool centre)
{
if (centre)
{
vgrdc = c;
}
else
{
const coord_def oldc = vgrdc;
const int xmarg =
Options.scroll_margin_x + LOS_RADIUS <= viewhalfsz.x
? Options.scroll_margin_x
: viewhalfsz.x - LOS_RADIUS;
const int ymarg =
Options.scroll_margin_y + LOS_RADIUS <= viewhalfsz.y
? Options.scroll_margin_y
: viewhalfsz.y - LOS_RADIUS;
if (Options.view_lock_x)
vgrdc.x = c.x;
else if (c.x - LOS_RADIUS < vgrdc.x - viewhalfsz.x + xmarg)
vgrdc.x = c.x - LOS_RADIUS + viewhalfsz.x - xmarg;
else if (c.x + LOS_RADIUS > vgrdc.x + viewhalfsz.x - xmarg)
vgrdc.x = c.x + LOS_RADIUS - viewhalfsz.x + xmarg;
if (Options.view_lock_y)
vgrdc.y = c.y;
else if (c.y - LOS_RADIUS < vgrdc.y - viewhalfsz.y + ymarg)
vgrdc.y = c.y - LOS_RADIUS + viewhalfsz.y - ymarg;
else if (c.y + LOS_RADIUS > vgrdc.y + viewhalfsz.y - ymarg)
vgrdc.y = c.y + LOS_RADIUS - viewhalfsz.y + ymarg;
if (vgrdc != oldc && Options.center_on_scroll)
vgrdc = c;
if (!Options.center_on_scroll && Options.symmetric_scroll
&& !Options.view_lock_x
&& !Options.view_lock_y
&& (c - last_player_pos).abs() == 2
&& (vgrdc - oldc).abs() == 1)
{
const coord_def dp = c - last_player_pos;
const coord_def dc = vgrdc - oldc;
if ((dc.x == dp.x) != (dc.y == dp.y))
vgrdc = oldc + dp;
}
}
glos1 = c - coord_def(LOS_RADIUS, LOS_RADIUS);
glos2 = c + coord_def(LOS_RADIUS, LOS_RADIUS);
vlos1 = glos1 - vgrdc + view_centre();
vlos2 = glos2 - vgrdc + view_centre();
last_player_pos = c;
}
void crawl_view_geometry::init_geometry()
{
termsz = coord_def( get_number_of_cols(), get_number_of_lines() );
// If the terminal is too small, exit with an error.
if (termsz.x < 80 || termsz.y < 24)
end(1, false, "Terminal too small (%d,%d), need at least (80,24)",
termsz.x, termsz.y);
int freeheight = termsz.y - message_min_lines;
// Make the viewport as tall as possible.
viewsz.y = freeheight < Options.view_max_height?
freeheight : Options.view_max_height;
// Make sure we're odd-sized.
if (!(viewsz.y % 2))
--viewsz.y;
// The message pane takes all lines not used by the viewport.
msgp = coord_def(1, viewsz.y + 1);
msgsz = coord_def(termsz.x, termsz.y - viewsz.y);
int freewidth = termsz.x - (hud_min_width + hud_min_gutter);
// Make the viewport as wide as possible.
viewsz.x = freewidth < Options.view_max_width?
freewidth : Options.view_max_width;
if (!(viewsz.x % 2))
--viewsz.x;
// The hud appears after the viewport + gutter.
hudp = coord_def(viewsz.x + 1 + hud_min_gutter, 1);
// HUD size never changes, but we may increase the gutter size (up to
// the current max of 6).
if (hudp.x + hudsz.x - 1 < termsz.x)
{
const int hudmarg = termsz.x - (hudp.x + hudsz.x - 1);
const int hud_increase_max = hud_max_gutter - hud_min_gutter;
hudp.x += hudmarg > hud_increase_max? hud_increase_max : hudmarg;
}
viewhalfsz = viewsz / 2;
init_view();
}
void player::moveto(const coord_def &c)
{
x_pos = c.x;
y_pos = c.y;
crawl_view.set_player_at(c);
}
memmove( screen + SCREENINDEX(0, VIEW_EY),
screen + SCREENINDEX(0, VIEW_EY + 1),
get_message_window_height() * get_number_of_cols()
* sizeof(*screen) );
memmove( screen + SCREENINDEX(crawl_view.msgp.x - 1, crawl_view.msgp.y - 1),
screen + SCREENINDEX(crawl_view.msgp.x - 1, crawl_view.msgp.y),
crawl_view.msgsz.y * get_number_of_cols() * sizeof(*screen) );
else if (key == "view_max_width")
{
view_max_width = atoi(field.c_str());
if (view_max_width < VIEW_EX)
view_max_width = VIEW_EX;
else if (view_max_width > GXM + 1)
view_max_width = GXM + 1;
}
else if (key == "view_max_height")
{
view_max_height = atoi(field.c_str());
if (view_max_height < VIEW_EY)
view_max_height = VIEW_EY;
else if (view_max_height > GYM + 1)
view_max_height = GYM + 1;
}
else if (key == "view_lock_x")
{
view_lock_x = read_bool(field, view_lock_x);
}
else if (key == "view_lock_y")
{
view_lock_y = read_bool(field, view_lock_y);
}
else if (key == "view_lock")
{
const bool lock = read_bool(field, true);
view_lock_x = view_lock_y = lock;
}
else if (key == "center_on_scroll")
{
center_on_scroll = read_bool(field, center_on_scroll);
}
else if (key == "symmetric_scroll")
{
symmetric_scroll = read_bool(field, symmetric_scroll);
}
else if (key == "scroll_margin_x")
{
scroll_margin_x = atoi(field.c_str());
if (scroll_margin_x < 0)
scroll_margin_x = 0;
}
else if (key == "scroll_margin_y")
{
scroll_margin_y = atoi(field.c_str());
if (scroll_margin_y < 0)
scroll_margin_y = 0;
}
else if (key == "scroll_margin")
{
int scrollmarg = atoi(field.c_str());
if (scrollmarg < 0)
scrollmarg = 0;
scroll_margin_x = scroll_margin_y = scrollmarg;
}
FixedArray< unsigned int, 19, 19> show; // view window char
FixedArray< unsigned short, 19, 19> show_col; // view window colour
FixedArray<unsigned, ENV_SHOW_DIAMETER, ENV_SHOW_DIAMETER>
show; // view window char
FixedArray<unsigned short, ENV_SHOW_DIAMETER, ENV_SHOW_DIAMETER>
show_col; // view window colour
struct crawl_view_geometry
{
public:
coord_def termsz; // Size of the terminal.
coord_def viewp; // Left-top pos of viewport.
coord_def viewsz; // Size of the viewport (play area).
coord_def hudp; // Left-top pos of status area.
coord_def hudsz; // Size of the status area.
coord_def msgp; // Left-top pos of the message pane.
coord_def msgsz; // Size of the message pane.
coord_def vgrdc; // What grid pos is at the centre of the view
// usually you.pos().
coord_def viewhalfsz;
coord_def glos1, glos2; // LOS limit grid coords (inclusive)
coord_def vlos1, vlos2; // LOS limit viewport coords (inclusive)
static const int message_min_lines = 7;
static const int hud_min_width = 41;
static const int hud_min_gutter = 3;
static const int hud_max_gutter = 6;
private:
coord_def last_player_pos;
public:
crawl_view_geometry();
void init_geometry();
void init_view();
void set_player_at(const coord_def &c, bool force_centre = false);
coord_def view_centre() const
{
return viewp + viewhalfsz;
}
bool in_grid_los(const coord_def &c) const
{
return (c.x >= glos1.x && c.x <= glos2.x
&& c.y >= glos1.y && c.y <= glos2.y);
}
bool in_view_los(const coord_def &c) const
{
return (c.x >= vlos1.x && c.x <= vlos2.x
&& c.y >= vlos1.y && c.y <= vlos2.y);
}
bool in_view_viewport(const coord_def &c) const
{
return (c.x >= viewp.x && c.y >= viewp.y
&& c.x < viewp.x + viewsz.x
&& c.y < viewp.y + viewsz.y);
}
bool in_grid_viewport(const coord_def &c) const
{
return in_view_viewport(c - vgrdc + view_centre());
}
};
// The view lock variables force centering the viewport around the PC @
// at all times (the default). If view locking is not enabled, the viewport
// scrolls only when the PC hits the edge of it.
bool view_lock_x;
bool view_lock_y;
// For an unlocked viewport, this will center the viewport when scrolling.
bool center_on_scroll;
// If symmetric_scroll is set, for diagonal moves, if the view
// scrolls at all, it'll scroll diagonally.
bool symmetric_scroll;
// How far from the viewport edge is scrolling forced.
int scroll_margin_x;
int scroll_margin_y;
static char find_square( unsigned char xps, unsigned char yps,
FixedVector<char, 2> &mfp, char direction,
static char find_square( int xps, int yps,
FixedVector<char, 2> &mfp, int direction,
const int tx = x + VIEW_CX - you.x_pos,
ty = y + VIEW_CY - you.y_pos;
if (!in_los_bounds(tx, ty))
return (false);
return (x == you.x_pos && y == you.y_pos) || env.show[tx - LOS_SX][ty];
return (in_vlos(grid2view(coord_def(x, y))));
const int minx = VIEW_SX, maxx = VIEW_EX,
miny = VIEW_SY - VIEW_Y_DIFF, maxy = VIEW_EY + VIEW_Y_DIFF,
ctrx = VIEW_CX, ctry = VIEW_CY;
const coord_def vyou = grid2view(you.pos());
const int minx = vyou.x - radius, maxx = vyou.x + radius,
miny = vyou.y - radius, maxy = vyou.y + radius,
ctrx = vyou.x, ctry = vyou.y;
##### 4-f Travel and Exploration #################
##### 4-f Viewport Options ###################
# view_max_width = 33
# view_max_height = 17
# view_lock = false
# center_on_scroll = true
# symmetric_scroll = false
# scroll_margin = 4
##### 4-g Travel and Exploration #################
4-f Travel and Exploration.
The viewport is the portion of the map that is displayed during normal
play. The viewport is 33x17 by default, but if you use larger terminal
sizes, you can set these options to make the game show a larger
viewport. (These options are not fully available on DOS.)
None of these options affects gameplay. In particular, your character's
line-of-sight is unaffected by these options.
view_max_width = 33
Sets the maximum width of the viewport (defaults to 33).
Making this larger will allow Crawl to show a wider viewport
on larger terminals.
view_max_height = 17
Similar to view_max_width, but sets the viewport's maximum
height.
* Note that using large viewports can slow the game down.
view_lock_x = true
Keeps the player character centered horizontally in the
viewport, continuously scrolling the viewport to match the
PC's movements. If this is not set, the player character can
move horizontally within the viewport, and the viewport will
scroll only when the character's line-of-sight reaches the
left or right edge.
view_lock_y = true
Keeps the character centered vertically in the viewport.
view_lock = true
Aliased option that sets both view_lock_x and view_lock_y.
center_on_scroll = false
If this is set, the viewport centers on the player character
whenever it scrolls (this option is irrelevant if view_lock_x
and view_lock_y are set).
symmetric_scroll = true
If this is set, the viewport will scroll in a manner consistent
with the character movement that caused the scroll.
To illustrate, let's say the PC is at the lower edge of the
viewport, but is near the horizontal center. Now the PC moves
diagonally down and right, forcing the viewport to scroll up
one line. If symmetric_scroll is set, the viewport will also
scroll left one column to match the PC's diagonal movement. If
symmetric_scroll is not set, the viewport will only scroll up,
not horizontally. symmetric_scroll can be less disorienting
than free scrolling.
This option is not relevant if view_lock or center_on_scroll
are set.
scroll_margin_x = 4
How far from the left or right edges scrolling starts. By
default, if the PC's circle of line-of-sight is closer than 4
squares from the edge, the viewport scrolls. If set at zero,
the viewport scrolls only when the LOS circle reaches the
viewport edge.
scroll_margin_y = 4
How far from the top or bottom edges scrolling starts.
scroll_margin = 4
An aliased option that sets both scroll_margin_x and
scroll_margin_y.
4-g Travel and Exploration.