hyperrogue/rogueviz/ads/display.cpp

278 lines
7.9 KiB
C++
Raw Normal View History

2022-09-11 10:16:50 +00:00
namespace hr {
namespace ads_game {
2022-09-17 15:34:54 +00:00
color_t shipcolor = 0x2020FFFF;
2022-09-11 11:44:28 +00:00
cross_result findflat(shiftpoint h) {
2022-09-11 10:16:50 +00:00
return cross0(current * rgpushxto0(h));
}
void draw_game_cell(cell *cs, ads_matrix V, ld plev) {
auto g = PIA( hybrid::get_where(cs) );
adjust_to_zero(V, g, plev);
auto c = g.first;
2022-09-11 11:44:28 +00:00
cross_result center;
vector<cross_result> hlist;
2022-09-11 10:16:50 +00:00
hybrid::in_actual([&]{
for(int i=0; i<=c->type; i++) {
hyperpoint ha = hybrid::get_corner(c, i, 2, 0);
hlist.push_back(findflat(V * ha));
}
center = findflat(V * C0);
});
if(1) {
ld d = hdist0(center.h);
if(d < vctr_dist) vctr_dist = d, new_vctr = PIA( hybrid::get_at(c, 0) ), new_vctrV = V;
2022-09-11 10:16:50 +00:00
}
auto& ci = ci_at[c];
if(ci.mpd_terrain > 0) {
if(!gen_budget) return;
gen_budget--;
}
gen_terrain(c, ci);
gen_rocks(c, ci, 0);
auto& t = ci.type;
if(t == wtGate) {
ld minv = hlist[0].shift;
ld maxv = hlist[0].shift;
for(auto& h: hlist) {
ld v = h.shift;
if(v < minv) minv = v;
if(v > maxv) maxv = v;
}
auto draw_slice = [&] (ld a, ld b, color_t col) {
vector<hyperpoint> slice;
for(int i=0; i<c->type; i++) {
if(hlist[i].shift >= a && hlist[i].shift <= b)
slice.push_back(hlist[i].h);
if((hlist[i].shift < a) ^ (hlist[i+1].shift < a)) {
ld p = ilerp(hlist[i].shift, hlist[i+1].shift, a);
hyperpoint h1 = lerp(hlist[i].h, hlist[i+1].h, p);
slice.push_back(h1);
}
if((hlist[i].shift > b) ^ (hlist[i+1].shift > b)) {
ld p = ilerp(hlist[i].shift, hlist[i+1].shift, b);
hyperpoint h1 = lerp(hlist[i].h, hlist[i+1].h, p);
slice.push_back(h1);
}
if(hlist[i+1].shift < a && hlist[i].shift > b)
swap((&slice.back())[-1], slice.back());
}
if(isize(slice) < 3) return;
for(auto e: slice) curvepoint(e);
curvepoint(slice[0]);
queuecurve(shiftless(Id), 0xFFFFFFFF, col, PPR::LINE);
};
for(int v=floor(minv); v<maxv+1; v++) {
draw_slice(v, v+1, (v & 3) ? 0x080828FF : 0xA04020FF);
}
}
else {
color_t col =
t == wtSolid ? 0x603000FF :
t == wtDestructible ? 0x301800FF :
0x181818FF;
for(auto h: hlist) curvepoint(h.h);
addaura(shiftless(center.h), col >> 8, 0);
queuecurve(shiftless(Id), 0x101010FF, col, PPR::WALL);
}
if(view_proper_times) {
2022-09-18 08:22:13 +00:00
string str = format(tformat, center.shift / time_unit);
2022-09-11 10:16:50 +00:00
queuestr(shiftless(rgpushxto0(center.h)), .1, str, 0xFF4040, 8);
}
for(auto& r: ci.rocks) {
auto& rock = *r;
2022-09-11 10:16:50 +00:00
2022-09-11 11:42:51 +00:00
hybrid::in_actual([&]{
2022-09-11 10:16:50 +00:00
dynamicval<eGeometry> b(geometry, gRotSpace);
auto h = V * rock.at;
2022-09-11 11:42:51 +00:00
rock.pt_main = cross0(current * h);
2022-09-11 10:16:50 +00:00
});
2022-09-11 11:42:51 +00:00
if(rock.pt_main.shift < rock.life_start || rock.pt_main.shift > rock.life_end) continue;
displayed.push_back(&rock);
2022-09-11 10:16:50 +00:00
rock.pts.clear();
auto& shape = *rock.shape;
2022-09-11 10:16:50 +00:00
for(int i=0; i<isize(shape); i += 2) {
hybrid::in_actual([&]{
2022-09-18 11:03:14 +00:00
auto h = V * rock.at * rots::uxpush(shape[i] * scale) * rots::uypush(shape[i+1] * scale);
2022-09-11 11:44:28 +00:00
cross_result f = cross0(current * h);
2022-09-11 11:42:51 +00:00
rock.pts.push_back(f);
2022-09-11 10:16:50 +00:00
});
}
2022-09-11 11:42:51 +00:00
for(auto h: rock.pts) curvepoint(h.h);
curvepoint(rock.pts[0].h);
queuecurve(shiftless(Id),
rock.type == oMissile ? missile_color :
rock.type == oParticle ? rock.col :
0x000000FF, rock.col, PPR::LINE);
2022-09-11 10:16:50 +00:00
if(view_proper_times && rock.type != oParticle) {
2022-09-18 08:22:13 +00:00
string str = format(tformat, rock.pt_main.shift / time_unit);
2022-09-11 11:42:51 +00:00
queuestr(shiftless(rgpushxto0(rock.pt_main.h)), .1, str, 0xFFFFFF, 8);
2022-09-11 10:16:50 +00:00
}
}
2022-09-17 15:34:54 +00:00
/* todo: binary search */
if(paused) for(auto& rock: ci.shipstates) {
ld t;
hybrid::in_actual([&]{
dynamicval<eGeometry> b(geometry, gRotSpace);
auto h = V * rock.at;
t = cross0(current * h).shift;
});
if(t < -1e-6 || t > rock.duration + 1e-6) continue;
vector<hyperpoint> pts;
auto& shape = shape_ship;
for(int i=0; i<isize(shape); i += 2) {
hybrid::in_actual([&]{
2022-09-18 11:03:14 +00:00
auto h = V * rock.at * rgpushxto0(normalize(hyperpoint(shape[i] * scale, shape[i+1] * scale, 1, 0)));
2022-09-17 15:34:54 +00:00
pts.push_back(cross0(current * h).h);
});
}
for(auto h: pts) curvepoint(h);
curvepoint(pts[0]);
queuecurve(shiftless(Id), 0xFF, shipcolor, PPR::LINE);
}
if(paused && c == vctr_ship_base && !game_over) {
vector<hyperpoint> pts;
vector<ld> times;
int ok = 0, bad = 0;
for(int i=0; i<=360; i++) {
hybrid::in_actual([&]{
auto h = ads_inverse(current_ship * vctrV_ship) * spin(i*degree) * lorentz(0, 2, 6);
auto cr = cross0(current * V * h);
pts.push_back(cr.h);
times.push_back(cr.shift);
if(cr.shift > 0 && cr.shift < 90*degree) ok++; else bad++;
});
}
if(bad == 0) {
for(auto h: pts) curvepoint(h);
queuecurve(shiftless(Id), 0x000000C0, 0x00000060, PPR::SUPERLINE);
}
}
2022-09-11 10:16:50 +00:00
}
void view_ads_game() {
ld plev;
2022-09-11 11:42:51 +00:00
displayed.clear();
2022-09-11 10:16:50 +00:00
hybrid::in_actual([&] {
plev = cgi.plevel; /* we are in another CGI so we have no access to that... */
2022-09-18 11:34:30 +00:00
gen_budget = max_gen_per_frame;
vctr = new_vctr;
vctrV = new_vctrV;
cross_result base;
2022-09-11 10:16:50 +00:00
// todo rebase
base = findflat(ads_point(C0, 0));
// println(hlog, base.h);
ld ebase = 0;
hybrid::in_underlying_geometry([&]{
ebase = hdist0(base.h);
// println(hlog, "dist base pre = ", hdist0(base.h), " at ", base.shift);
});
// println(hlog, base.h[2]*base.h[2] - base.h[1]*base.h[1] - base.h[0] * base.h[0]);
for(int u=0; u<30; u++) {
auto bcurrent = current;
transmatrix T = spin(12*degree*u) * xpush(0.5);
current.T = current.T * T;
auto base1 = findflat(ads_point(C0, 0));
ld ebase1 = 0;
hybrid::in_underlying_geometry([&] {
ebase1 = hdist0(base1.h);
});
if(ebase1 < ebase) { vctrV.T = inverse(T) * vctrV.T; }
else { current = bcurrent; }
}
}
);
2022-09-11 10:16:50 +00:00
// current = current * gpushxto0(p);
// vctrV = rgpushxto0(p) * vctrV;
if(1) {
2022-09-11 10:16:50 +00:00
make_shape();
2022-09-11 10:16:50 +00:00
set<cell*> visited;
queue<pair<cell*, ads_matrix>> dq;
auto visit = [&] (cell *c, const ads_matrix& V) {
auto w = hybrid::get_where(c);
if(visited.count(w.first)) return;
visited.insert(w.first);
dq.emplace(c, V);
};
hybrid::in_actual([&] {
dynamicval<eGeometry> b(geometry, gRotSpace);
visit(vctr, vctrV);
vctr_dist = HUGE_VAL;
});
int i = 0;
while(!dq.empty()) {
2022-09-18 11:34:30 +00:00
i++; if(i > draw_per_frame) break;
2022-09-11 10:16:50 +00:00
auto& p = dq.front();
cell *c = p.first;
ads_matrix V = p.second;
dq.pop();
draw_game_cell(c, V, plev);
hybrid::in_actual([&] {
for(int i=0; i<c->type-2; i++) {
cell *c2 = c->cmove(i);
auto V1 = V * currentmap->adj(c, i);
optimize_shift(V1);
visit(c2, V1);
}
});
}
if(!game_over && !paused) {
2022-09-11 10:16:50 +00:00
poly_outline = 0xFF;
2022-09-12 10:57:52 +00:00
if(ship_pt < invincibility_pt) {
ld u = (invincibility_pt-ship_pt) / how_much_invincibility;
poly_outline = gradient(shipcolor, rsrc_color[rtHull], 0, 0.5 + cos(5*u*TAU), 1);
}
queuepolyat(shiftless(spin(ang*degree) * Id), shShip, shipcolor, PPR::LINE);
poly_outline = 0xFF;
2022-09-11 10:16:50 +00:00
if(view_proper_times) {
2022-09-18 08:22:13 +00:00
string str = format(tformat, ship_pt / time_unit);
2022-09-11 10:16:50 +00:00
queuestr(shiftless(Id), .1, str, 0xFFFFFF, 8);
}
}
if(paused && view_proper_times) {
2022-09-18 08:22:13 +00:00
string str = format(tformat, view_pt / time_unit);
queuestr(shiftless(Id), .1, str, 0xFFFF00, 8);
}
}
2022-09-11 10:16:50 +00:00
}
}}