notcurses/src/demo/dragon.c
2021-07-01 05:28:30 -04:00

114 lines
2.6 KiB
C

#include "demo.h"
// lame as fuck lol
static bool done;
static uint32_t pixel;
static int y, x, dy, dx;
static int
dragonmayer(struct ncvisual* ncv, const char* str, int iters){
int total = 0;
char c;
int r;
while( (c = *str++) ){
switch(c){
case 'X':
if(iters > 1){
if((r = dragonmayer(ncv, "X+YF+", iters - 1)) < 0){
return r;
}
total += r;
}
break;
case 'Y':
if(iters > 1){
if((r = dragonmayer(ncv, "-FX-Y", iters - 1)) < 0){
return r;
}
total += r;
}
break;
case '+': { int tmp = dy; dy = -dx; dx = tmp; break; }
case '-': { int tmp = -dy; dy = dx; dx = tmp; break; }
case 'F': // FIXME want a line
ncpixel_set_r(&pixel, 0xb0 - (iters * 0x10));
ncpixel_set_a(&pixel, 0xff);
if(ncvisual_set_yx(ncv, y, x, pixel) == 0){
++total;
}
pixel = 0;
x += dx;
y += dy;
break;
default:
return -1;
}
}
return total;
}
int dragon_demo(struct notcurses* nc){
done = false;
int dimy, dimx;
struct ncplane* n = notcurses_stddim_yx(nc, &dimy, &dimx);
--dimy; // don't disturb the menu bar
// we use a Lindenmayer string rewriting system. the classic dragon curve
// system is X -> X+YF+, Y -> -FX-Y, where F is forward, - is turn left, and
// + is turn right.
const char LINDENSTART[] = "FX";
const int vscale = 3;
dimy *= vscale;
dimy += (vscale - 1);
dimx *= 2;
int dxstart, dystart;
if(dimy > dimx){
dystart = 0;
dxstart = 1;
}else{
dystart = 1;
dxstart = 0;
}
size_t fbbytes = sizeof(uint32_t) * dimy * dimx;
uint32_t* rgba = malloc(fbbytes);
if(rgba == NULL){
return -1;
}
memset(rgba, 0, fbbytes);
struct ncvisual* ncv = ncvisual_from_rgba(rgba, dimy, dimx * sizeof(uint32_t), dimx);
free(rgba);
if(ncv == NULL){
return -1;
}
struct timespec scaled;
timespec_div(&demodelay, 8, &scaled);
int lasttotal = 0;
int iters = 0;
int r = 0;
do{
++iters;
lasttotal = r;
dx = dxstart;
dy = dystart;
x = dimx / 2;
y = dimy / vscale;
r = dragonmayer(ncv, LINDENSTART, iters);
if(r < 0){
ncvisual_destroy(ncv);
return r;
}
struct ncvisual_options vopts = {
.n = n,
.y = 1,
.scaling = NCSCALE_STRETCH,
};
if(ncvisual_render(nc, ncv, &vopts) == NULL){
ncvisual_destroy(ncv);
return -1;
}
DEMO_RENDER(nc);
demo_nanosleep(nc, &scaled);
}while(lasttotal != r);
ncvisual_destroy(ncv);
return 0;
}