1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-08-29 16:57:56 +00:00

rogueviz:: ads:: tour improved

This commit is contained in:
Zeno Rogue
2025-06-22 16:10:49 +02:00
parent 460f011590
commit 66ae1d48d3

View File

@@ -3,6 +3,7 @@ namespace hr {
namespace ads_game { namespace ads_game {
extern purehookset hooks_pre_ads_start; extern purehookset hooks_pre_ads_start;
extern bool changed_structure;
namespace ads_tour { namespace ads_tour {
using namespace rogueviz::pres; using namespace rogueviz::pres;
@@ -28,9 +29,49 @@ cell *slv;
transmatrix at0, at1; transmatrix at0, at1;
int t0, t1; int t0, t1;
void straight_line_viz_rocks(presmode mode) {
if(mode == pmStart) {
rv_hook(shmup::hooks_draw, 100, [] (const shiftmatrix&, cell*, shmup::monster*) {
items[itOrbAether] = 0; items[itOrbShield] = 0;
return false;
});
}
if(mode == pmFrame) {
items[itOrbLife] = 3; if(shmup::pc[0]) shmup::pc[0]->dead = false;
}
if(mode == pmKey) {
for(auto [c, mo]: shmup::monstersAt) if(mo->type == moAsteroid) mo->dead = true;
auto pc = shmup::pc[0];
for(int r: {1, 2, 3})
for(int i=0; i<36*r; i++) {
transmatrix T = spin(TAU*i/r/36) * xpush(cgi.scalefactor*r) * spin(-TAU*i/r/6);
ld r = hypot_d(WDIM, pc->inertia), eps = 1e-3;
transmatrix In = lrspintox(pc->inertia) * lxpush(r * eps) * lspintox(pc->inertia);
shmup::monster* child = new shmup::monster;
child->base = pc->base;
child->at = pc->at * T;
child->ori = pc->ori;
child->type = moAsteroid;
child->pid = pc->pid;
child->inertia = inverse(T) * In * T * C0;
auto f = child->inertia;
child->inertia = lrspintox(child->inertia) * eupoint(hdist0(child->inertia) / eps, 0);
println(hlog, "inertia = ", child->inertia, " f = ", f);
// child->inertia = eupoint(0, 0);
child->hitpoints = 3;
shmup::additional.push_back(child);
}
if(tour_value == 1) quitmainloop = true;
}
}
void straight_line_viz(presmode mode) { void straight_line_viz(presmode mode) {
if(mode == pmKey) slv_mode = (slv_mode == 0 ? 1 : 0); if(mode == pmKey) slv_mode = (slv_mode == 0 ? 1 : 0);
if(mode == pmStart) rogueviz::rv_hook(hooks_markers, 100, [] { if(mode == pmStart) rogueviz::rv_hook(hooks_frame, 100, [] {
if(inHighQual && slv_mode == 0) slv_mode = 1;
println(hlog, "slv_mode = ", slv_mode, " tick = ", ticks); println(hlog, "slv_mode = ", slv_mode, " tick = ", ticks);
if(slv_mode == 1) { if(slv_mode == 1) {
t0 = ticks; t0 = ticks;
@@ -90,6 +131,13 @@ void set_spacerocks_ship() {
tour::slide_backup(cs.eyecolor, 0x8080FFFF); tour::slide_backup(cs.eyecolor, 0x8080FFFF);
tour::slide_backup(cs.dresscolor, 0xFFC0C0FF); tour::slide_backup(cs.dresscolor, 0xFFC0C0FF);
tour::slide_backup(cs.haircolor, 0xC0FFC0FF); tour::slide_backup(cs.haircolor, 0xC0FFC0FF);
tour::slide_backup(stdgridcolor, 0x808080FF);
tour::slide_backup(vid.multiplier_grid, 3);
tour::slide_backup(hide_kills, true);
tour::slide_backup(hide_watermark, true);
tour::slide_backup(gridbelow, true);
tour::slide_backup(nomap, false);
tour::slide_backup(mapeditor::drawplayer, true);
} }
slide relhell_tour[] = { slide relhell_tour[] = {
@@ -98,8 +146,10 @@ slide relhell_tour[] = {
"Here is Space Rocks, a clone of the classic game Asteroids. It is based on Newtonian physics: " "Here is Space Rocks, a clone of the classic game Asteroids. It is based on Newtonian physics: "
"if you accelerate, you move forever in that direction, unless you deaccelerate.", "if you accelerate, you move forever in that direction, unless you deaccelerate.",
[] (presmode mode) { [] (presmode mode) {
kills[moAsteroid] = 0;
setCanvas(mode, &ccolor::plain, [] { setCanvas(mode, &ccolor::plain, [] {
set_spacerocks_ship(); set_spacerocks_ship();
tour::slide_backup(vid.creature_scale, 0.5);
set_geometry(gEuclidSquare); set_geometry(gEuclidSquare);
set_variation(eVariation::pure); set_variation(eVariation::pure);
tour::slide_backup(land_structure, lsSingle); tour::slide_backup(land_structure, lsSingle);
@@ -116,6 +166,45 @@ slide relhell_tour[] = {
} }
}, },
{"Euclidean symmetry: formation", 10, LEGAL::ANY | QUICKGEO | NOTITLE,
"In the previous slide, time was implemented as in most games, and "
"how Newton imagined it. It is assumed that objects move on geodesics "
"(great circles) if no force is acting on them.\n\n"
"Note that, in the world of Newton and Galileo, and also in the world of Einstein's special relativity, the spacetime is perfectly symmetric. "
"You cannot really tell that you are moving (except by looking at landmarks); you can create a frame of reference and a system of coordinates "
"in which the ship is not moving and the physics are the same.\n\n"
"While the spherical space is perfectly symmetric, the spacetime as shown in this slide is not. "
"The wings of our ship do not move in straight lines (instead they move in smaller circles, which are curved). "
"If we had unchained items there, they would move towards the center of the ship, allowing the "
"captain to tell that they are moving.\n\n"
"Press 5 to see a visualization of how various parts of the ships would move if they actually moved in straight lines."
,
[] (presmode mode) {
kills[moAsteroid] = 0;
setCanvas(mode, &ccolor::plain, [] {
set_spacerocks_ship();
set_geometry(gEuclidSquare);
set_variation(eVariation::pure);
tour::slide_backup(land_structure, lsSingle);
tour::slide_backup(specialland, laAsteroids);
auto& ua = euc::eu_input;
tour::slide_backup(ua, ua);
for(int i=0; i<2; i++)
for(int j=0; j<2; j++) ua.user_axes[i][j] = i == j ? 35 : 0;
ua.twisted = false;
euc::build_torus3();
tour::slide_backup(shmup::on, true);
tour::slide_backup(pconf.scale, 0.3);
tour::slide_backup(dont_gen_asteroids, true);
tour::slide_backup(stdgridcolor, 0xC0C0C0C0);
tour::slide_backup(vid.multiplier_grid, 3);
tour::slide_backup(gridbelow, true);
});
straight_line_viz_rocks(mode);
}
},
{"Small Relativistic Effects", 10, LEGAL::ANY | QUICKGEO, {"Small Relativistic Effects", 10, LEGAL::ANY | QUICKGEO,
"In our real world, the universe is expanding, and the spaceship would observe relativistic effects if it started to move very fast. " "In our real world, the universe is expanding, and the spaceship would observe relativistic effects if it started to move very fast. "
"Such effects can be also observed in this slide, although you still need to wait for a long time or move very fast. They will be more pronounced in Relative Hell, and in the later slides.", "Such effects can be also observed in this slide, although you still need to wait for a long time or move very fast. They will be more pronounced in Relative Hell, and in the later slides.",
@@ -136,12 +225,35 @@ slide relhell_tour[] = {
rockgen.cshift = 0; rockgen.cshift = 0;
rogueviz::rv_hook(multi::hooks_handleInput, 100, [] {
if(tour_value == 0) return;
auto& act = multi::action_states[1];
if(ticks >= 1000 && ticks < 4000) act[multi::pcMoveLeft].held = true;
if(ticks >= 5500 && ticks < 8500) act[multi::pcMoveRight].held = true;
if(ticks >= 9500 && ticks < 12500) act[multi::pcMoveRight].held = true;
if(ticks >=14000 && ticks < 17000) act[multi::pcMoveLeft].held = true;
});
if(1) { if(1) {
std::mt19937 gr;
gr.seed(617);
auto randd = [&] { return (gr() % 1000000 + .5) / 1000000; };
dynamicval<eGeometry> g(geometry, gSpace435); dynamicval<eGeometry> g(geometry, gSpace435);
for(int x=-10; x<=10; x++) for(int x=-10; x<=10; x++)
for(int y=-10; y<=10; y++) if(hypot(x+0.5, y) >= 2) { for(int y=-10; y<=10; y++) if(hypot(x+0.5, y) >= 2) {
rockgen.add(cspin(0, 2, (x + randd() - randd()) / sca) * cspin(1, 2, (y + randd() - randd()) / sca)); rockgen.add(cspin(0, 2, (x + randd() - randd()) / sca) * cspin(1, 2, (y + randd() - randd()) / sca));
} }
for(int x: {-2.5}) {
auto r = rockgen.add(cspin(0, 2, x / sca) * cspin(1, 2, 0));
r->type = oResource;
r->resource = rtFuel;
r->shape = rsrc_shape[rtFuel];
r->col = rsrc_color[rtFuel];
}
} }
rockgen.cshift = 10; rockgen.cshift = 10;
@@ -167,23 +279,45 @@ slide relhell_tour[] = {
tour::slide_backup(vid.creature_scale, 1 / sca); tour::slide_backup(vid.creature_scale, 1 / sca);
tour::slide_backup(pconf.scale, sca); tour::slide_backup(pconf.scale, sca);
tour::slide_backup(texture_off, true); tour::slide_backup(texture_off, true);
tour::slide_backup(spacetime_step, spacetime_step / sca);
tour::slide_backup(spacetime_qty, spacetime_qty * 5);
dynamicval<ld> fs(future_shown, -10); dynamicval<ld> fs(future_shown, -10);
ds_restart_scaled(); ds_restart_scaled();
tour::slide_backup(invincibility_pt, HUGE_VAL); tour::slide_backup(invincibility_pt, HUGE_VAL);
rockgen.cshift = 0; rockgen.cshift = 0;
rogueviz::rv_hook(multi::hooks_handleInput, 100, [] {
if(tour_value == 0) return;
auto& act = multi::action_states[1];
if(ticks >= 16000 && ticks < 18000) act[multi::pcMoveUp].held = true;
});
if(1) { if(1) {
std::mt19937 gr;
gr.seed(617);
auto randd = [&] { return (gr() % 1000000 + .5) / 1000000; };
dynamicval<eGeometry> g(geometry, gSpace435); dynamicval<eGeometry> g(geometry, gSpace435);
for(int x=-10; x<=10; x++) for(int x=-6; x<=6; x++)
for(int y=-10; y<=10; y++) if(hypot(x+0.5, y) >= 2) { for(int y=-40; y<=10; y++) if(hypot(x+0.5, y) >= 2 && (x&1) == 1) {
rockgen.add(cspin(0, 2, (x + randd() - randd()) / sca) * cspin(1, 2, (y + randd() - randd()) / sca)); rockgen.add(cspin(0, 2, (x + (randd() - randd())/3) / sca) * cspin(1, 2, (y + randd() - randd()) / sca));
}
for(int x=-6; x<=6; x++)
for(int y=60; y<=200; y++) if((x&3) == 2) {
rockgen.add(lorentz(1, 3, -2 * ds_simspeed * ds_accel) * cspin(0, 2, (x + randd() - randd()) / sca) * cspin(1, 2, (y/2 + randd() - randd()) / sca));
}
if(true) {
rockgen.add(lorentz(3, 2, 12.5 * ds_simspeed) * cspin(1, 2, 1 / sca) * cspin(0, 2, -0.5 / sca) * lorentz(1, 3, -1 * ds_simspeed * ds_accel));
} }
for(int x=0; x<=24; x++) for(int x=0; x<=24; x++)
for(int y=-10; y<=10; y++) if(y) { for(int y=-10; y<=10; y++) if(y) {
rockgen.cshift = (rand() % 1000) / 100. / sca; rockgen.cshift = (rand() % 1000) / 100. / sca;
rockgen.add(cspin(0, 1, x * 15._deg) * cspin(1, 2, y / sca) * lorentz(0, 3, 1 + randd() * 3)); rockgen.add(lorentz(3, 2, 5 * ds_simspeed) * cspin(0, 1, x * 15._deg) * cspin(1, 2, y / sca) * lorentz(0, 3, 1 + randd() * 3));
} }
} }
@@ -205,17 +339,93 @@ slide relhell_tour[] = {
tour::slide_backup(ds_missile_rapidity, 0.5); tour::slide_backup(ds_missile_rapidity, 0.5);
tour::slide_backup(ds_accel, ds_accel * 10); tour::slide_backup(ds_accel, ds_accel * 10);
tour::slide_backup(vid.creature_scale, 5 / sca); tour::slide_backup(vid.creature_scale, 5 / sca);
tour::slide_backup(pconf.scale, sca); tour::slide_backup(pconf.scale, sca * 2);
tour::slide_backup(texture_off, true); tour::slide_backup(texture_off, true);
tour::slide_backup(view_proper_times, true); tour::slide_backup(view_proper_times, true);
tour::slide_backup(time_scale, 0.15); tour::slide_backup(time_scale, 0.15);
tour::slide_backup(disable_ds_gen, true); tour::slide_backup(disable_ds_gen, true);
tour::slide_backup(spacetime_step, spacetime_step / sca * 3);
tour::slide_backup(spacetime_qty, spacetime_qty * 500);
tour::slide_backup(ship_history_period, spacetime_step);
dynamicval<ld> fs(future_shown, -10); dynamicval<ld> fs(future_shown, -10);
ds_restart_scaled(); ds_restart_scaled();
tour::slide_backup(invincibility_pt, HUGE_VAL); tour::slide_backup(invincibility_pt, HUGE_VAL);
rogueviz::rv_hook(multi::hooks_handleInput, 100, [] {
if(tour_value == 0) return;
auto& act = multi::action_states[1];
if(ticks >= 11000 && ticks < 13000) act[multi::pcMoveUp].held = true;
if(ticks >= 13000 && ticks < 17000) act[multi::pcMoveDown].held = true;
if(ticks >= 17000 && ticks < 19000) act[multi::pcMoveUp].held = true;
});
rockgen.cshift = 10; rockgen.cshift = 10;
}); });
static ld alpha = 0;
add_temporary_hook(mode, hook_alter_replay, 100, [] {
if(tour_value == 0) return;
alpha = 0;
if(ticks >= 9000 && ticks <= 10000) {
ld t = (ticks - 9000) / 1000.;
t = t * t * (3 - 2 * t);
alpha = sin(t * TAU) * 0.5;
println(hlog, "alpha = ", alpha);
current.T = cspin(1, 0, alpha) * current.T;
}
// if(ticks >= 11000 && ticks < 13000) act[multi::pcMoveUp].held = true;
});
add_temporary_hook(mode, hooks_prestats, 50, [] {
if(tour_value == 0) return false;
dynamicval<eGeometry> g(geometry, gCubeTiling); dynamicval<eVariation> gv(variation, eVariation::pure);
dynamicval<eModel> gm(pmodel, mdPerspective); dynamicval<ld> gs(sightranges[geometry], 50);
dynamicval<ld> gw(vid.linewidth, 3 * vid.linewidth);
initquickqueue();
calcparam();
for(int w: {0, 1}) {
shiftmatrix T = shiftless(MirrorY * rgpushxto0(hyperpoint(-7, -4, 2.2, 1)));
if(w == 1) {
T = T * cspin(1, 0, -alpha);
ld rapid_gained = 0;
if(ticks >= 11000) rapid_gained += min(ticks - 11000, 2000);
if(ticks >= 13000) rapid_gained -= min(ticks - 13000, 4000);
if(ticks >= 17000) rapid_gained += min(ticks - 17000, 2000);
rapid_gained /= 1000;
auto rg = rapid_gained;
rapid_gained *= ds_simspeed;
rapid_gained *= ds_accel;
println(hlog, "rapid_gained = ", rapid_gained, " from ", rg);
T = T * lorentz(1, 2, -rapid_gained);
}
color_t col = w == 1 ? 0xFFFFFFFF : 0x8000FF;
queueline(T * hyperpoint(-0.2, 0, 0, 1), T * hyperpoint(1.2, 0, 0, 1), col);
curvepoint(hyperpoint(1.2, 0, 0, 1));
curvepoint(hyperpoint(1.1, 0.05, 0, 1));
curvepoint(hyperpoint(1.1, -0.05, 0, 1));
curvepoint(hyperpoint(1.2, 0, 0, 1));
queuecurve(T, 0, col, PPR::LINE);
latex_in_space(T * eupush(hyperpoint(1.2, 0.2, 0, 1)) * MirrorY, 0.002, "$x$", col, 0);
queueline(T * hyperpoint(0,-0.2, 0, 1), T * hyperpoint(0, 1.2, 0, 1), col);
curvepoint(hyperpoint(0, 1.2, 0, 1));
curvepoint(hyperpoint(+0.05, 1.1, 0, 1));
curvepoint(hyperpoint(-0.05, 1.1, 0, 1));
curvepoint(hyperpoint(0, 1.2, 0, 1));
queuecurve(T, 0, col, PPR::LINE);
latex_in_space(T * eupush(hyperpoint(0.2, 1.2, 0, 1)) * MirrorY, 0.002, "$y$", col, 0);
queueline(T * hyperpoint(0,0,-0.2, 1), T * hyperpoint(0, 0, 1.2, 1), col);
curvepoint(hyperpoint(0, 0, 1.2, 1));
curvepoint(hyperpoint(+0.05, -0.05, 1.1, 1));
curvepoint(hyperpoint(-0.05, 0.05, 1.1, 1));
curvepoint(hyperpoint(0, 0, 1.2, 1));
queuecurve(T, 0, col, PPR::LINE);
latex_in_space(T * eupush(hyperpoint(0, -0.2, 1.2, 1)) * MirrorY, 0.002, "$t$", col, 0);
}
quickqueue();
return true;
});
} }
}, },
@@ -224,6 +434,7 @@ slide relhell_tour[] = {
"Here is Space Rocks played in spherical geometry. It uses " "Here is Space Rocks played in spherical geometry. It uses "
"stereographic projection so that a big part of the sphere can be seen. (You can press '5' to switch to and from the orthogonal projection.)", "stereographic projection so that a big part of the sphere can be seen. (You can press '5' to switch to and from the orthogonal projection.)",
[] (presmode mode) { [] (presmode mode) {
kills[moAsteroid] = 0;
setCanvas(mode, &ccolor::plain, [] { setCanvas(mode, &ccolor::plain, [] {
set_spacerocks_ship(); set_spacerocks_ship();
set_geometry(gSphere); set_geometry(gSphere);
@@ -234,6 +445,7 @@ slide relhell_tour[] = {
tour::slide_backup(pconf.scale, 0.5); tour::slide_backup(pconf.scale, 0.5);
tour::slide_backup(pconf.alpha, 1); tour::slide_backup(pconf.alpha, 1);
tour::slide_backup(vid.monmode, 2); tour::slide_backup(vid.monmode, 2);
tour::slide_backup(vid.aurasmoothen, 90);
}); });
if(mode == pmKey) { if(mode == pmKey) {
if(pconf.alpha == 1) pconf.alpha = 1000, pconf.scale = 950; if(pconf.alpha == 1) pconf.alpha = 1000, pconf.scale = 950;
@@ -242,7 +454,7 @@ slide relhell_tour[] = {
} }
}, },
{"Spherical symmetry", 10, LEGAL::ANY | QUICKGEO | NOTITLE, {"Spherical symmetry: formation", 10, LEGAL::ANY | QUICKGEO | NOTITLE,
"In the previous slide, time was implemented as in most games, and " "In the previous slide, time was implemented as in most games, and "
"how Newton imagined it. It is assumed that objects move on geodesics " "how Newton imagined it. It is assumed that objects move on geodesics "
"(great circles) if no force is acting on them.\n\n" "(great circles) if no force is acting on them.\n\n"
@@ -257,6 +469,44 @@ slide relhell_tour[] = {
, ,
[] (presmode mode) { [] (presmode mode) {
kills[moAsteroid] = 0;
setCanvas(mode, &ccolor::plain, [] {
set_spacerocks_ship();
set_geometry(gSphere);
set_variation(eVariation::bitruncated);
tour::slide_backup(land_structure, lsSingle);
tour::slide_backup(specialland, laAsteroids);
tour::slide_backup(shmup::on, true);
tour::slide_backup(pconf.scale, 0.5);
tour::slide_backup(pconf.alpha, 1);
tour::slide_backup(vid.monmode, 2);
tour::slide_backup(vid.creature_scale, 0.5);
tour::slide_backup(dont_gen_asteroids, true);
// tour::slide_backup(stdgridcolor, 0x808080FF);
tour::slide_backup(stdgridcolor, 0xC0C0C0C0);
tour::slide_backup(vid.multiplier_grid, 3);
tour::slide_backup(gridbelow, true);
});
straight_line_viz_rocks(mode);
}
},
{"Spherical symmetry: forces", 10, LEGAL::ANY | QUICKGEO | NOTITLE,
"In the previous slide, time was implemented as in most games, and "
"how Newton imagined it. It is assumed that objects move on geodesics "
"(great circles) if no force is acting on them.\n\n"
"Note that, in the world of Newton and Galileo, and also in the world of Einstein's special relativity, the spacetime is perfectly symmetric. "
"You cannot really tell that you are moving (except by looking at landmarks); you can create a frame of reference and a system of coordinates "
"in which the ship is not moving and the physics are the same.\n\n"
"While the spherical space is perfectly symmetric, the spacetime as shown in this slide is not. "
"The wings of our ship do not move in straight lines (instead they move in smaller circles, which are curved). "
"If we had unchained items there, they would move towards the center of the ship, allowing the "
"captain to tell that they are moving.\n\n"
"Press 5 to see a visualization of how various parts of the ships would move if they actually moved in straight lines."
,
[] (presmode mode) {
kills[moAsteroid] = 0;
setCanvas(mode, &ccolor::plain, [] { setCanvas(mode, &ccolor::plain, [] {
set_spacerocks_ship(); set_spacerocks_ship();
set_geometry(gSphere); set_geometry(gSphere);
@@ -274,7 +524,7 @@ slide relhell_tour[] = {
} }
}, },
{"de Sitter spacetime", 10, LEGAL::ANY | QUICKGEO, {"empty de Sitter spacetime", 10, LEGAL::ANY | QUICKGEO,
"The de Sitter spacetime is a way to add time to spherical geometry in a symmetric way. " "The de Sitter spacetime is a way to add time to spherical geometry in a symmetric way. "
"The space here feels to expand exponentially as the time passes, as in, nearby objects get farther and farther away. " "The space here feels to expand exponentially as the time passes, as in, nearby objects get farther and farther away. "
"Still, the spacetime is symmetric -- if we are using an appropriate frame of reference, the 'totally geodesic' slice of spacetime at t=0 is " "Still, the spacetime is symmetric -- if we are using an appropriate frame of reference, the 'totally geodesic' slice of spacetime at t=0 is "
@@ -288,10 +538,12 @@ slide relhell_tour[] = {
tour::slide_backup(ds_simspeed, M_PI / 10); tour::slide_backup(ds_simspeed, M_PI / 10);
// tour::slide_backup(ds_scale, 1); // tour::slide_backup(ds_scale, 1);
tour::slide_backup(pconf.scale, 1); tour::slide_backup(pconf.scale, 1);
dynamicval<ld> fs(future_shown, -10); tour::slide_backup(disable_ds_gen, true);
dynamicval<ld> fs(future_shown, -20);
ds_restart(); ds_restart();
rockgen.cshift = 10; rockgen.cshift = 20;
rsrcgen.cshift = 20;
}); });
if(mode == pmStart) { if(mode == pmStart) {
add_ds_cleanup(); add_ds_cleanup();
@@ -300,9 +552,8 @@ slide relhell_tour[] = {
} }
}, },
{"de Sitter game", 10, LEGAL::ANY | QUICKGEO, {"full de Sitter game", 10, LEGAL::ANY | QUICKGEO,
"The de Sitter part of the Relative Hell game takes part in this spacetime. " "And here is the full game. If required, you can "
"Try to stay close to the yellow star as long as possible! If required, you can "
"shoot down stars with a limited number of missiles. For high score, you will also need to replenish your " "shoot down stars with a limited number of missiles. For high score, you will also need to replenish your "
"resources by capturing free-flying fuel, oxygen, health, and missiles.", "resources by capturing free-flying fuel, oxygen, health, and missiles.",
@@ -321,6 +572,7 @@ slide relhell_tour[] = {
"you can press 5 to switch to the Beltrami-Klein model.\n\n", "you can press 5 to switch to the Beltrami-Klein model.\n\n",
[] (presmode mode) { [] (presmode mode) {
kills[moAsteroid] = 0;
setCanvas(mode, &ccolor::plain, [] { setCanvas(mode, &ccolor::plain, [] {
set_spacerocks_ship(); set_spacerocks_ship();
set_geometry(gKleinQuartic); set_geometry(gKleinQuartic);
@@ -339,11 +591,40 @@ slide relhell_tour[] = {
} }
}, },
{"Hyperbolic symmetry", 10, LEGAL::ANY | QUICKGEO | NOTITLE, {"Hyperbolic symmetry: formation", 10, LEGAL::ANY | QUICKGEO | NOTITLE,
"Of course, just like in spherical space, this is not a symmetric spacetime.\n\n" "Of course, just like in spherical space, this is not a symmetric spacetime.\n\n"
"Press 5 to see a visualization of how various parts of the ships would move if they actually moved in straight lines.", "Press 5 to see a visualization of how various parts of the ships would move if they actually moved in straight lines.",
[] (presmode mode) { [] (presmode mode) {
kills[moAsteroid] = 0;
setCanvas(mode, &ccolor::plain, [] {
set_spacerocks_ship();
set_geometry(gKleinQuartic);
set_variation(eVariation::bitruncated);
tour::slide_backup(land_structure, lsSingle);
tour::slide_backup(specialland, laAsteroids);
tour::slide_backup(shmup::on, true);
tour::slide_backup(pconf.scale, 0.95);
tour::slide_backup(pconf.alpha, 1);
tour::slide_backup(vid.monmode, 2);
tour::slide_backup(dont_gen_asteroids, true);
tour::slide_backup(vid.linequality, 3);
tour::slide_backup(vid.creature_scale, 0.3);
// tour::slide_backup(stdgridcolor, 0x808080FF);
tour::slide_backup(stdgridcolor, 0xC0C0C0C0);
tour::slide_backup(vid.multiplier_grid, 3);
tour::slide_backup(gridbelow, true);
});
straight_line_viz_rocks(mode);
}
},
{"Hyperbolic symmetry: forces", 10, LEGAL::ANY | QUICKGEO | NOTITLE,
"Of course, just like in spherical space, this is not a symmetric spacetime.\n\n"
"Press 5 to see a visualization of how various parts of the ships would move if they actually moved in straight lines.",
[] (presmode mode) {
kills[moAsteroid] = 0;
setCanvas(mode, &ccolor::plain, [] { setCanvas(mode, &ccolor::plain, [] {
set_spacerocks_ship(); set_spacerocks_ship();
set_geometry(gKleinQuartic); set_geometry(gKleinQuartic);
@@ -361,10 +642,81 @@ slide relhell_tour[] = {
} }
}, },
{"anti-de Sitter spacetime", 10, LEGAL::ANY | QUICKGEO | NOTITLE, {"anti-de Sitter spacetime: rocks", 10, LEGAL::ANY | QUICKGEO | NOTITLE,
"anti-de Sitter spacetime is a way to add time to this space in a symmetric way.\n\n" "anti-de Sitter spacetime is a way to add time to this space in a symmetric way.\n\n"
"Because of how the anti-de Sitter spacetime works, faraway objects are 'pulled' towards us. " "Because of how the anti-de Sitter spacetime works, faraway objects are 'pulled' towards us. "
"You can see this effect by shooting a missile -- it will eventually return to us!\n\n" "Here is an almost empty anti-de Sitter space, with some rocks. See how they are pulled towards "
"the center."
,
[] (presmode mode) {
setCanvas(mode, &ccolor::plain, [] {
rogueviz::on_cleanup_or_next([] { lps_enable(nullptr); });
ads_game::run_ads_game_std();
stop_game();
run_ads_game();
tour::slide_backup(changed_structure, true);
tour::slide_backup(specialland, laAsteroids);
// tour::slide_backup(specialland, laCrossroads);
tour::slide_backup(land_structure, lsSingle);
run_ads_game();
/* disable everything */
tour::slide_backup(pconf.alpha, 1);
tour::slide_backup(keep_ship_angle, true);
rogueviz::rv_hook(hooks_frame, 100, [] {
for(int i=0; i<360; i++) addaura(shiftless(xspinpush0(i*1._deg, 1)), 0xFFFFFF, 0);
});
for(int i=0; i<50; i++) hybrid::in_actual([&] {
add_rock(cwt.at, ci_at[cwt.at],
// ads_matrix(Id) * spin(rand() % 100) * twist::uxpush(0.5 + (rand() % 100)/50.) * spin(rand() % 2 ? -90._deg : 90._deg) * lorentz(0, 3, 0.2 + (rand() % 100) / 100.)
ads_matrix(Id) * spin(rand() % 100) * lorentz(0, 3, 0.5 + (rand() % 100)/40.) * spin(rand() % 2 ? -90._deg : 90._deg) * lorentz(0, 2, 0.2 + (rand() % 100) / 50.)
);
});
});
}
},
{"anti-de Sitter spacetime: missiles", 10, LEGAL::ANY | QUICKGEO | NOTITLE,
"You can also see this effect by shooting a missile -- it will eventually return to us!\n\n"
"Then, press 5 to see a replay from the missile's point of view."
,
[] (presmode mode) {
setCanvas(mode, &ccolor::plain, [] {
rogueviz::on_cleanup_or_next([] { lps_enable(nullptr); });
ads_game::run_ads_game_std();
stop_game();
run_ads_game();
tour::slide_backup(changed_structure, true);
tour::slide_backup(specialland, laAsteroids);
// tour::slide_backup(specialland, laCrossroads);
tour::slide_backup(land_structure, lsSingle);
run_ads_game();
/* disable everything */
tour::slide_backup(pconf.alpha, 1);
tour::slide_backup(keep_ship_angle, true);
rogueviz::rv_hook(hooks_frame, 100, [] {
for(int i=0; i<360; i++) addaura(shiftless(xspinpush0(i*1._deg, 1)), 0xFFFFFF, 0);
});
tour::slide_backup(time_shift, 0.2);
tour::slide_backup(ads_time_unit, 1);
tour::slide_backup(view_proper_times, true);
});
if(mode == pmStart) tour::slide_backup(missile_replay, missile_replay);
if(mode == pmKey) {
switch_replay();
missile_replay = !missile_replay;
}
if(mode == pmStop && in_replay) switch_replay();
}
},
{"anti-de Sitter spacetime: world", 10, LEGAL::ANY | QUICKGEO | NOTITLE,
"In the world of Relative Hell, this pull is countered by making the static objects rotate in a specific way -- this creates a centrifugal " "In the world of Relative Hell, this pull is countered by making the static objects rotate in a specific way -- this creates a centrifugal "
"force which counterbalances this effect. As you can see, the heptagons further away are " "force which counterbalances this effect. As you can see, the heptagons further away are "
"squashed -- this is again the Lorentz contraction\n\n." "squashed -- this is again the Lorentz contraction\n\n."
@@ -454,6 +806,7 @@ slide relhell_tour[] = {
[] (presmode mode) { [] (presmode mode) {
setCanvas(mode, &ccolor::plain, [] { setCanvas(mode, &ccolor::plain, [] {
rogueviz::on_cleanup_or_next([] { lps_enable(nullptr); }); rogueviz::on_cleanup_or_next([] { lps_enable(nullptr); });
tour::slide_backup(turret_limit, 1);
ads_game::run_ads_game_std(); ads_game::run_ads_game_std();
tour::slide_backup(pconf.alpha, 1); tour::slide_backup(pconf.alpha, 1);
rv_hook(hooks_pre_ads_start, 100, [] { rv_hook(hooks_pre_ads_start, 100, [] {
@@ -512,14 +865,70 @@ slide relhell_tour[] = {
{\color{remph}3-dimensional Euclidean space:} {\color{remph}3-dimensional Euclidean space:}
\begin{itemize} \begin{itemize}
\item $\bbE^3 = \{(x,y,z): x,y,z \in \bbR\}$ \item $\bbE^3 = \{(x,y,z): x,y,z \in \bbR\}$
\item squared distance between \\ points $(x_1,y_1,z_1)$ and $(x_2, y_2, z_2)$ is \[(x_1-x_2)^2+(y_1-y_2)^2+(z_1-z_2)^2\] \item squared distance between \\ points $(x_1,y_1,z_1)$ and $(x_2, y_2, z_2)$ is \[(x_1-x_2)^2+(y_1-y_2)^2+(z_1-z_2)^2\rule{3cm}{0cm}\]
\item {\color{remph} isometries} (rotations, etc.) preserve this squared distance \item {\color{remph} isometries} (rotations, etc.) \\ preserve this squared distance
\end{itemize} \end{itemize}
)=", sm::SIDE, 90); )=", sm::SIDE, 90);
static int start = -1;
static int anim_start = -1;
if(mode == pmKey) start = (start == -1) ? ticks : -1;
if(mode == pmKeyAlt) anim_start = ticks;
if(mode == pmStart) { if(mode == pmStart) {
tour::slide_backup(mapeditor::drawplayer, false); tour::slide_backup(mapeditor::drawplayer, false);
tour::slide_backup(vid.axes, 0); tour::slide_backup(vid.axes, 0);
tour::slide_backup(pconf.scale, 0.5);
tour::slide_backup(vid.use_smart_range, 2);
tour::slide_backup(vid.smart_range_detail, 1);
tour::slide_backup(pconf.xposition, -0.4);
rogueviz::rv_hook(hooks_latex_slide, 100, [] { dialog::dwidth += 500; menu_darkening++; dialog::draw_side_shade(); dialog::dwidth -= 500; menu_darkening --; }); rogueviz::rv_hook(hooks_latex_slide, 100, [] { dialog::dwidth += 500; menu_darkening++; dialog::draw_side_shade(); dialog::dwidth -= 500; menu_darkening --; });
View = Id;
static ld t;
rogueviz::rv_hook(anims::hooks_anim, 101, [] {
if(anim_start >= 0) {
ld t = (ticks - anim_start) / 4000.;
if(t >= 1) t = 1;
centerover = currentmap->gamestart();
View = ypush(t * t * (3 - 2 * t));
}
if(start != -1) {
t = (ticks - start) / 5000.;
if(t < 1) t *= t;
else t = 2 * t - 1;
}
View = spin(t) * View;
anims::moved();
});
rogueviz::rv_hook(hooks_frame, 101, [] {
if(!nomap) for(int s: {0, 1}) {
color_t axecolor = s == 0 ? 0x80C080FF : 0x008000FF;
shiftmatrix S = shiftless(s == 0 ? View : Id);
vid.linewidth *= 3;
if(s == 0 && (tour_value != 1 || ticks >= 13000)) {
vid.linewidth *= 3;
for(ld v=0; v<=TAU; v+=0.01) curvepoint(hyperpoint(sin(v), cos(v), 1, 1)); queuecurve(S, 0xFFC0C0FF, 0, PPR::LINE);
vid.linewidth /= 3;
}
curvepoint(hyperpoint(2.1,0,1,1)); curvepoint(hyperpoint(-2.1,0,1,1)); queuecurve(S, axecolor, 0, PPR::LINE);
curvepoint(hyperpoint(0,2.1,1,1)); curvepoint(hyperpoint(0,-2.1,1,1)); queuecurve(S, axecolor, 0, PPR::LINE);
latex_in_space(S * eupush(hyperpoint(2.2, 0.2, 1, 1)), 0.002, "$x$", axecolor, 0);
latex_in_space(S * eupush(hyperpoint(0.2, -2.2, 1, 1)), 0.002, "$y$", axecolor, 0);
for(int x: {-2, -1, 1, 2}) {
curvepoint(hyperpoint(x,0.1,1,1)); curvepoint(hyperpoint(x,-0.1,1,1)); queuecurve(S, axecolor, 0, PPR::LINE);
curvepoint(hyperpoint(0.1,x,1,1)); curvepoint(hyperpoint(-0.1,x,1,1)); queuecurve(S, axecolor, 0, PPR::LINE);
}
vid.linewidth /= 3;
curvepoint(hyperpoint(2.1,0.1,1,1)); curvepoint(hyperpoint(2.3,0,1,1)); curvepoint(hyperpoint(2.1,-0.1,1,1));
queuecurve(S, 0, axecolor, PPR::LINE);
curvepoint(hyperpoint(0.1,-2.1,1,1)); curvepoint(hyperpoint(0,-2.3,1,1)); curvepoint(hyperpoint(-0.1,-2.1,1,1));
queuecurve(S, 0, axecolor, PPR::LINE);
}
});
} }
}}, }},
@@ -533,17 +942,33 @@ slide relhell_tour[] = {
"light-like (squared distance = 0) and time-like (squared distance < 0), but if we have a point and direction, we have an isometry that " "light-like (squared distance = 0) and time-like (squared distance < 0), but if we have a point and direction, we have an isometry that "
"takes it into any other point and direction of the same type.", "takes it into any other point and direction of the same type.",
[] (presmode mode) { [] (presmode mode) {
latex_slide(mode, defs+R"=( string s = "";
if(!tour_value || ticks >= 9000) {
s = "\\definecolor{rcsl}{rgb}{0,0.75,0}\n\\definecolor{rtsl}{rgb}{0,0,1}\n\\definecolor{rsign}{rgb}{1,0.25,0.25}\n";
if(ticks >= 19000 || !tour_value)
s += "\\def\\csl#1{{\\color{rcsl}#1}}\n\\def\\tsl#1{{\\color{rtsl}#1}}\n\\def\\hlsign#1{{\\color{rsign}#1}}\n";
else if(ticks >= 11000)
s += "\\def\\csl#1{{\\color{rcsl}#1}}\n\\def\\tsl#1{{\\color{rtsl}#1}}\n\\def\\hlsign#1{{#1}}\n";
else if(ticks >= 9000)
s += "\\def\\csl#1{{\\color{rcsl}#1}}\n\\def\\tsl#1{{#1}}\n\\def\\hlsign#1{{#1}}\n";
}
else {
s = "\\def\\csl#1{{#1}}\n\\def\\tsl#1{{#1}}\n\\def\\hlsign#1{{#1}}\n";
}
latex_slide(mode, defs+s+R"=(
{\color{remph}Minkowski spacetime with 2 space and 1 time dimension:} {\color{remph}Minkowski spacetime with 2 space and 1 time dimension:}
\begin{itemize} \begin{itemize}
\item $\bbE^{2,1} = \{(x,y,t): x,y,t \in \bbR\}$ \item $\bbE^{2,1} = \{(\csl{x,y},\tsl{t}): \csl{x,y},\tsl{t} \in \bbR\}$
\item spacetime interval between \\ points $(x_1,y_1,t_1)$ and $(x_2, y_2, t_2)$ is \[(x_1-x_2)^2+(y_1-y_2)^2-(t_1-t_2)^2\] \item spacetime interval (``squared distance'') between \\ points $(\csl{x_1,y_1},\tsl{t_1})$ and $(\csl{x_2, y_2}, \tsl{t_2})$ is \[\csl{(x_1-x_2)^2\hlsign{+}(y_1-y_2)^2}\tsl{\hlsign{-}(t_1-t_2)^2}\rule{3cm}{0cm}\]
\item {\color{remph} Lorentz transformations} preserve this \item {\color{remph} Lorentz transformations} preserve this
\end{itemize} \end{itemize}
\rule{0cm}{3cm}
)=", sm::SIDE, 90); )=", sm::SIDE, 90);
setCanvas(mode, &ccolor::chessboard, [] { set_geometry(gEuclidSquare); set_variation(eVariation::pure); tour::slide_backup(vid.axes, 0); }); setCanvas(mode, &ccolor::chessboard, [] { set_geometry(gEuclidSquare); set_variation(eVariation::pure); tour::slide_backup(vid.axes, 0); });
static int start = -1; static int start = -1;
static int hilite = 0;
if(mode == pmKey) start = (start == -1) ? ticks : -1; if(mode == pmKey) start = (start == -1) ? ticks : -1;
if(mode == pmKeyAlt) hilite++;
if(mode == pmStart) { if(mode == pmStart) {
tour::slide_backup(anims::ma, anims::maTranslation); tour::slide_backup(anims::ma, anims::maTranslation);
tour::slide_backup(pconf.stretch, 1); tour::slide_backup(pconf.stretch, 1);
@@ -553,21 +978,77 @@ slide relhell_tour[] = {
tour::slide_backup(vid.axes, 0); tour::slide_backup(vid.axes, 0);
tour::slide_backup(vid.use_smart_range, 2); tour::slide_backup(vid.use_smart_range, 2);
tour::slide_backup(vid.smart_range_detail, 1); tour::slide_backup(vid.smart_range_detail, 1);
static ld t;
rogueviz::rv_hook(hooks_frame, 101, [] { rogueviz::rv_hook(hooks_frame, 101, [] {
if(start == -1) { anims::cycle_length = 0; pconf.stretch = 1; return; } if(start == -1) { anims::cycle_length = 0; pconf.stretch = 1; t = 0; return; }
ld t = asinh((ticks - start) / 5000.); t = (ticks - start) / 5000.;
anims::cycle_length = sinh(t) * 10; if(tour_value && t > 1) t = 1;
if(tour_value && ticks - start > 45000)
t = t - (ticks - start - 45000) / 5000.;
t = asinh(t);
anims::cycle_length = sinh(t) * 10 * anims::period / 10000;
pconf.stretch = sqrt(1 - tanh(t) * tanh(t)); pconf.stretch = sqrt(1 - tanh(t) * tanh(t));
println(hlog, "t=", t, "sinh = ", anims::cycle_length, " stretch = ", pconf.stretch); println(hlog, "t=", t, "sinh = ", anims::cycle_length, " stretch = ", pconf.stretch);
}); });
rogueviz::rv_hook(hooks_latex_slide, 100, [] { rogueviz::rv_hook(hooks_latex_slide, 100, [] {
initquickqueue(); initquickqueue();
dynamicval<ld> s(pconf.stretch, 1); dynamicval<ld> s(pconf.stretch, 1);
drawMonsterType(moRunDog, nullptr, shiftless(spin(90._deg)), 0xFFFFFFFF, start >= 0 ? (ticks-start) / 500. : 0, 0xFFFFFFFF); drawMonsterType(moRunDog, nullptr, shiftless(spin(t >= 0 ? 90._deg : -90._deg)), 0xFFFFFFFF, start >= 0 ? (ticks-start) / 500. : 0, 0xFFFFFFFF);
sortquickqueue(); sortquickqueue();
quickqueue(); quickqueue();
dialog::dwidth += 500; menu_darkening++; dialog::draw_side_shade(); dialog::dwidth -= 500; menu_darkening --; dialog::dwidth += 500; menu_darkening++; dialog::draw_side_shade(); dialog::dwidth -= 500; menu_darkening --;
}); });
rogueviz::rv_hook(hooks_post_latex_slide, 100, [] {
dynamicval<ld> s(pconf.stretch, 1);
if(true) for(int s: {0, 1}) {
vid.linewidth *= 2;
initquickqueue();
color_t axecolor = s == 0 ? 0x80C080FF : 0x00C000FF;
color_t axecolor2 = s == 0 ? 0x8080C0FF : 0x0000FFFF;
shiftmatrix S = shiftless(eupush(3, 1.1) * euscale(0.4, 0.4));
ld gs = 2.45;
if(s == 0 && (!tour_value || ticks >= 32000)) for(int a=0; a<4; a++) {
vid.linewidth *= 3;
for(ld v=-1.5; v<=1.5; v+=0.01) curvepoint(hyperpoint(sinh(v), cosh(v), 1, 1)); queuecurve(S * spin(90._deg*a), 0xFFC0C0FF, 0, PPR::LINE);
vid.linewidth /= 3;
}
if(s==0) if(hilite == 3 || hilite == 4 || !tour_value) {
curvepoint(hyperpoint(gs,gs,1,1)); curvepoint(hyperpoint(-gs,gs,1,1)); curvepoint(hyperpoint(0,0,1,1)); queuecurve(S, 0, axecolor2 & 0xFFFFFF80, PPR::LINE);
curvepoint(hyperpoint(gs,-gs,1,1)); curvepoint(hyperpoint(-gs,-gs,1,1)); curvepoint(hyperpoint(0,0,1,1)); queuecurve(S, 0, axecolor2 & 0xFFFFFF80, PPR::LINE);
}
if(s==0) if(hilite == 1 || hilite == 4 || !tour_value) {
curvepoint(hyperpoint(gs,gs,1,1)); curvepoint(hyperpoint(gs,-gs,1,1)); curvepoint(hyperpoint(0,0,1,1)); queuecurve(S, 0, axecolor & 0xFFFFFF80, PPR::LINE);
curvepoint(hyperpoint(-gs,-gs,1,1)); curvepoint(hyperpoint(-gs,gs,1,1)); curvepoint(hyperpoint(0,0,1,1)); queuecurve(S, 0, axecolor & 0xFFFFFF80, PPR::LINE);
}
if(s==0) if(hilite == 2 || hilite == 4 || !tour_value) {
vid.linewidth *= 3;
curvepoint(hyperpoint(gs,gs,1,1)); curvepoint(hyperpoint(-gs,-gs,1,1)); curvepoint(hyperpoint(0,0,1,1)); queuecurve(S, 0x00C0C0FF, 0, PPR::LINE);
curvepoint(hyperpoint(gs,-gs,1,1)); curvepoint(hyperpoint(-gs,gs,1,1)); curvepoint(hyperpoint(0,0,1,1)); queuecurve(S, 0x00C0C0FF, 0, PPR::LINE);
vid.linewidth /= 3;
}
if(s == 0) S = S * lorentz(0, 1, t);
vid.linewidth *= 3;
curvepoint(hyperpoint(2.1,0,1,1)); curvepoint(hyperpoint(-2.1,0,1,1)); queuecurve(S, axecolor, 0, PPR::LINE);
curvepoint(hyperpoint(0,2.1,1,1)); curvepoint(hyperpoint(0,-2.1,1,1)); queuecurve(S, axecolor2, 0, PPR::LINE);
latex_in_space(S * eupush(hyperpoint(2.2, 0.2, 0, 1)), 0.002, "$y$", axecolor, 0);
latex_in_space(S * eupush(hyperpoint(0.2, -2.2, 0, 1)), 0.002, "$t$", axecolor2, 0);
for(int x: {-2, -1, 1, 2}) {
curvepoint(hyperpoint(x,0.1,1,1)); curvepoint(hyperpoint(x,-0.1,1,1)); queuecurve(S, axecolor, 0, PPR::LINE);
curvepoint(hyperpoint(0.1,x,1,1)); curvepoint(hyperpoint(-0.1,x,1,1)); queuecurve(S, axecolor2, 0, PPR::LINE);
}
vid.linewidth /= 3;
curvepoint(hyperpoint(2.1,0.1,1,1)); curvepoint(hyperpoint(2.3,0,1,1)); curvepoint(hyperpoint(2.1,-0.1,1,1));
queuecurve(S, 0, axecolor, PPR::LINE);
curvepoint(hyperpoint(0.1,-2.1,1,1)); curvepoint(hyperpoint(0,-2.3,1,1)); curvepoint(hyperpoint(-0.1,-2.1,1,1));
queuecurve(S, 0, axecolor2, PPR::LINE);
quickqueue();
vid.linewidth /= 2;
}
});
} }
}}, }},
@@ -585,7 +1066,11 @@ slide relhell_tour[] = {
tour::slide_backup(pconf.alpha, 1000); tour::slide_backup(pconf.alpha, 1000);
tour::slide_backup(mapeditor::drawplayer, false); tour::slide_backup(mapeditor::drawplayer, false);
tour::slide_backup(vid.axes, 0); tour::slide_backup(vid.axes, 0);
tour::slide_backup(pconf.xposition, -0.25);
tour::slide_backup(anims::ma, anims::maTranslation);
tour::slide_backup(anims::cycle_length, 0);
} }
if(mode == pmKey) anims::cycle_length = 10 - anims::cycle_length;
latex_slide(mode, defs+R"=( latex_slide(mode, defs+R"=(
{\color{remph}2-dimensional sphere:} {\color{remph}2-dimensional sphere:}
\begin{itemize} \begin{itemize}
@@ -594,6 +1079,19 @@ slide relhell_tour[] = {
\item {\color{remph} isometries} (rotations, etc.) keep this distance \item {\color{remph} isometries} (rotations, etc.) keep this distance
\end{itemize} \end{itemize}
)=", sm::SIDE, 90); )=", sm::SIDE, 90);
static bool arcs = false;
if(mode == pmKeyAlt) arcs = !arcs;
if(mode == pmStart) rogueviz::rv_hook(hooks_post_latex_slide, 100, [] {
if(!arcs) return;
initquickqueue();
vid.linewidth *= 15;
for(int a=0; a<=6; a++) {
for(ld v=-1; v<=1; v+=0.01) curvepoint(cspin(0, 2, 15._deg * a) * hyperpoint(-cos(v), sin(v), 0, 1));
queuecurve(shiftless(Id), 0xFF8080FF, 0, PPR::LINE);
}
vid.linewidth /= 15;
quickqueue();
});
}}, }},
{"hyperbolic geometry", 999, LEGAL::NONE | QUICKGEO | USE_SLIDE_NAME | NOTITLE, {"hyperbolic geometry", 999, LEGAL::NONE | QUICKGEO | USE_SLIDE_NAME | NOTITLE,
@@ -606,10 +1104,18 @@ slide relhell_tour[] = {
"also employ an extra coordinate, and it is straightforward to apply 3D engines to work with " "also employ an extra coordinate, and it is straightforward to apply 3D engines to work with "
"spherical and hyperbolic geometry too, using these models.", "spherical and hyperbolic geometry too, using these models.",
[] (presmode mode) { [] (presmode mode) {
latex_slide(mode, defs+R"=( string s = "";
{\color{remph}2-dimensional hyperbolic space (Minkowski hyperboloid model):} if(!tour_value || ticks >= 13000) {
s = "\\definecolor{rcsl}{rgb}{0,0.75,0}\n\\definecolor{rtsl}{rgb}{0,0,1}\n\\definecolor{rsign}{rgb}{1,0.25,0.25}\n";
s += "\\def\\csl#1{{\\color{rcsl}#1}}\n\\def\\tsl#1{{\\color{rtsl}#1}}\n\\def\\hlsign#1{{\\color{rsign}#1}}\n";
}
else {
s = "\\def\\csl#1{{#1}}\n\\def\\tsl#1{{#1}}\n\\def\\hlsign#1{{#1}}\n";
}
latex_slide(mode, defs+s+R"=(
{\color{remph}2-dimensional hyperbolic space \\ (Minkowski hyperboloid model):}
\begin{itemize} \begin{itemize}
\item $\bbH^2 = \{(x,y,t) \in \bbE^{2,1}: x^2+y^2-t^2=-1, t>0\}$ \item $\bbH^2 = \{(\csl{x,y},\tsl{t}) \in \bbE^{2,1}: \csl{x^2\hlsign{+}y^2}\hlsign{-}\tsl{t^2}=-1, t>0\}$
\item distances measured as \\ the lengths of curves in $\bbE^{2,1}$ \item distances measured as \\ the lengths of curves in $\bbE^{2,1}$
\item {\color{remph} isometries} (rotations, etc.) keep this distance \item {\color{remph} isometries} (rotations, etc.) keep this distance
\item we get the Poincaré model by projecting \\ $(x,y,t) \mapsto (\frac{x}{t+1}, \frac{y}{t+1})$ \item we get the Poincaré model by projecting \\ $(x,y,t) \mapsto (\frac{x}{t+1}, \frac{y}{t+1})$
@@ -617,15 +1123,19 @@ slide relhell_tour[] = {
)=", sm::SIDE, 90); )=", sm::SIDE, 90);
setCanvas(mode, &ccolor::football, [] { setCanvas(mode, &ccolor::football, [] {
tour::slide_backup(pconf.model, mdHyperboloid); tour::slide_backup(pconf.model, mdHyperboloid);
tour::slide_backup(pconf.scale, pconf.scale * 0.5); tour::slide_backup(pconf.scale, pconf.scale * 1);
tour::slide_backup(vid.multiplier_ring, 3);
tour::slide_backup(pconf.ball(), cspin(1, 2, -20._deg)); tour::slide_backup(pconf.ball(), cspin(1, 2, -20._deg));
tour::slide_backup(mapeditor::drawplayer, false); tour::slide_backup(mapeditor::drawplayer, false);
tour::slide_backup(vid.axes, 0); tour::slide_backup(vid.axes, 0);
rogueviz::rv_hook(hooks_latex_slide, 100, [] { dialog::dwidth += 500; menu_darkening++; dialog::draw_side_shade(); dialog::dwidth -= 500; menu_darkening --; }); rogueviz::rv_hook(hooks_latex_slide, 100, [] { dialog::dwidth += 500; menu_darkening++; dialog::draw_side_shade(); dialog::dwidth -= 500; menu_darkening --; });
tour::slide_backup(anims::ma, anims::maTranslation);
tour::slide_backup(anims::cycle_length, 0);
}); });
if(mode == pmKey) anims::cycle_length = 10 - anims::cycle_length;
}}, }},
{"anti-de Sitter spacetime", 999, LEGAL::NONE | QUICKGEO | USE_SLIDE_NAME | NOTITLE, {"anti-de Sitter geometry", 999, LEGAL::NONE | QUICKGEO | USE_SLIDE_NAME | NOTITLE,
"Here is how we add a time coordinate to the hyperbolic plane, in order to get 2+1D anti-de Sitter spacetime. " "Here is how we add a time coordinate to the hyperbolic plane, in order to get 2+1D anti-de Sitter spacetime. "
"As you can see, the construction is quite similar, and again, we get a maximally symmetric spacetime.\n\n" "As you can see, the construction is quite similar, and again, we get a maximally symmetric spacetime.\n\n"
"Press 5 for an animated visualization of this construction. Initially you see the hyperbolic plane at time 0 (u=0, t>0). " "Press 5 for an animated visualization of this construction. Initially you see the hyperbolic plane at time 0 (u=0, t>0). "
@@ -634,10 +1144,12 @@ slide relhell_tour[] = {
"uses the RogueViz implementation of that space. However, the angular coordinate becomes time-like, making our spacetime to be " "uses the RogueViz implementation of that space. However, the angular coordinate becomes time-like, making our spacetime to be "
"much more symmetric, and the geodesics work in a much more intuitive way.", "much more symmetric, and the geodesics work in a much more intuitive way.",
[] (presmode mode) { [] (presmode mode) {
latex_slide(mode, defs+R"=( string s = "\\definecolor{rcsl}{rgb}{0,0.75,0}\n\\definecolor{rtsl}{rgb}{0,0,1}\n\\definecolor{rsign}{rgb}{1,0.25,0.25}\n";
s += "\\def\\csl#1{{\\color{rcsl}#1}}\n\\def\\tsl#1{{\\color{rtsl}#1}}\n\\def\\hlsign#1{{\\color{rsign}#1}}\n";
latex_slide(mode, defs+s+R"=(
{\color{remph}anti-de Sitter spacetime:} {\color{remph}anti-de Sitter spacetime:}
\begin{itemize} \begin{itemize}
\item $\wadS{2} = \{(x,y,t,u) \in \bbE^{2,2}: \\ x^2+y^2-t^2-u^2=-1\}$ \item $\wadS{2} = \{(\csl{x,y},\tsl{t,u}) \in \bbE^{2,2}: \\ \csl{x^2\hlsign{+}y^2}\hlsign{-}\tsl{t^2\hlsign{-}u^2}=-1\}$
\item take $u=0, t>0$ -- we get $\bbH^2$ \item take $u=0, t>0$ -- we get $\bbH^2$
\item rotation in the $(t,u)$ plane \\ corresponds to the pass of time \item rotation in the $(t,u)$ plane \\ corresponds to the pass of time
\item $\uadS{2}$ -- the {\color{remph}universal cover}: \\ \item $\uadS{2}$ -- the {\color{remph}universal cover}: \\
@@ -675,7 +1187,7 @@ slide relhell_tour[] = {
}); });
}}, }},
{"de Sitter spacetime", 999, LEGAL::NONE | QUICKGEO | USE_SLIDE_NAME | NOTITLE, {"de Sitter spacetime geometry", 999, LEGAL::NONE | QUICKGEO | USE_SLIDE_NAME | NOTITLE,
"And here is how we add a time coordinate to 2D spherical geometry, to get 2+1D de Sitter spacetime. " "And here is how we add a time coordinate to 2D spherical geometry, to get 2+1D de Sitter spacetime. "
"The construction is actually very similar to three-dimensional hyperbolic plane, but now the " "The construction is actually very similar to three-dimensional hyperbolic plane, but now the "
"'squared radius' is space-like. So we get a maximally symmetric spacetime again.\n\n" "'squared radius' is space-like. So we get a maximally symmetric spacetime again.\n\n"
@@ -683,12 +1195,14 @@ slide relhell_tour[] = {
"it looks from the point of view of an inhabitant -- the whole 'sphere' does not expand.", "it looks from the point of view of an inhabitant -- the whole 'sphere' does not expand.",
[] (presmode mode) { [] (presmode mode) {
latex_slide(mode, defs+R"=( string s = "\\definecolor{rcsl}{rgb}{0,0.75,0}\n\\definecolor{rtsl}{rgb}{0,0,1}\n\\definecolor{rsign}{rgb}{1,0.25,0.25}\n";
s += "\\def\\csl#1{{\\color{rcsl}#1}}\n\\def\\tsl#1{{\\color{rtsl}#1}}\n\\def\\hlsign#1{{\\color{rsign}#1}}\n";
latex_slide(mode, defs+s+R"=(
{\color{remph}de Sitter spacetime:} {\color{remph}de Sitter spacetime:}
\begin{itemize} \begin{itemize}
\item $\dS{2} = \{(x,y,z,t) \in \bbE^{3,1}: \\ x^2+y^2+z^2-t^2=1\}$ \item $\dS{2} = \{(\csl{x,y,z},\tsl{t}) \in \bbE^{3,1}: \\ \csl{x^2\hlsign{+}y^2\hlsign{+}z^2}\hlsign{-}\tsl{t^2}=1\}$
\item take $t=0$ -- we get $\bbS^2$ \item take $t=0$ -- we get $\bbS^2$
\item the universe is expanding with $t$ \\ (not if we apply Lorentz transformation) \item the universe is expanding with $t$ \\ (not if we apply \\ the Lorentz transformation)
\end{itemize} \end{itemize}
)=", sm::NOSCR | sm::SIDE, 90); )=", sm::NOSCR | sm::SIDE, 90);
static int phase = 0; static int phase = 0;
@@ -759,14 +1273,72 @@ slide relhell_tour[] = {
}; };
int pohooks = int pohooks =
0 + 0 + arg::add3("-contrep", [] {
addHook_slideshows(100, [] (tour::ss::slideshow_callback cb) { cmode = sm::NORMAL; for(int a=0; a<3000; a++) println(hlog, a), paused = false, game_over = false, have_crashes = false, ds_turn(10), ticks += 10;
switch_replay();
switch_spacetime_to(true);
pmodel = mdRelPerspective; use_duality = false;
})
+ arg::add3("-ads-missile-replay", [] { missile_replay = true; })
+ arg::add3("-stereo-transition", [] {
arg::shift(); int len = arg::argi();
static int tstart = 999000;
rogueviz::rv_hook(hooks_handleKey, 101, [] (int sym, int uni) {
println(hlog, "uni = ", uni);
if((cmode & sm::NORMAL) && uni == 'y') {
tstart = tstart > ticks ? ticks : 999000;
return true;
}
return false;
});
rv_hook(anims::hooks_anim, 102, [len] {
ld t = (ticks - tstart) * 1. / len; flip_limit = 0.9;
if(t < 0) { pconf.alpha = 1000; pconf.scale = 950; vid.yshift = 0; pconf.stretch = 1; backbrightness = 0.25; }
else if(t > 1) { pconf.alpha = 1; pconf.scale = 0.95; pconf.stretch = 1; vid.yshift = M_PI; backbrightness = 1; }
else {
ld t1 = t; t1 = t1 * t1 * (3 - 2 * t1);
pconf.alpha = exp(log(1000) * (1 - t1));
pconf.scale = 0.95 * pconf.alpha;
pconf.stretch = 1;
vid.yshift = M_PI * t1;
backbrightness = lerp(0.25, 1, t1);
}
});
})
+ arg::add3("-ads-resource", [] {
static int howmany = -2;
if(howmany == -2) rogueviz::rv_hook(hooks_prestats, 101, [] {
if(howmany <= 0) return false;
vector<eResourceType> res = {rtFuel, rtOxygen, rtHull, rtAmmo};
flat_model_enabler fm;
dynamicval<eGeometry> g(geometry, gEuclid);
initquickqueue();
int index = 0;
for(auto which: res) {
auto sh = *rsrc_shape[which];
for(int s: {0, 1}) for(int dx=-5; dx<=5; dx++) for(int dy=-5; dy<=5; dy++) {
if(s == 1 && (dx || dy)) continue;
if(s == 0 && (dx*dx+dy*dy >= 20)) continue;
for(int i=0; i<isize(sh); i+=2)
curvepoint(hyperpoint(sh[i], sh[i+1], 1, 1));
queuecurve(atscreenpos(vid.xres * (.63+.1 * index) + dx, vid.yres * .8 + dy) * euscalexx(1000) * spin90(), 0, s == 0 ? 0xFF : rsrc_color[which], PPR::LINE);
}
index++; if(index == howmany) break;
}
quickqueue();
return true;
});
arg::shift(); howmany = arg::argi();
})
+ addHook_slideshows(100, [] (tour::ss::slideshow_callback cb) {
cb(XLAT("Relative Hell guided tour"), &relhell_tour[0], 'S'); cb(XLAT("Relative Hell guided tour"), &relhell_tour[0], 'S');
}); });
} }
void start_relhell_tour() { void start_relhell_tour() {
lps_enable(nullptr);
popScreenAll(); popScreenAll();
tour::slides = &ads_tour::relhell_tour[0]; tour::slides = &ads_tour::relhell_tour[0];
tour::start(); tour::start();