smart display range

This commit is contained in:
Zeno Rogue 2018-11-01 18:59:25 +01:00
parent c40953fbad
commit 1ba1b141f3
8 changed files with 196 additions and 69 deletions

View File

@ -290,6 +290,10 @@ void initConfig() {
addsaver(texture::texture_aura, "texture-aura", false);
#endif
addsaver(vid.use_smart_range, "smart-range", 0);
addsaver(vid.smart_range_detail, "smart-range-detail", 8);
addsaver(vid.cells_drawn_limit, "limit on cells drawn", 10000);
#if CAP_SHMUP
shmup::initConfig();
#endif
@ -555,6 +559,59 @@ void loadNewConfig(FILE *f) {
}
allconfigs.clear();
}
void edit_sightrange() {
if(vid.use_smart_range == 0) {
dialog::editNumber(sightrange_bonus, -5, allowIncreasedSight() ? 3 : 0, 1, 0, XLAT("sight range"),
XLAT("Roughly 42% cells are on the edge of your sight range. Reducing "
"the sight range makes HyperRogue work faster, but also makes "
"the game effectively harder."));
dialog::reaction = [] () {
doOvergenerate();
};
}
else {
dialog::editNumber(vid.smart_range_detail, 1, 50, 1, 8, XLAT("minimum visible cell in pixels"), "");
}
dialog::extra_options = [] () {
dialog::addBoolItem(XLAT("draw range based on distance"), vid.use_smart_range == 0, 'd');
dialog::add_action([] () { vid.use_smart_range = 0; popScreen(); edit_sightrange(); });
if(allowIncreasedSight()) {
dialog::addBoolItem(XLAT("draw based on size in the projection (no generation)"), vid.use_smart_range == 1, 'n');
dialog::add_action([] () { vid.use_smart_range = 1; popScreen(); edit_sightrange(); });
}
if(allowChangeRange()) {
dialog::addBoolItem(XLAT("draw based on size in the projection (generation)"), vid.use_smart_range == 2, 'g');
dialog::add_action([] () { vid.use_smart_range = 2; popScreen(); edit_sightrange(); });
}
if(vid.use_smart_range == 0 && allowChangeRange()) {
dialog::addSelItem(XLAT("generation range bonus"), its(genrange_bonus), 'o');
dialog::add_action([] () { genrange_bonus = sightrange_bonus; doOvergenerate(); });
dialog::addSelItem(XLAT("game range bonus"), its(gamerange_bonus), 'O');
dialog::add_action([] () { gamerange_bonus = sightrange_bonus; doOvergenerate(); });
}
if(!allowChangeRange() || !allowIncreasedSight()) {
dialog::addItem(XLAT("enable the cheat mode for additional options"), 'C');
dialog::add_action(enable_cheat);
}
dialog::addSelItem(XLAT("cells drawn"), its(cells_drawn), 'c');
dialog::add_action([] () {
popScreen();
dialog::editNumber(vid.cells_drawn_limit, 100, 1000000, log(10), 10000, XLAT("limit on cells drawn"),
XLAT("This limit exists to protect the engine from freezing when too many cells would be drawn according to the current options.")
);
dialog::scaleLog();
});
};
}
void menuitem_sightrange(char c = 'r') {
if(vid.use_smart_range)
dialog::addSelItem(XLAT("minimum visible cell in pixels"), fts(vid.smart_range_detail), c);
else
dialog::addSelItem(XLAT("sight range"), its(sightrange_bonus), c);
dialog::add_action(edit_sightrange);
}
void loadConfig() {
@ -663,8 +720,8 @@ void showGraphConfig() {
dialog::addSelItem(XLAT("font scale"), its(fontscale), 'b');
dialog::addSelItem(XLAT("sight range"), its(sightrange_bonus), 'r');
menuitem_sightrange();
dialog::addSelItem(XLAT("compass size"), its(vid.mobilecompasssize), 'c');
dialog::addSelItem(XLAT("aura brightness"), its(vid.aurastr), 'z');
@ -701,26 +758,6 @@ void showGraphConfig() {
XLAT("movement animation speed"),
XLAT("+5 = move instantly"));
if(xuni == 'r') {
dialog::editNumber(sightrange_bonus, -5, allowIncreasedSight() ? 3 : 0, 1, 0, XLAT("sight range"),
XLAT("Roughly 42% cells are on the edge of your sight range. Reducing "
"the sight range makes HyperRogue work faster, but also makes "
"the game effectively harder."));
dialog::reaction = [] () {
doOvergenerate();
};
dialog::extra_options = [] () {
if(allowChangeRange()) {
dialog::addSelItem(XLAT("generation range bonus"), its(genrange_bonus), 'o');
dialog::add_action([] () { genrange_bonus = sightrange_bonus; doOvergenerate(); });
dialog::addSelItem(XLAT("game range bonus"), its(gamerange_bonus), 'O');
dialog::add_action([] () { gamerange_bonus = sightrange_bonus; doOvergenerate(); });
}
if(!allowChangeRange() || !allowIncreasedSight())
dialog::addInfo(XLAT("note: enable the cheat mode for additional options"));
};
}
if(xuni == 'k') {
glyphsortorder = eGlyphsortorder((glyphsortorder+6+(shiftmul>0?1:-1)) % gsoMAX);
}
@ -1177,10 +1214,12 @@ void show3D() {
using namespace geom3;
dialog::init(XLAT("3D configuration"));
dialog::addSelItem(XLAT("High detail range"), fts(highdetail), 'n');
dialog::addSelItem(XLAT("Mid detail range"), fts(middetail), 'm');
if(vid.use_smart_range == 0) {
dialog::addSelItem(XLAT("High detail range"), fts(highdetail), 'n');
dialog::addSelItem(XLAT("Mid detail range"), fts(middetail), 'm');
dialog::addBreak(50);
}
dialog::addBreak(50);
dialog::addSelItem(XLAT("Camera level above the plane"), fts3(camera), 'c');
dialog::addSelItem(XLAT("Ground level below the plane"), fts3(depth), 'g');

View File

@ -682,6 +682,8 @@ namespace conformal {
}
dialog::addSelItem(XLAT("vertical stretch"), fts3(vid.stretch), 's');
menuitem_sightrange('R');
dialog::addBreak(100);
dialog::addItem(XLAT("history mode"), 'a');

View File

@ -3353,7 +3353,7 @@ void pushdown(cell *c, int& q, const transmatrix &V, double down, bool rezoom, b
bool dodrawcell(cell *c) {
// do not display out of range cells, unless on torus
if(c->pathdist == PINFD && geometry != gTorus)
if(c->pathdist == PINFD && geometry != gTorus && vid.use_smart_range == 0)
return false;
// do not display not fully generated cells, unless a cheater
if(c->mpdist > 7 && !cheater && !autocheat) return false;
@ -3535,6 +3535,8 @@ int colorhash(color_t i) {
void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
cells_drawn++;
#if CAP_TEXTURE
if(texture::saving) {
texture::config.apply(c, V, 0xFFFFFFFF);
@ -3564,7 +3566,8 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
if(callhandlers(false, hooks_drawcell, c, V)) return;
ld dist0 = hdist0(tC0(V)) - 1e-6;
if(dist0 < geom3::highdetail) detaillevel = 2;
if(vid.use_smart_range) detaillevel = 2;
else if(dist0 < geom3::highdetail) detaillevel = 2;
else if(dist0 < geom3::middetail) detaillevel = 1;
else detaillevel = 0;
@ -5245,6 +5248,7 @@ void drawthemap() {
callhooks(hooks_drawmap);
frameid++;
cells_drawn = 0;
wavephase = (-(ticks / 100)) & 7;
@ -5316,7 +5320,7 @@ void drawthemap() {
else if(archimedean)
arcm::draw();
else
drawrec(viewctr, hsOrigin, cview());
drawrec(viewctr, hsOrigin, cview(), 0);
drawWormSegments();
drawBlizzards();
drawArrowTraps();

26
hyper.h
View File

@ -1047,6 +1047,10 @@ struct videopar {
bool skipstart; // skip the start menu
int quickmouse; // quick mouse on the map
int timeformat; // time format used in the message log
int use_smart_range; // 0 = distance-based, 1 = model-based, 2 = model-based and generate
ld smart_range_detail;// minimum visible cell for modes 1 and 2
int cells_drawn_limit;
};
extern videopar vid;
@ -3798,7 +3802,7 @@ void queuestr(const hyperpoint& h, int size, const string& chr, color_t col, int
void queuechr(const transmatrix& V, double size, char chr, color_t col, int frame = 0);
extern bool just_gmatrix;
void drawrec(const heptspin& hs, hstate s, const transmatrix& V);
void drawrec(const heptspin& hs, hstate s, const transmatrix& V, int reclev = 0);
bool haveLeaderboard(int id);
int get_currentscore(int id);
@ -4272,5 +4276,25 @@ struct exp_parser {
}
};
#ifdef CAP_COMPLEX2
namespace brownian {
const int level = 5;
void init(cell *c);
void build(cell *c, int d);
void explosion(cell *c, int x);
};
#else
namespace brownian {
inline void dissolve_brownian(cell*, int) {};
inline void build(cell *c, int d) {}
inline void init(cell *c) {}
}
#endif
#define ONEMPTY if(d == 7 && passable(c, NULL, 0) && !safety)
void enable_cheat();
extern int cells_drawn;
}

View File

@ -626,9 +626,34 @@ transmatrix applyspin(const heptspin& hs, const transmatrix& V) {
return hs.spin ? V * spin(hs.spin*2*M_PI/S7) : V;
}
bool in_smart_range(const transmatrix& T) {
hyperpoint h1, h2, h3;
applymodel(tC0(T), h1);
ld x = vid.xcenter + vid.radius * h1[0];
ld y = vid.ycenter + vid.radius * h1[1] * vid.stretch;
if(x > vid.xres * 2) return false;
if(x < -vid.xres) return false;
if(y > vid.yres * 2) return false;
if(y < -vid.yres) return false;
ld epsilon = 0.01;
applymodel(T * xpush0(epsilon), h2);
ld x1 = vid.radius * abs(h2[0] - h1[0]) / epsilon;
ld y1 = vid.radius * abs(h2[1] - h1[1]) * vid.stretch / epsilon;
applymodel(T * ypush(epsilon) * C0, h3);
ld x2 = vid.radius * abs(h3[0] - h1[0]) / epsilon;
ld y2 = vid.radius * abs(h3[1] - h1[1]) * vid.stretch / epsilon;
ld scale = sqrt(hypot(x1, y1) * hypot(x2, y2)) * scalefactor * hcrossf7;
return
scale > vid.smart_range_detail &&
x - 2 * max(x1, x2) < vid.xres &&
x + 2 * max(x1, x2) > 0 &&
y - 2 * max(y1, y2) < vid.yres &&
y + 2 * max(y1, y2) > 0;
}
// in hyperbolic quotient geometries, relying on pathdist is not sufficient
bool in_qrange(const transmatrix& V) {
if(!quotient || !hyperbolic) return true;
if(!quotient || !hyperbolic || vid.use_smart_range) return true;
return V[2][2] < cosh(crossf * get_sightrange_ambush());
}
@ -688,7 +713,7 @@ void drawrec(cell *c, const transmatrix& V) {
}
}
void drawrec(const heptspin& hs, hstate s, const transmatrix& V) {
void drawrec(const heptspin& hs, hstate s, const transmatrix& V, int reclev) {
// calc_relative_matrix(cwt.c, hs.at);
@ -699,6 +724,14 @@ void drawrec(const heptspin& hs, hstate s, const transmatrix& V) {
bool draw = c->pathdist < PINFD;
if(cells_drawn > vid.cells_drawn_limit || reclev >= 100 || std::isinf(V[2][2]) || std::isnan(V[2][2]))
draw = false;
else if(vid.use_smart_range) {
draw = reclev < 2 ? true : in_smart_range(V);
if(draw && vid.use_smart_range == 2)
setdist(c, 7, NULL);
}
if(GOLDBERG) {
gp::drawrec(c, actualV(hs, V1));
}
@ -734,7 +767,7 @@ void drawrec(const heptspin& hs, hstate s, const transmatrix& V) {
hstate s2 = transition(s, d);
if(s2 == hsError) continue;
heptspin hs2 = hs + d + wstep;
drawrec(hs2, s2, V * heptmove[d]);
drawrec(hs2, s2, V * heptmove[d], reclev+1);
}
}
@ -838,19 +871,31 @@ void drawEuclidean() {
// Mat[2][0] = x*x/10;
// Mat[2][1] = y*y/10;
// Mat = Mat * xpush(x-30) * ypush(y-30);
int cx, cy, shift;
getcoord0(tC0(Mat), cx, cy, shift);
if(cx >= 0 && cy >= 0 && cx < vid.xres && cy < vid.yres) {
if(dx < mindx) mindx = dx;
if(dy < mindy) mindy = dy;
if(dx > maxdx) maxdx = dx;
if(dy > maxdy) maxdy = dy;
}
if(cx >= -cellrad && cy >= -cellrad && cx < vid.xres+cellrad && cy < vid.yres+cellrad)
if(dodrawcell(cw.at)) {
drawcell(cw.at, cw.mirrored ? Mat * Mirror : Mat, cw.spin, cw.mirrored);
if(vid.use_smart_range) {
if(in_smart_range(Mat)) {
if(dx < mindx) mindx = dx;
if(dy < mindy) mindy = dy;
if(dx > maxdx) maxdx = dx;
if(dy > maxdy) maxdy = dy;
if(dodrawcell(cw.at))
drawcell(cw.at, cw.mirrored ? Mat * Mirror : Mat, cw.spin, cw.mirrored);
}
}
else {
int cx, cy, shift;
getcoord0(tC0(Mat), cx, cy, shift);
if(cx >= 0 && cy >= 0 && cx < vid.xres && cy < vid.yres) {
if(dx < mindx) mindx = dx;
if(dy < mindy) mindy = dy;
if(dx > maxdx) maxdx = dx;
if(dy > maxdy) maxdy = dy;
}
if(cx >= -cellrad && cy >= -cellrad && cx < vid.xres+cellrad && cy < vid.yres+cellrad)
if(dodrawcell(cw.at)) {
drawcell(cw.at, cw.mirrored ? Mat * Mirror : Mat, cw.spin, cw.mirrored);
}
}
}
}
@ -997,6 +1042,8 @@ void panning(hyperpoint hf, hyperpoint ht) {
playermoved = false;
}
int cells_drawn;
void fullcenter() {
if(playerfound && false) centerpc(INF);
else {

View File

@ -406,6 +406,28 @@ void showDisplayMode() {
};
}
void enable_cheat() {
if(tactic::on && gold()) {
addMessage(XLAT("Not available in the pure tactics mode!"));
}
else if(daily::on) {
addMessage(XLAT("Not available in the daily challenge!"));
}
else if(!cheater) {
cheater++;
addMessage(XLAT("You activate your demonic powers!"));
#if ISMOBILE==0
addMessage(XLAT("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc."));
#endif
popScreen();
}
else {
popScreen();
firstland = princess::challenge ? laPalace : laIce;
restart_game();
}
}
// -- game modes --
void switchHardcore() {
@ -484,27 +506,8 @@ void showChangeMode() {
pushScreen(daily::showMenu);
#endif
else if(uni == 'c') {
if(tactic::on && gold()) {
addMessage(XLAT("Not available in the pure tactics mode!"));
}
else if(daily::on) {
addMessage(XLAT("Not available in the daily challenge!"));
}
else if(!cheater) {
cheater++;
addMessage(XLAT("You activate your demonic powers!"));
#if ISMOBILE==0
addMessage(XLAT("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc."));
#endif
popScreen();
}
else {
popScreen();
firstland = princess::challenge ? laPalace : laIce;
restart_game();
}
}
else if(uni == 'c')
enable_cheat();
else if(xuni == 'e')
runGeometryExperiments();

View File

@ -293,7 +293,11 @@ void initgame() {
if(quotient || sphere)
for(cell *c: currentmap->allcells()) setdist(c, 8, NULL);
if(!cheater) gamerange_bonus = genrange_bonus = 0;
if(!cheater) {
gamerange_bonus = genrange_bonus = 0;
if(vid.use_smart_range == 2) vid.use_smart_range = 1;
}
if(!allowIncreasedSight()) vid.use_smart_range = 0;
}
bool havesave = true;

View File

@ -588,11 +588,12 @@ slide default_slides[] = {
"The next slide shows another model, called the Poincaré upper half-plane model. In this model, "
"horocycles centered at one specific ideal point are drawn as straight lines.",
[] (presmode mode) {
static int smart;
if(mode == 1)
pmodel = mdHalfplane;
pmodel = mdHalfplane, smart = vid.use_smart_range, vid.use_smart_range = 2;
if(mode == 2)
conformal::rotation = cwt.at->land == laDungeon ? 0 : 2;
if(mode == 3) pmodel = mdDisk, conformal::rotation = 0;
if(mode == 3) pmodel = mdDisk, conformal::rotation = 0, vid.use_smart_range = smart;
}
},
{"Curvature", 29, LEGAL_ANY,
@ -739,13 +740,16 @@ slide default_slides[] = {
"If you want, press '5' to see it rendered as a spiral, although it takes lots of time and "
"memory.",
[] (presmode mode) {
if(mode == 1) pmodel = mdBand, conformal::create(), conformal::rotation = 0;
static int smart;
if(mode == 1) pmodel = mdBand, conformal::create(), conformal::rotation = 0,
smart = vid.use_smart_range, vid.use_smart_range = 2;
if(mode == 3) {
conformal::clear(), pmodel = mdDisk;
resetview();
drawthemap();
centerpc(INF);
conformal::includeHistory = false;
vid.use_smart_range = smart;
}
#if CAP_SDL
slidecommand = "render spiral";