mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-27 14:37:16 +00:00
db3e5d1009
Eliminate a format-string warning by using less template magic: https://stackoverflow.com/questions/12573968/how-to-use-gccs-printf-format-attribute-with-c11-variadic-templates Fix one `%Ld` in `rogueviz.cpp` that should have been `%lld`. Rename `savepng.c` into `savepng.cpp` so that we don't have to care about the system's C compiler; it builds fine using the same C++ options as HyperRogue itself. Figure out how to get `-DCAP_PNG` and `-DCAP_ROGUEVIZ` working on Mac, and document them. Assume that roughly the same things should also work on MinGW. Consistency on `STDSIZE`, even though it doesn't suffice for C++17 conformance. It *almost* suffices; the one place where Clang still complains even with `-std=c++17 -DSTDSIZE -Wno-sign-compare` is here: ./fieldpattern.cpp:757:51: error: non-constant-expression cannot be narrowed from type 'unsigned long' to 'int' in initializer list [-Wc++11-narrowing] ex.primes.emplace_back(primeinfo{nextprime, size(fp.matrices) / S7, (bool) fp.wsquare}); ^~~~~~~~~~~~~~~~~~~~~~ So, we fix that up too, in this patch.
265 lines
7.7 KiB
C++
265 lines
7.7 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
|
|
|
|
// 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) {
|
|
pngformat = 2;
|
|
sightrange_bonus = 3;
|
|
genrange_bonus = 3;
|
|
dronemode = true; vid.camera_angle = -45; rog3 = true; patterns::whichShape = '8';
|
|
vid.aurastr = 512;
|
|
long long reached = 763ll;
|
|
while(reached < (1ll<<60)) {
|
|
if(reached%3 == 2 && (2*reached-1) % 9 && hrand(100) < 50)
|
|
reached = (2*reached-1) / 3;
|
|
else reached *= 2;
|
|
}
|
|
printf("reached = %lld\n", reached);
|
|
vector<string> seq;
|
|
while(reached>1) {
|
|
seq.push_back(llts(reached));
|
|
if(reached&1) reached += (reached>>1)+1;
|
|
else reached >>= 1;
|
|
}
|
|
// seq.push_back("1");
|
|
reverse(seq.begin(), seq.end());
|
|
|
|
int id = 0;
|
|
int next = 0;
|
|
|
|
int steps = 0;
|
|
while(true) {
|
|
steps++;
|
|
if(std::isnan(View[0][0])) exit(1);
|
|
shmup::turn(100);
|
|
drawthemap();
|
|
centerpc(100); optimizeview();
|
|
fixmatrix(View);
|
|
bfs(); setdist(cwt.c, 7 - getDistLimit() - genrange_bonus, NULL);
|
|
vertexdata& vd = vdata[id];
|
|
for(int e=0; e<size(vd.edges); e++) {
|
|
int id2 = vd.edges[e].first;
|
|
if(vdata[id2].name == seq[next]) {
|
|
id = id2; next++;
|
|
cwt.c = shmup::pc[0]->base = vdata[id2].m->base;
|
|
if(next == size(seq)) goto found;
|
|
}
|
|
}
|
|
}
|
|
|
|
found:
|
|
printf("steps = %d\n", steps);
|
|
conformal::create(), conformal::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::setColor(linepatterns::patZebraTriangles, 0x40FF4000 + drawtris);
|
|
|
|
if(dn && drawnet < 255) drawnet++;
|
|
else if(drawnet && !dn) drawnet--;
|
|
|
|
linepatterns::setColor(linepatterns::patZebraLines, 0xFF000000 + drawnet);
|
|
|
|
vid.grid = drawnet;
|
|
|
|
conformal::phase = 1 + (size(conformal::v)-3) * i * .95 / FRAMECOUNT;
|
|
conformal::movetophase();
|
|
|
|
char buf[500];
|
|
snprintf(buf, 500, fname.c_str(), i);
|
|
|
|
if(i == 0) drawthemap();
|
|
shmup::turn(100);
|
|
printf("%s\n", buf);
|
|
pngres = 1080;
|
|
saveHighQualityShot(buf, caption, fade);
|
|
}
|
|
|
|
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);
|
|
saveHighQualityShot(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);
|
|
stereo::mode = stereo::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(vid.xcenter, TSIZE/2);
|
|
dynamicval<int> vyc(vid.ycenter, TSIZE/2);
|
|
stereo::set_viewport(0);
|
|
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;
|
|
stereo::set_viewport(0);
|
|
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;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
auto rv_hooks = addHook(hooks_args, 100, videoArgs);
|
|
|
|
}
|