You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
6.6 KiB
C
228 lines
6.6 KiB
C
5 years ago
|
#include "demo.h"
|
||
5 years ago
|
#include <pthread.h>
|
||
|
|
||
5 years ago
|
static int
|
||
|
drop_bricks(struct notcurses* nc, struct ncplane** arr, int arrcount){
|
||
|
if(arrcount == 0 || arr == NULL){
|
||
|
return -1;
|
||
|
}
|
||
5 years ago
|
int stdy, stdx;
|
||
|
notcurses_term_dim_yx(nc, &stdy, &stdx);
|
||
5 years ago
|
// an erase+render cycle ought not change the screen, as we duplicated it
|
||
|
struct timespec iterdelay;
|
||
|
// 5 * demodelay total
|
||
5 years ago
|
ns_to_timespec(timespec_to_ns(&demodelay) / arrcount / 2, &iterdelay);
|
||
5 years ago
|
// we've got a range of up to 10% total blocks falling at any given time. they
|
||
5 years ago
|
// accelerate as they fall. [ranges, reange) covers the active range.
|
||
|
int ranges = 0;
|
||
|
int rangee = 0;
|
||
4 years ago
|
const int FALLINGMAX = arrcount < 10 ? 1 : arrcount / 10;
|
||
5 years ago
|
int speeds[FALLINGMAX];
|
||
|
while(ranges < arrcount){
|
||
|
// if we don't have a full set active, and there is another available, go
|
||
|
// ahead and get it kicked off
|
||
|
if(rangee - ranges + 1 < FALLINGMAX){
|
||
|
if(rangee < arrcount){
|
||
3 years ago
|
int y;
|
||
|
ncplane_yx(arr[ranges], &y, NULL);
|
||
|
speeds[rangee - ranges] = y < stdy / 2 ? 1 : -1;
|
||
5 years ago
|
++rangee;
|
||
|
}
|
||
5 years ago
|
}
|
||
5 years ago
|
do{
|
||
5 years ago
|
DEMO_RENDER(nc);
|
||
5 years ago
|
// don't allow gaps in the active range. so long as felloff is true, we've only handled
|
||
|
// planes which have fallen off the screen, and can be collected.
|
||
|
bool felloff = true;
|
||
|
for(int i = 0 ; i < rangee - ranges ; ++i){
|
||
|
struct ncplane* ncp = arr[ranges + i];
|
||
4 years ago
|
ncplane_move_top(ncp);
|
||
5 years ago
|
int x, y;
|
||
|
ncplane_yx(ncp, &y, &x);
|
||
|
if(felloff){
|
||
3 years ago
|
if(y + speeds[i] >= stdy || y + speeds[i] + ncplane_dim_y(ncp) < 0){
|
||
5 years ago
|
ncplane_destroy(ncp);
|
||
|
arr[ranges + i] = NULL;
|
||
5 years ago
|
if(ranges + i + 1 == rangee){
|
||
5 years ago
|
ranges += i + 1;
|
||
|
break;
|
||
|
}
|
||
|
}else{ // transition point
|
||
|
if(i){
|
||
|
if(rangee - ranges - i){
|
||
|
memmove(speeds, speeds + i, (rangee - ranges - i) * sizeof(*speeds));
|
||
|
}
|
||
|
ranges += i;
|
||
|
i = 0;
|
||
|
}
|
||
|
felloff = false;
|
||
|
}
|
||
|
}
|
||
|
if(!felloff){
|
||
|
ncplane_move_yx(ncp, y + speeds[i], x);
|
||
3 years ago
|
if(speeds[i] < 0){
|
||
|
--speeds[i];
|
||
|
}else{
|
||
|
++speeds[i];
|
||
|
}
|
||
5 years ago
|
}else if(i){
|
||
|
if(rangee - ranges - i){
|
||
|
memmove(speeds, speeds + i, (rangee - ranges - i) * sizeof(*speeds));
|
||
|
}
|
||
|
ranges += i;
|
||
|
i = 0;
|
||
5 years ago
|
}
|
||
5 years ago
|
demo_nanosleep(nc, &iterdelay);
|
||
5 years ago
|
}
|
||
|
}while(rangee - ranges + 1 >= FALLINGMAX);
|
||
5 years ago
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
5 years ago
|
// Shuffle a new ncplane into the array of ncplanes having 'count' elements.
|
||
|
static struct ncplane**
|
||
|
shuffle_in(struct ncplane** arr, int count, struct ncplane* n){
|
||
|
struct ncplane** tmp = realloc(arr, sizeof(*arr) * (count + 1));
|
||
|
if(tmp == NULL){
|
||
|
return NULL;
|
||
|
}
|
||
|
arr = tmp;
|
||
|
// location of new element
|
||
|
int pos = random() % (count + 1);
|
||
|
if(pos < count){
|
||
|
// move everything, starting at our new location, one spot right
|
||
5 years ago
|
memmove(arr + pos + 1, arr + pos, sizeof(*arr) * (count - pos));
|
||
5 years ago
|
}
|
||
|
arr[pos] = n;
|
||
|
return arr;
|
||
|
}
|
||
|
|
||
3 years ago
|
// you played yourself https://genius.com/De-la-soul-fallin-lyrics
|
||
|
int fission_demo(struct notcurses* nc){
|
||
5 years ago
|
int dimx, dimy;
|
||
5 years ago
|
struct ncplane* stdn = notcurses_stddim_yx(nc, &dimy, &dimx);
|
||
5 years ago
|
size_t usesize = sizeof(bool) * dimy * dimx;
|
||
|
bool* usemap = malloc(usesize);
|
||
3 years ago
|
if(usemap == NULL){
|
||
|
return -1;
|
||
|
}
|
||
5 years ago
|
memset(usemap, 0, usesize);
|
||
|
// brick size is relative to the screen size
|
||
5 years ago
|
const int maxx = dimx > 39 ? dimx / 10 : 2;
|
||
5 years ago
|
const int maxy = dimy > 19 ? dimy / 10 : 2;
|
||
5 years ago
|
// proceed from top to bottom, left to right, and partition the existing
|
||
5 years ago
|
// content into 'arrcount' copies into small ncplanes in 'arr'.
|
||
5 years ago
|
struct ncplane** arr = NULL;
|
||
|
int arrcount = 0;
|
||
5 years ago
|
// There are a lot of y/x pairs at this point:
|
||
|
// * dimx/dimy: geometry of standard plane
|
||
|
// * y/x: iterators through standard plane
|
||
|
// * maxy/maxx: maximum geometry of randomly-generated bricks
|
||
|
// * newy/newx: actual geometry of current brick
|
||
|
// * usey/usex:
|
||
5 years ago
|
ncplane_greyscale(stdn);
|
||
4 years ago
|
for(int y = 1 ; y < dimy ; ++y){
|
||
5 years ago
|
int x = 0;
|
||
|
while(x < dimx){
|
||
|
if(usemap[y * dimx + x]){ // skip if we've already been copied
|
||
|
++x;
|
||
5 years ago
|
continue;
|
||
|
}
|
||
|
int newy, newx;
|
||
5 years ago
|
newy = random() % (maxy - 1) + 2;
|
||
|
newx = random() % (maxx - 1) + 2;
|
||
5 years ago
|
if(x + newx >= dimx){
|
||
|
newx = dimx - x;
|
||
|
}
|
||
|
if(y + newy >= dimy){
|
||
|
newy = dimy - y;
|
||
|
}
|
||
4 years ago
|
struct ncplane_options nopts = {
|
||
|
.y = y,
|
||
|
.x = x,
|
||
|
.rows = newy,
|
||
|
.cols = newx,
|
||
|
};
|
||
|
struct ncplane* n = ncplane_create(stdn, &nopts);
|
||
5 years ago
|
if(n == NULL){
|
||
4 years ago
|
goto err;
|
||
5 years ago
|
}
|
||
5 years ago
|
// copy the old content into this new ncplane
|
||
5 years ago
|
for(int usey = y ; usey < y + newy ; ++usey){
|
||
|
for(int usex = x ; usex < x + newx ; ++usex){
|
||
5 years ago
|
if(usemap[usey * dimx + usex]){
|
||
|
newx = usex - x;
|
||
|
ncplane_resize_simple(n, newy, newx);
|
||
|
continue;
|
||
|
}
|
||
4 years ago
|
cell c = CELL_TRIVIAL_INITIALIZER;
|
||
|
uint16_t smask;
|
||
|
uint64_t channels;
|
||
|
char* egc = ncplane_at_yx(stdn, usey, usex, &smask, &channels);
|
||
|
if(egc == NULL){
|
||
4 years ago
|
goto err;
|
||
5 years ago
|
}
|
||
4 years ago
|
if(*egc){
|
||
4 years ago
|
if(nccell_prime(n, &c, egc, smask, channels) <= 0){
|
||
4 years ago
|
free(egc);
|
||
|
goto err;
|
||
|
}
|
||
|
free(egc);
|
||
|
if(ncplane_putc_yx(n, usey - y, usex - x, &c) < 0){
|
||
5 years ago
|
// allow a fail if we were printing a wide char to the
|
||
|
// last column of our plane
|
||
4 years ago
|
if(!nccell_double_wide_p(&c) || usex + 1 < x + newx){
|
||
4 years ago
|
nccell_release(n, &c);
|
||
4 years ago
|
goto err;
|
||
5 years ago
|
}
|
||
|
}
|
||
3 years ago
|
}else{
|
||
|
free(egc);
|
||
5 years ago
|
}
|
||
|
usemap[usey * dimx + usex] = true;
|
||
4 years ago
|
nccell_release(n, &c);
|
||
5 years ago
|
}
|
||
|
}
|
||
5 years ago
|
// shuffle the new ncplane into the array
|
||
5 years ago
|
struct ncplane **tmp;
|
||
|
tmp = shuffle_in(arr, arrcount, n);
|
||
|
if(tmp == NULL){
|
||
4 years ago
|
goto err;
|
||
5 years ago
|
}
|
||
|
arr = tmp;
|
||
|
++arrcount;
|
||
5 years ago
|
x += newx;
|
||
5 years ago
|
}
|
||
5 years ago
|
}
|
||
4 years ago
|
ncplane_erase(stdn);
|
||
5 years ago
|
#ifndef DFSG_BUILD
|
||
4 years ago
|
if(notcurses_canopen_images(nc)){
|
||
4 years ago
|
char* path = find_data("lamepatents.jpg");
|
||
|
struct ncvisual* ncv = ncvisual_from_file(path);
|
||
|
free(path);
|
||
|
if(ncv == NULL){
|
||
|
goto err;
|
||
|
}
|
||
|
struct ncvisual_options vopts = {
|
||
|
.n = stdn,
|
||
|
.scaling = NCSCALE_STRETCH,
|
||
|
};
|
||
|
if(ncvisual_render(nc, ncv, &vopts) == NULL){
|
||
5 years ago
|
ncvisual_destroy(ncv);
|
||
4 years ago
|
goto err;
|
||
|
}
|
||
|
assert(ncvisual_decode(ncv) == 1);
|
||
|
ncvisual_destroy(ncv);
|
||
4 years ago
|
}
|
||
5 years ago
|
#endif
|
||
|
int ret = drop_bricks(nc, arr, arrcount);
|
||
4 years ago
|
free(arr);
|
||
|
free(usemap);
|
||
5 years ago
|
return ret;
|
||
4 years ago
|
|
||
|
err:
|
||
|
free(usemap);
|
||
|
free(arr);
|
||
|
return -1;
|
||
5 years ago
|
}
|