📄 nsaver.c
字号:
pos = (incr * (i - 1)) + (RANDRANGE(0, SAVER6_MAXZIGZAG) -
((double)SAVER6_MAXZIGZAG / 2.0));
if(pos < 0) pos = 0;
if(pos > length) pos = length;
nx = x - (pos * sin(angle));
ny = y + pos * cos(angle);
saver6_perturb(state, &nx, &ny, SAVER6_MAXZIGZAG);
saver6_setvertices(s, bolt, fork, i, nx , ny);
}
}
int saver6_makeforks(nstate *state, s6state *s, int bolt, int fork,
int *vert, int *nextfork)
{
int thisvert = 1, thisfork;
double prob;
if(*vert == (s->bolts[bolt].forks[fork].valid - 1)) return 0;
if(*nextfork == SAVER6_MAXFORKS) return 0;
prob = (double)SAVER6_FORK_PROBABILITY * ((double)*vert /
(double)s->bolts[bolt].forks[fork].valid) *
(1.0 / ((double)fork + 1.0));
if(RANDRANGE(0, 1) < prob) {
thisfork = *nextfork;
saver6_makefork(state, s, bolt, thisfork,
s->bolts[bolt].forks[fork].vertices[0][*vert].x,
s->bolts[bolt].forks[fork].vertices[0][*vert].y);
*nextfork += 1;
while(saver6_makeforks(state, s, bolt, thisfork, &thisvert,
nextfork));
}
*vert += 1;
return 1;
}
void saver6_makebolt(nstate *state, s6state *s, int bolt)
{
GR_COORD x;
int vert = 1, nextfork = 1, n;
for(n = 0; n < SAVER6_MAXFORKS; n++)
s->bolts[bolt].forks[n].valid = 0;
x = (int)RANDRANGE(0, (state->si.cols - 1.0));
saver6_makefork(state, s, bolt, 0, x, 0);
while(saver6_makeforks(state, s, bolt, 0, &vert, &nextfork));
}
void saver6_newbolt(nstate *state, s6state *s)
{
int i;
for(i = 0; i < SAVER6_MAXBOLTS; i++) {
if(!s->bolts[i].duration) {
saver6_makebolt(state, s, i);
s->bolts[i].duration = RANDRANGE(SAVER6_MINDURATION,
SAVER6_MAXDURATION);
saver6_drawbolt(state, s, i, 0);
break;
}
}
s->new_bolt_time = RANDRANGE(1, SAVER6_MAXNEWBOLTTIME);
}
void saver6_perturb_bolt(nstate *state, s6state *s, int bolt, int fork)
{
int m, o;
GR_COORD x, ox, y, oy;
for(m = 1; m < s->bolts[bolt].forks[fork].valid; m++) {
ox = x = s->bolts[bolt].forks[fork].vertices[0][m].x;
oy = y = s->bolts[bolt].forks[fork].vertices[0][m].y;
saver6_perturb(state, &x, &y, SAVER6_MAXZIGZAG);
saver6_setvertices(s, bolt, fork, m, x, y);
for(o = fork + 1; o < SAVER6_MAXFORKS; o++) {
if((s->bolts[bolt].forks[o].vertices[0][0].x == ox) &&
(s->bolts[bolt].forks[o].vertices[0][0].y
== oy)) {
saver6_setvertices(s, bolt, o, 0, x, y);
}
}
}
}
void saver6_perturb_lightning(nstate *state, s6state *s)
{
int i, n;
for(i = 0; i < SAVER6_MAXBOLTS; i++) {
if(!s->bolts[i].duration) continue;
for(n = 0; n < SAVER6_MAXFORKS; n++) {
if(!s->bolts[i].forks[n].valid) continue;
saver6_perturb_bolt(state, s, i, n);
}
}
}
void saver6_animate(nstate *state)
{
s6state *s = state->priv;
saver6_drawlightning(state, s, 1);
saver6_perturb_lightning(state, s);
saver6_drawlightning(state, s, 0);
if(!s->new_bolt_time--) saver6_newbolt(state, s);
}
/* The algorithm used in saver7 was adapted from "grav" by Greg Bowering */
void saver7_drawstar(nstate *state, s7state *s)
{
GrSetGCForeground(state->main_gc, SAVER7_STARCOLOUR);
GrFillEllipse(state->main_window, state->main_gc, s->starx, s->stary,
SAVER7_STARRADIUS, SAVER7_STARRADIUS);
}
void saver7_drawplanet(nstate *state, s7state *s, int planet, int erase)
{
if(erase) GrSetGCForeground(state->main_gc, BLACK);
else GrSetGCForeground(state->main_gc, s->planets[planet].colour);
if((s->planets[planet].ax < 0) || (s->planets[planet].ay < 0) ||
(s->planets[planet].ax >= state->si.cols) ||
(s->planets[planet].ay >= state->si.rows)) {
return;
}
GrFillEllipse(state->main_window, state->main_gc, s->planets[planet].ax,
s->planets[planet].ay,
SAVER7_PLANETRADIUS, SAVER7_PLANETRADIUS);
}
void saver7_calc_planet_position(nstate *state, s7state *s, int planet)
{
if(s->planets[planet].r > -SAVER7_ALMOSTDIST) {
s->planets[planet].ax = (int)((double) state->si.cols *
(0.5 + (s->planets[planet].x / (s->planets[planet].r +
SAVER7_DIST))));
s->planets[planet].ay = (int)((double) state->si.rows *
(0.5 + (s->planets[planet].y / (s->planets[planet].r +
SAVER7_DIST))));
} else {
s->planets[planet].ax = -1;
s->planets[planet].ay = -1;
}
}
void saver7_init(nstate *state)
{
int i;
s7state *s = my_malloc(sizeof(s7state));
state->priv = s;
s->starx = state->si.cols / 2;
s->stary = state->si.rows / 2;
for(i = 0; i < SAVER7_PLANETS; i++) {
s->planets[i].r = RANDRANGE(SAVER7_MIN_STARTDIM,
SAVER7_MAX_STARTDIM);
s->planets[i].x = RANDRANGE(SAVER7_MIN_STARTDIM,
SAVER7_MAX_STARTDIM);
s->planets[i].y = RANDRANGE(SAVER7_MIN_STARTDIM,
SAVER7_MAX_STARTDIM);
s->planets[i].rv = RANDRANGE(SAVER7_MIN_STARTVEL,
SAVER7_MAX_STARTVEL);
s->planets[i].xv = RANDRANGE(SAVER7_MIN_STARTVEL,
SAVER7_MAX_STARTVEL);
s->planets[i].yv = RANDRANGE(SAVER7_MIN_STARTVEL,
SAVER7_MAX_STARTVEL);
s->planets[i].colour = RANDRANGE(0, (state->si.ncolors - 1));
saver7_calc_planet_position(state, s, i);
saver7_drawplanet(state, s, i, 0);
}
saver7_drawstar(state, s);
state->animate_interval = SAVER7_DELAY;
}
void saver7_exposure(nstate *state)
{
int i;
s7state *s = state->priv;
GrClearWindow(state->main_window, 0);
for(i = 0; i < SAVER7_PLANETS; i++)
saver7_drawplanet(state, s, i, 0);
saver7_drawstar(state, s);
}
void saver7_moveplanet(nstate *state, s7state *s, int planet)
{
double dist;
double accel;
dist = (s->planets[planet].x * s->planets[planet].x) +
(s->planets[planet].y * s->planets[planet].y) +
(s->planets[planet].r * s->planets[planet].r);
if(dist < SAVER7_COLLIDE) dist = SAVER7_COLLIDE;
dist = sqrt(dist);
dist = dist * dist * dist;
#ifdef SAVER7_USE_DAMPING
accel = s->planets[planet].r * SAVER7_G / dist;
if(accel > SAVER7_MAX_ACCEL) accel = SAVER7_MAX_ACCEL;
else if(accel < -SAVER7_MAX_ACCEL) accel = -SAVER7_MAX_ACCEL;
s->planets[planet].rv = (s->planets[planet].rv + accel) *
SAVER7_DAMPING_FACTOR;
s->planets[planet].r += s->planets[planet].rv;
accel = s->planets[planet].x * SAVER7_G / dist;
if(accel > SAVER7_MAX_ACCEL) accel = SAVER7_MAX_ACCEL;
else if(accel < -SAVER7_MAX_ACCEL) accel = -SAVER7_MAX_ACCEL;
s->planets[planet].xv = (s->planets[planet].xv + accel) *
SAVER7_DAMPING_FACTOR;
s->planets[planet].x += s->planets[planet].xv;
accel = s->planets[planet].y * SAVER7_G / dist;
if(accel > SAVER7_MAX_ACCEL) accel = SAVER7_MAX_ACCEL;
else if(accel < -SAVER7_MAX_ACCEL) accel = -SAVER7_MAX_ACCEL;
s->planets[planet].yv = (s->planets[planet].yv + accel) *
SAVER7_DAMPING_FACTOR;
s->planets[planet].y += s->planets[planet].yv;
#else
accel = s->planets[planet].r * SAVER7_G / dist;
s->planets[planet].rv += accel;
s->planets[planet].r += s->planets[planet].rv;
accel = s->planets[planet].x * SAVER7_G / dist;
s->planets[planet].xv += accel;
s->planets[planet].x += s->planets[planet].xv;
accel = s->planets[planet].y * SAVER7_G / dist;
s->planets[planet].yv += accel;
s->planets[planet].y += s->planets[planet].yv;
#endif
}
void saver7_animate(nstate *state)
{
int i;
s7state *s = state->priv;
for(i = 0; i < SAVER7_PLANETS; i++) {
saver7_moveplanet(state, s, i);
saver7_drawplanet(state, s, i, 1);
saver7_calc_planet_position(state, s, i);
saver7_drawplanet(state, s, i, 0);
}
saver7_drawstar(state, s);
}
/* The algorithm used in saver8 is based on that found at:
http://www.go2net.com/internet/deep/1997/04/16/body.html */
void saver8_init(nstate *state)
{
int red = 0, green = 0, blue = 0, step, i = 0;
s8state *s = my_malloc(sizeof(s8state));
state->priv = s;
s->current_line = 0;
step = 512 / SAVER8_NUMCOLOURS;
for(green = 255; green > 0; green -= step, blue += step, i++)
s->colours[i] = GR_RGB(0, green, blue);
for(blue = 255; blue > 0; blue -= step, red += step, i++)
s->colours[i] = GR_RGB(red, 0, blue);
state->animate_interval = SAVER8_DELAY;
}
void saver8_drawpattern(nstate *state)
{
int x, col, lines = SAVER8_LINES_PER_FRAME;
s8state *s = state->priv;
if(!s->current_line)
s->factor = RANDRANGE(SAVER8_MINFACTOR, SAVER8_MAXFACTOR);
while(s->current_line < state->si.rows) {
if(!--lines) return;
for(x = 0; x < state->si.cols; x++) {
col = ((((x * x) + (s->current_line * s->current_line))
/ s->factor) % SAVER8_NUMCOLOURS);
GrSetGCForeground(state->main_gc, s->colours[col]);
GrPoint(state->main_window, state->main_gc, x,
s->current_line);
}
s->current_line++;
}
s->current_line = 0;
}
void saver8_exposure(nstate *state)
{
s8state *s = state->priv;
GrClearWindow(state->main_window, 0);
s->current_line = 0;
saver8_drawpattern(state);
}
void saver8_animate(nstate *state)
{
saver8_drawpattern(state);
}
int init(nstate *state)
{
GR_WM_PROPERTIES props;
GR_BITMAP cursor = 0;
if(!GrOpen()) {
fprintf(stderr, "Couldn't connect to Nano-X server\n");
return 3;
}
GrGetScreenInfo(&state->si);
state->main_window = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0,
state->si.cols, state->si.rows, 0, BLACK, 0);
GrSelectEvents(state->main_window, GR_EVENT_MASK_EXPOSURE |
GR_EVENT_MASK_BUTTON_UP |
GR_EVENT_MASK_BUTTON_DOWN |
GR_EVENT_MASK_MOUSE_MOTION |
GR_EVENT_MASK_KEY_UP |
GR_EVENT_MASK_KEY_DOWN |
GR_EVENT_MASK_FOCUS_OUT |
GR_EVENT_MASK_CLOSE_REQ);
props.flags = GR_WM_FLAGS_PROPS;
props.props = GR_WM_PROPS_NOMOVE | GR_WM_PROPS_NODECORATE |
GR_WM_PROPS_NOAUTOMOVE | GR_WM_PROPS_NOAUTORESIZE;
GrSetWMProperties(state->main_window, &props);
state->main_gc = GrNewGC();
GrSetGCForeground(state->main_gc, WHITE);
GrSetGCBackground(state->main_gc, BLACK);
state->animate_interval = 0;
srand(time(0));
init_functions[state->saver](state);
calculate_timeout(state);
GrSelectEvents(GR_ROOT_WINDOW_ID, GR_EVENT_MASK_SCREENSAVER);
GrSetCursor(state->main_window, 1, 1, 1, 1, 0, 0, &cursor, &cursor);
GrMapWindow(state->main_window);
GrSetFocus(state->main_window);
return 0;
}
void calculate_timeout(nstate *state)
{
struct timeval t;
long u;
gettimeofday(&t, NULL);
u = t.tv_usec + (state->animate_interval * 1000);
state->timeout.tv_sec = t.tv_sec + (u / 1000000);
state->timeout.tv_usec = u % 1000000;
}
unsigned long timeout_delay(nstate *state)
{
struct timeval t;
signed long s, m, ret;
gettimeofday(&t, NULL);
if(!state->animate_interval) return 0;
if((t.tv_sec > state->timeout.tv_sec) ||
((t.tv_sec == state->timeout.tv_sec) &&
t.tv_usec >= state->timeout.tv_usec)) return 1;
s = state->timeout.tv_sec - t.tv_sec;
m = ((state->timeout.tv_usec - t.tv_usec) / 1000);
ret = (unsigned long)((1000 * s) + m);
if(ret <= 0) return 1;
else return ret;
}
void do_animate(nstate *state)
{
struct timeval t;
if(!state->animate_interval) return;
gettimeofday(&t, NULL);
if((t.tv_sec > state->timeout.tv_sec) ||
((t.tv_sec == state->timeout.tv_sec) &&
(t.tv_usec >= state->timeout.tv_usec))) {
animate_functions[state->saver](state);
calculate_timeout(state);
}
}
int do_screensaver_event(nstate *state)
{
GR_EVENT_SCREENSAVER *event = &state->event.screensaver;
if(event->activate != GR_FALSE) {
fprintf(stderr, "Got a non-deactivate screensaver event\n");
return 0;
}
return 1;
}
int handle_event(nstate *state)
{
switch(state->event.type) {
case GR_EVENT_TYPE_EXPOSURE:
exposure_functions[state->saver](state);
case GR_EVENT_TYPE_TIMEOUT:
case GR_EVENT_TYPE_NONE:
break;
case GR_EVENT_TYPE_SCREENSAVER:
if(do_screensaver_event(state)) return 0;
break;
case GR_EVENT_TYPE_CLOSE_REQ:
case GR_EVENT_MASK_BUTTON_UP:
case GR_EVENT_MASK_BUTTON_DOWN:
case GR_EVENT_MASK_MOUSE_MOTION:
case GR_EVENT_MASK_KEY_UP:
case GR_EVENT_MASK_KEY_DOWN:
case GR_EVENT_MASK_FOCUS_OUT:
return 0;
default:
fprintf(stderr, "Got unknown event type %d\n",
state->event.type);
break;
}
do_animate(state);
return(1);
}
int main(int argc, char *argv[])
{
int ret;
nstate *state = my_malloc(sizeof(nstate));
if(argc == 2) {
state->saver = atoi(argv[1]) - 1;
if((state->saver) < 0 || (state->saver >= NUM_SAVERS)) {
fprintf(stderr, "Invalid saver number \"%s\"\n",
argv[1]);
return 2;
}
} else state->saver = 0;
if((ret = init(state))) return ret;
do {
GrGetNextEventTimeout(&state->event, timeout_delay(state));
} while(handle_event(state));
GrClose();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -