mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-25 17:40:36 +00:00
225 lines
6.5 KiB
C++
225 lines
6.5 KiB
C++
// RogueViz -- source code for creating videos and animations
|
|
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
|
|
|
|
namespace rogueviz {
|
|
|
|
#if CAP_SDL && CAP_SHOT
|
|
|
|
// see: https://www.youtube.com/watch?v=4Vu3F95jpQ4&t=6s (Collatz)
|
|
// see: https://www.youtube.com/watch?v=mDG3_f8R2Ns (SAG boardgames)
|
|
// see: https://www.youtube.com/watch?v=WSyygk_3j9o (SAG roguelikes)
|
|
// see: https://www.youtube.com/watch?v=HWQkDkeEUeM (SAG programming languages)
|
|
|
|
void rvvideo(const string &fname) {
|
|
if(kind == kCollatz) {
|
|
sightrange_bonus = 3;
|
|
genrange_bonus = 3;
|
|
dronemode = true; vid.camera_angle = -45; rog3 = true; patterns::whichShape = '8';
|
|
vid.aurastr = 512;
|
|
|
|
collatz::lookup(763, 60);
|
|
|
|
history::create_playerpath(), models::rotation = 1;
|
|
// pmodel = mdBand;
|
|
|
|
#define STORYCOUNT 24
|
|
#define T(m,ss) (60*24*(m)+24*(ss))
|
|
#define FRAMECOUNT T(4,55)
|
|
|
|
printf("framecount = %d\n", FRAMECOUNT);
|
|
|
|
struct storydata { int s; int e; const char *text; } story[] = {
|
|
{T(0,14), T(0,17), "I am flying above a tree of numbers."},
|
|
{T(0,17), T(0,20), "It starts with the number 1."},
|
|
{T(0,20), T(0,23), "Each number n branches left to 2n."},
|
|
{T(0,23), T(0,28), "And it branches right to (2n-1)/3 if possible."},
|
|
|
|
{T(1, 8), T(1,11), "What I am flying above is not a plane."},
|
|
{T(1,11), T(1,14), "It is not a sphere either."},
|
|
{T(1,14), T(1,17), "To be honest, the space I live in..."},
|
|
{T(1,17), T(1,20), "...is not even Euclidean."},
|
|
|
|
{T(2,12), T(2,15), "Look, angles of a triangle add up to..."},
|
|
{T(2,15), T(2,18), "...less than 180 degrees in this world."},
|
|
{T(2,18), T(2,21), "6/7 of 180 degrees, to be exact."},
|
|
{T(2,21), T(2,24), "Do you see the regular heptagons?"},
|
|
{T(2,36), T(2,42), "And all these lines are straight."},
|
|
|
|
{T(3, 8), T(3,11), "Lots of space in my world."},
|
|
{T(3,11), T(3,14), "In 105 steps from the root..."},
|
|
{T(3,14), T(3,17), "...there are trillions of numbers."},
|
|
{T(3,17), T(3,20), "That would not fit in your world."},
|
|
|
|
{T(4,0), T(4,3), "Is every positive number somewhere in the tree?"},
|
|
{T(4,3), T(4,6), "Your mathematicians do not know this yet."},
|
|
{T(4,6), T(4,10), "Will you find the answer?"},
|
|
|
|
{T(4,44), T(4,54), "music: Ambient Flow, by Indjenuity"},
|
|
|
|
{T(2,6), T(2,27), "@triangles"},
|
|
{T(2,27), T(2,42), "@network"},
|
|
|
|
{0, T(0,7), "@fi"},
|
|
{T(4,48), T(4,55), "@fo"},
|
|
|
|
{0,0,NULL}
|
|
};
|
|
|
|
int drawtris=0, drawnet=0;
|
|
|
|
for(int i=0; i<FRAMECOUNT; i++) {
|
|
const char *caption = NULL;
|
|
int fade = 255;
|
|
|
|
bool dt = false, dn = false;
|
|
|
|
for(int j=0; story[j].text; j++) if(i >= story[j].s && i <= story[j].e) {
|
|
if(story[j].text[0] != '@')
|
|
caption = story[j].text;
|
|
else if(story[j].text[1] == 't')
|
|
dt = true;
|
|
else if(story[j].text[1] == 'n')
|
|
dn = true;
|
|
else if(story[j].text[2] == 'i')
|
|
fade = 255 * (i - story[j].s) / (story[j].e-story[j].s);
|
|
else if(story[j].text[2] == 'o')
|
|
fade = 255 * (story[j].e - i) / (story[j].e-story[j].s);
|
|
}
|
|
|
|
if(dt && drawtris < 255) drawtris++;
|
|
else if(drawtris && !dt) drawtris--;
|
|
|
|
linepatterns::patZebraTriangles.color = 0x40FF4000 + drawtris;
|
|
|
|
if(dn && drawnet < 255) drawnet++;
|
|
else if(drawnet && !dn) drawnet--;
|
|
|
|
linepatterns::patZebraLines.color = 0xFF000000 + drawnet;
|
|
|
|
vid.grid = drawnet;
|
|
|
|
history::phase = 1 + (isize(history::v)-3) * i * .95 / FRAMECOUNT;
|
|
history::movetophase();
|
|
|
|
char buf[500];
|
|
snprintf(buf, 500, fname.c_str(), i);
|
|
|
|
if(i == 0) drawthemap();
|
|
shmup::turn(100);
|
|
printf("%s\n", buf);
|
|
shot::shoty = 1080; shot::shotx = 1920;
|
|
shot::caption = caption;
|
|
shot::fade = fade;
|
|
shot::take(buf);
|
|
}
|
|
|
|
return;
|
|
}
|
|
for(int i=0; i<1800; i++) {
|
|
char buf[500];
|
|
snprintf(buf, 500, fname.c_str(), i);
|
|
shmup::pc[0]->base = currentmap->gamestart();
|
|
shmup::pc[0]->at = spin(i * 2 * M_PI / (58*30.)) * xpush(1.7);
|
|
if(i == 0) drawthemap();
|
|
shmup::turn(100);
|
|
if(i == 0) drawthemap();
|
|
centerpc(100);
|
|
printf("%s\n", buf);
|
|
shot::take(buf);
|
|
}
|
|
}
|
|
|
|
string its05(int i) { char buf[64]; sprintf(buf, "%05d", i); return buf; }
|
|
|
|
#define TSIZE 4096
|
|
|
|
// see: https://www.youtube.com/watch?v=HZNRo6mr5pk
|
|
|
|
void staircase_video(int from, int num, int step) {
|
|
resetbuffer rb;
|
|
renderbuffer rbuf(TSIZE, TSIZE, true);
|
|
vid.stereo_mode = sODS;
|
|
|
|
for(int i=from; i<num; i+=step) {
|
|
ld t = i * 1. / num;
|
|
t = pow(t, .3);
|
|
staircase::scurvature = t * t * (t-.95) * 4;
|
|
staircase::progress = i / 30.;
|
|
|
|
staircase::strafex = (sin(i / 240.) - sin(i / 501.)) / 2.5;
|
|
staircase::strafey = (cos(i / 240.) - cos(i / 501.)) / 2.5;
|
|
|
|
staircase::make_staircase();
|
|
|
|
rbuf.enable();
|
|
dynamicval<int> vx(vid.xres, TSIZE);
|
|
dynamicval<int> vy(vid.yres, TSIZE);
|
|
dynamicval<int> vxc(current_display->xcenter, TSIZE/2);
|
|
dynamicval<int> vyc(current_display->ycenter, TSIZE/2);
|
|
printf("draw scene\n");
|
|
rug::drawRugScene();
|
|
|
|
IMAGESAVE(rbuf.render(), ("staircase/" + its05(i) + IMAGEEXT).c_str());
|
|
printf("GL %5d/%5d\n", i, num);
|
|
}
|
|
|
|
rb.reset();
|
|
}
|
|
|
|
#undef TSIZE
|
|
|
|
#define TSIZE 2048
|
|
|
|
// see: https://twitter.com/ZenoRogue/status/1001127253747658752
|
|
// see also: https://twitter.com/ZenoRogue/status/1000043540985057280 (older version)
|
|
|
|
void bantar_record() {
|
|
resetbuffer rb;
|
|
renderbuffer rbuf(TSIZE, TSIZE, true);
|
|
|
|
int fr = 0;
|
|
|
|
for(int i=0; i < 10000; i += 33) {
|
|
if(i % 1000 == 999) i++;
|
|
ticks = i;
|
|
|
|
rbuf.enable();
|
|
vid.xres = vid.yres = TSIZE;
|
|
banachtarski::bantar_frame();
|
|
|
|
IMAGESAVE(rbuf.render(), ("bantar/" + its05(fr) + IMAGEEXT).c_str());
|
|
printf("GL %5d/%5d\n", i, 10000);
|
|
fr++;
|
|
}
|
|
|
|
rb.reset();
|
|
}
|
|
#undef TSIZE
|
|
|
|
#if CAP_COMMANDLINE
|
|
int videoArgs() {
|
|
using namespace arg;
|
|
if(argis("-rvvideo")) {
|
|
shift(); rvvideo(arg::args());
|
|
}
|
|
else if(argis("-staircase_video")) {
|
|
staircase_video(0, 128*30, 1); // goal: 168*30
|
|
}
|
|
else if(argis("-bantar_record")) {
|
|
using namespace banachtarski;
|
|
PHASE(3);
|
|
peace::on = true;
|
|
airmap.clear();
|
|
ForInfos if(cci.second.c->monst == moAirElemental)
|
|
cci.second.c->monst = moFireElemental;
|
|
bantar_record();
|
|
}
|
|
else return 1;
|
|
return 0;
|
|
}
|
|
|
|
auto rv_hooks = addHook(hooks_args, 100, videoArgs);
|
|
#endif
|
|
#endif
|
|
}
|