1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-23 21:07:17 +00:00

ads-game:: underlying/spacetime views

This commit is contained in:
Zeno Rogue 2022-10-14 01:01:50 +02:00
parent a7ca4c2902
commit 45141a9df0
6 changed files with 294 additions and 58 deletions

View File

@ -39,6 +39,7 @@ namespace rogueviz { std::vector<hr::reaction_t> cleanup; }
#include "menu.cpp" #include "menu.cpp"
#include "ds-game.cpp" #include "ds-game.cpp"
#include "ds-texture.cpp" #include "ds-texture.cpp"
#include "underlying.cpp"
namespace hr { namespace hr {
@ -101,6 +102,7 @@ void run_ads_game() {
rogueviz::rv_hook(hooks_frame, 100, view_ads_game); rogueviz::rv_hook(hooks_frame, 100, view_ads_game);
rogueviz::rv_hook(hooks_prestats, 100, display_rsrc); rogueviz::rv_hook(hooks_prestats, 100, display_rsrc);
rogueviz::rv_hook(hooks_handleKey, 0, handleKey); rogueviz::rv_hook(hooks_handleKey, 0, handleKey);
rogueviz::rv_hook(hooks_drawcell, 0, ads_draw_cell);
rogueviz::rv_hook(shmup::hooks_turn, 0, ads_turn); rogueviz::rv_hook(shmup::hooks_turn, 0, ads_turn);
rogueviz::rv_hook(anims::hooks_anim, 100, replay_animation); rogueviz::rv_hook(anims::hooks_anim, 100, replay_animation);

View File

@ -17,7 +17,7 @@ struct cell_to_draw {
}; };
void draw_game_cell(const cell_to_draw& cd) { void draw_game_cell(const cell_to_draw& cd) {
bool hv = rotspace;
using cellptr = cell*; using cellptr = cell*;
const cellptr& c = cd.c; const cellptr& c = cd.c;
const ads_matrix& V = cd.V; const ads_matrix& V = cd.V;
@ -36,12 +36,15 @@ void draw_game_cell(const cell_to_draw& cd) {
if(!gen_budget) return; if(!gen_budget) return;
gen_budget--; gen_budget--;
} }
gen_terrain(c, ci); PIU({
gen_rocks(c, ci, 0); gen_terrain(c, ci);
gen_rocks(c, ci, 0);
});
auto& t = ci.type; auto& t = ci.type;
if(t == wtGate) { if(hv) ;
else if(t == wtGate) {
ld minv = hlist[0].shift; ld minv = hlist[0].shift;
ld maxv = hlist[0].shift; ld maxv = hlist[0].shift;
for(auto& h: hlist) { for(auto& h: hlist) {
@ -120,13 +123,28 @@ void draw_game_cell(const cell_to_draw& cd) {
rock.pts.push_back(f); rock.pts.push_back(f);
}); });
} }
if(hv) {
ads_point M = current * (V * rock.at) * ads_matrix(Id, rock.pt_main.shift) * C0;
optimize_shift(M);
for(ld z=-5; z<=5; z+=0.2) {
for(int i=0; i<isize(shape); i += 2) {
auto h = rots::uxpush(shape[i] * ads_scale) * rots::uypush(shape[i+1] * ads_scale) * C0;
curvepoint(h);
}
curvepoint_first();
queuecurve(current * V * rock.at * ads_matrix(Id, rock.pt_main.shift+z), rock.col, 0, PPR::LINE);
}
}
for(auto h: rock.pts) curvepoint(h.h); else {
curvepoint(rock.pts[0].h); for(auto h: rock.pts) curvepoint(h.h);
queuecurve(shiftless(Id), curvepoint(rock.pts[0].h);
rock.type == oMissile ? missile_color : queuecurve(shiftless(Id),
rock.type == oParticle ? rock.col : rock.type == oMissile ? missile_color :
0x000000FF, rock.col, obj_prio[rock.type]); rock.type == oParticle ? rock.col :
0x000000FF, rock.col, obj_prio[rock.type]);
}
if(view_proper_times && rock.type != oParticle) { if(view_proper_times && rock.type != oParticle) {
string str = format(tformat, rock.pt_main.shift / ads_time_unit); string str = format(tformat, rock.pt_main.shift / ads_time_unit);
@ -137,6 +155,18 @@ void draw_game_cell(const cell_to_draw& cd) {
/* todo: binary search */ /* todo: binary search */
if(paused) for(auto& rock: ci.shipstates) { if(paused) for(auto& rock: ci.shipstates) {
cross_result cr; cross_result cr;
if(hv) {
auto& shape = shape_ship;
for(int i=0; i<isize(shape); i += 2) {
auto h = rots::uxpush(shape[i] * ads_scale) * rots::uypush(shape[i+1] * ads_scale) * C0;
curvepoint(h);
}
curvepoint_first();
queuecurve(current * V * rock.at, shipcolor, 0, PPR::LINE);
continue;
}
hybrid::in_actual([&]{ hybrid::in_actual([&]{
dynamicval<eGeometry> b(geometry, gRotSpace); dynamicval<eGeometry> b(geometry, gRotSpace);
auto h = V * rock.at; auto h = V * rock.at;
@ -164,7 +194,7 @@ void draw_game_cell(const cell_to_draw& cd) {
} }
} }
if(paused && c == vctr_ship && !game_over && !inHighQual) { if(paused && c == vctr_ship && !game_over && !in_replay && !hv) {
cross_result cr; cross_result cr;
hybrid::in_actual([&]{ hybrid::in_actual([&]{
auto h = ads_inverse(current_ship * vctrV_ship); auto h = ads_inverse(current_ship * vctrV_ship);
@ -202,6 +232,8 @@ void view_footer() {
void view_ads_game() { void view_ads_game() {
displayed.clear(); displayed.clear();
bool hv = hybri;
hybrid::in_actual([&] { hybrid::in_actual([&] {
gen_budget = max_gen_per_frame; gen_budget = max_gen_per_frame;
@ -284,7 +316,7 @@ void view_ads_game() {
}); });
} }
if(!game_over && !paused && !in_replay) { if(!game_over && !paused && !in_replay && !hv) {
poly_outline = 0xFF; poly_outline = 0xFF;
if(ship_pt < invincibility_pt) { if(ship_pt < invincibility_pt) {
ld u = (invincibility_pt-ship_pt) / ads_how_much_invincibility; ld u = (invincibility_pt-ship_pt) / ads_how_much_invincibility;

View File

@ -261,6 +261,7 @@ void ds_crash_ship() {
void ds_handle_crashes() { void ds_handle_crashes() {
if(paused) return; if(paused) return;
dynamicval<eGeometry> g(geometry, gSphere);
vector<ads_object*> dmissiles; vector<ads_object*> dmissiles;
vector<ads_object*> drocks; vector<ads_object*> drocks;
vector<ads_object*> dresources; vector<ads_object*> dresources;
@ -456,10 +457,13 @@ bool invalid(cross_result& res) {
void view_ds_game() { void view_ds_game() {
displayed.clear(); displayed.clear();
draw_textures();
sphereflip = sphereflipped() ? MirrorZ : Id; bool hv = hyperbolic;
bool hvrel = among(pmodel, mdRelPerspective, mdRelOrthogonal);
sphereflip = hv ? Id : sphereflipped() ? MirrorZ : Id;
if(!hv) draw_textures();
if(1) { if(1) {
for(auto& r: rocks) { for(auto& r: rocks) {
@ -505,8 +509,39 @@ void view_ds_game() {
if(area > 0) continue; if(area > 0) continue;
for(auto p: rock.pts) curvepoint(p.h); if(hv) {
queuecurve(shiftless(sphereflip), rock.col, rock.col, obj_prio[rock.type]); ld t = rock.at.shift;
if(rock.type == oMainRock) t = floor(10*t + .5) / 10;
transmatrix at = current.T * lorentz(2, 3, t - current.shift) * rock.at.T;
for(ld s=-3; s<=3; s+=0.1) {
transmatrix at1 = at * lorentz(2, 3, s);
if((at1 * pov) [2] < 0) continue;
auto& sh = *rock.shape;
for(int i=0; i<isize(sh); i+=2) {
hyperpoint h = hvrel ? tpt(sh[i], sh[i+1]) * pov: hpxy(sh[i], sh[i+1]);
curvepoint(h);
}
curvepoint_first();
color_t col = rock.col;
if(col == 0xFF) col = 0xFFD500FF;
if(col != 0xFFD500FF && !hvrel) part(col, 0) = part(col, 0) / 4;
queuecurve(shiftless(at1), col, 0, PPR::TRANSPARENT_WALL);
}
}
if(!hv) {
for(auto p: rock.pts) curvepoint(p.h);
queuecurve(shiftless(sphereflip), rock.col, rock.col, obj_prio[rock.type]);
}
if(pmodel == mdPerspective) {
for(auto p: rock.pts) curvepoint(p.h);
curvepoint_first();
color_t col = rock.col; part(col, 0) /= 2;
queuecurve(shiftless(sphereflip), col, 0, obj_prio[rock.type]).flags |= POLY_NO_FOG;
}
if(view_proper_times && rock.type != oParticle) { if(view_proper_times && rock.type != oParticle) {
ld t = rock.pt_main.shift; ld t = rock.pt_main.shift;
@ -524,6 +559,19 @@ void view_ds_game() {
if(paused) for(auto& ss: history) { if(paused) for(auto& ss: history) {
if(ss.at.shift < current.shift - 4 * TAU) continue; if(ss.at.shift < current.shift - 4 * TAU) continue;
if(ss.at.shift > current.shift + 4 * TAU) continue; if(ss.at.shift > current.shift + 4 * TAU) continue;
auto& shape = shape_ship;
if(hv) {
for(int i=0; i<isize(shape); i+=2) {
hyperpoint h = hvrel ? tpt(shape[i], shape[i+1]) * pov: hpxy(shape[i], shape[i+1]);
curvepoint(h);
}
curvepoint_first();
queuecurve(shiftless(current.T * lorentz(2, 3, ss.at.shift - current.shift) * ss.at.T), shipcolor, 0, PPR::TRANSPARENT_WALL);
continue;
}
dynamicval<eGeometry> g(geometry, gSpace435); dynamicval<eGeometry> g(geometry, gSpace435);
cross_result cr = ds_cross0(current.T * lorentz(2, 3, ss.at.shift - current.shift) * ss.at.T); cross_result cr = ds_cross0(current.T * lorentz(2, 3, ss.at.shift - current.shift) * ss.at.T);
if(cr.shift < delta) continue; if(cr.shift < delta) continue;
@ -532,15 +580,22 @@ void view_ds_game() {
vector<hyperpoint> pts; vector<hyperpoint> pts;
auto& shape = shape_ship;
for(int i=0; i<isize(shape); i += 2) { for(int i=0; i<isize(shape); i += 2) {
transmatrix at1 = at * tpt(shape[i], shape[i+1]); transmatrix at1 = at * tpt(shape[i], shape[i+1]);
pts.push_back(ds_cross0(at1).h); pts.push_back(ds_cross0(at1).h);
} }
geometry = g.backup; geometry = g.backup;
for(auto pt: pts) curvepoint(pt);
queuecurve(shiftless(sphereflip), 0xFF, shipcolor, PPR::MONSTER_FOOT); if(!hv) {
for(auto pt: pts) curvepoint(pt);
queuecurve(shiftless(sphereflip), 0xFF, shipcolor, PPR::MONSTER_FOOT);
}
if(pmodel == mdPerspective) {
for(auto pt: pts) curvepoint(pt);
queuecurve(shiftless(sphereflip), 0xFF, shipcolor, PPR::MONSTER_FOOT).flags |= POLY_NO_FOG;
}
if(view_proper_times) { if(view_proper_times) {
string str = format(tformat, (cr.shift + ss.start) / ds_time_unit); string str = format(tformat, (cr.shift + ss.start) / ds_time_unit);
@ -554,7 +609,17 @@ void view_ds_game() {
ld u = (invincibility_pt-ship_pt) / ds_how_much_invincibility; ld u = (invincibility_pt-ship_pt) / ds_how_much_invincibility;
poly_outline = gradient(shipcolor, rsrc_color[rtHull], 0, 0.5 + cos(5*u*TAU), 1); poly_outline = gradient(shipcolor, rsrc_color[rtHull], 0, 0.5 + cos(5*u*TAU), 1);
} }
queuepolyat(shiftless(sphereflip * spin(ang*degree)), make_shape(), shipcolor, PPR::MONSTER_HAIR); if(hv) {
auto& shape = shape_ship;
for(int i=0; i<isize(shape); i += 2) {
transmatrix at1 = tpt(shape[i], shape[i+1]);
curvepoint(ds_cross0(at1).h);
}
queuecurve(shiftless(sphereflip * spin(ang*degree)), shipcolor, 0, PPR::MONSTER_HAIR).flags |= POLY_NO_FOG;
}
else {
queuepolyat(shiftless(sphereflip * spin(ang*degree)), make_shape(), shipcolor, PPR::MONSTER_HAIR);
}
poly_outline = 0xFF; poly_outline = 0xFF;
if(view_proper_times) { if(view_proper_times) {
@ -568,7 +633,7 @@ void view_ds_game() {
queuestr(shiftless(sphereflip), .1, str, 0xFFFF00, 8); queuestr(shiftless(sphereflip), .1, str, 0xFFFF00, 8);
} }
if(paused && !game_over && !in_replay) { if(paused && !game_over && !in_replay && !hv) {
vector<hyperpoint> pts; vector<hyperpoint> pts;
int ok = 0, bad = 0; int ok = 0, bad = 0;
for(int i=0; i<=360; i++) { for(int i=0; i<=360; i++) {
@ -606,30 +671,6 @@ void ds_restart() {
init_rsrc(); init_rsrc();
} }
void replay_animation() {
if(!in_replay) return;
view_pt = (ticks / 1000.) * DS_(simspeed);
ld maxt = history.back().start + 0.001;
view_pt -= maxt * floor(view_pt / maxt);
for(auto& ss: history)
if(ss.start + ss.duration > view_pt) {
current = ss.current;
if(sphere) {
dynamicval<eGeometry> g(geometry, gSpace435);
current.T = inverse(ss.at.T * spin(-(ss.ang+90)*degree));
current.T = lorentz(3, 2, view_pt - ss.start) * current.T;
}
else PIA({
vctr = new_vctr = ss.vctr;
vctrV = new_vctrV = ss.vctrV;
current.T = cspin(3, 2, view_pt - ss.start) * current.T;
if(auto_rotate)
current.T = cspin(1, 0, view_pt - ss.start) * current.T;
});
break;
}
}
void run_ds_game() { void run_ds_game() {
stop_game(); stop_game();
@ -648,19 +689,8 @@ void run_ds_game() {
rogueviz::rv_hook(anims::hooks_anim, 100, replay_animation); rogueviz::rv_hook(anims::hooks_anim, 100, replay_animation);
} }
void switch_replay() {
in_replay = !in_replay;
if(in_replay) {
paused = true;
anims::period = 1000. * history.back().start / DS_(simspeed);
anims::noframes = anims::period * 60 / 1000;
}
}
auto ds_hooks = auto ds_hooks =
arg::add3("-ds-game", run_ds_game) arg::add3("-ds-game", run_ds_game);
+ arg::add3("-ds-recenter", [] { current = Id; })
+ arg::add3("-ds-record", switch_replay);
} }
} }

View File

@ -128,5 +128,9 @@ void run_ds_game();
/** in the replay mode */ /** in the replay mode */
bool in_replay; bool in_replay;
void switch_replay(); void switch_replay();
void replay_animation();
void switch_underlying();
bool ads_draw_cell(cell *c, const shiftmatrix& V);
}} }}

View File

@ -247,6 +247,11 @@ void ads_crash_ship() {
void handle_crashes() { void handle_crashes() {
if(paused) return; if(paused) return;
if(rotspace) {
if(!currentmap) { println(hlog, "no currentmap!"); return; }
PIU({ handle_crashes(); });
return;
}
vector<ads_object*> missiles; vector<ads_object*> missiles;
vector<ads_object*> rocks; vector<ads_object*> rocks;
vector<ads_object*> resources; vector<ads_object*> resources;

163
rogueviz/ads/views.cpp Normal file
View File

@ -0,0 +1,163 @@
/* underlying/spacetime views, and also replaying */
namespace hr {
namespace ads_game {
hrmap *map_hyp;
bool hv_klein = false;
transmatrix Duality;
void switch_underlying() {
clearMessages();
if(main_rock) {
if(sphere) {
cgi.use_count++;
geometry = gSpace435;
variation = eVariation::pure;
swap(currentmap, map_hyp);
pmodel = hv_klein ? mdDisk : mdPerspective;
if(hv_klein) pconf.alpha = 0;
check_cgi();
cgi.require_basics();
cgi.use_count++;
initcells();
initgame();
nomap = false;
}
else if(hyperbolic) {
nomap = true;
geometry = gSphere;
variation = eVariation::bitruncated;
swap(currentmap, map_hyp);
pmodel = mdDisk;
check_cgi();
nomap = true;
}
}
else {
check_cgi();
cgi.use_count++;
if(hyperbolic) {
hybrid::switch_to_actual();
pmodel = mdRelPerspective;
hyperpoint res;
nomap = false;
nonisotropic_weird_transforms = true;
NLP = Id;
/* Duality = Id;
for(int a=0; a<4; a++) for(int b=0; b<4; b++) Duality[a][b] = (a^2) == b; */
}
else if(hybri) {
hybrid::switch_to_underlying();
pmodel = mdDisk;
nomap = true;
}
cgi.use_count++;
}
View = Id;
cwt = centerover = currentmap->gamestart();
}
bool ads_draw_cell(cell *c, const shiftmatrix& V) {
auto cur_w = hybrid::get_where(c);
auto& ci = ci_at[cur_w.first];
if(ci.type) {
c->wall = waWaxWall;
c->landparam =
ci.type == wtSolid ? 0x603000 :
ci.type == wtDestructible ? 0x301800 :
0x080828;
}
else {
c->wall = waNone;
}
return false;
}
void replay_animation() {
if(in_replay) {
view_pt = (ticks / 1000.) * DS_(simspeed);
ld maxt = history.back().start + 0.001;
view_pt -= maxt * floor(view_pt / maxt);
for(auto& ss: history)
if(ss.start + ss.duration > view_pt) {
current = ss.current;
if(main_rock) {
dynamicval<eGeometry> g(geometry, gSpace435);
current.T = inverse(ss.at.T * spin(-(ss.ang)*degree));
current.T = lorentz(3, 2, view_pt - ss.start) * current.T;
}
else PIA({
vctr = new_vctr = ss.vctr;
vctrV = new_vctrV = ss.vctrV;
current.T = cspin(3, 2, view_pt - ss.start) * current.T;
if(auto_rotate)
current.T = cspin(1, 0, view_pt - ss.start) * current.T;
});
break;
}
}
if(main_rock && hyperbolic) {
View = Id;
centerover = currentmap->gamestart();
ld s = current.shift;
while(s > +1) { View = lorentz(2, 3, -1) * View; optimizeview(); s--; }
while(s < -1) { View = lorentz(2, 3, 1) * View; optimizeview(); s++; }
View = current.T * lorentz(2, 3, -s) * View; optimizeview();
centerover->wall = waNone;
}
if(!main_rock && rotspace) {
check_cgi();
ads_matrix CV = current * vctrV;
centerover = hybrid::get_at(vctr, 0);
View = Id;
// chg_shift(CV.shift) * CV.T
auto sub_optimizeview = [&] {
/* the important difference from optimizeview() is that we do not try to fix */
transmatrix iView = inverse(View);
virtualRebase(centerover, iView);
View = inverse(iView);
};
ld s = CV.shift;
View = CV.T * View; optimizeview();
while(s > 1) { View = chg_shift(1) * View; sub_optimizeview(); s--; }
while(s < -1) { View = chg_shift(-1) * View; sub_optimizeview(); s++; }
View = chg_shift(s) * View; sub_optimizeview();
centerover->wall = waNone;
}
}
void switch_replay() {
in_replay = !in_replay;
if(in_replay) {
paused = true;
anims::period = 1000. * history.back().start / DS_(simspeed);
anims::noframes = anims::period * 60 / 1000;
}
}
auto view_hooks =
+ arg::add3("-ds-recenter", [] { current = Id; })
+ arg::add3("-ds-record", switch_replay)
+ arg::add3("-ds-switchu", switch_underlying);
}}