/*
|
/*
|
* The contents of this file are subject to the Mozilla Public License
|
* The contents of this file are subject to the Mozilla Public License
|
* Version 1.1 (the "License"); you may not use this file except in
|
* Version 1.1 (the "License"); you may not use this file except in
|
* compliance with the License. You may obtain a copy of the License at
|
* compliance with the License. You may obtain a copy of the License at
|
* http://www.mozilla.org/MPL/
|
* http://www.mozilla.org/MPL/
|
*
|
*
|
* Software distributed under the License is distributed on an "AS IS"
|
* Software distributed under the License is distributed on an "AS IS"
|
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
* License for the specific language governing rights and limitations
|
* License for the specific language governing rights and limitations
|
* under the License.
|
* under the License.
|
*
|
*
|
* The Original Code is NanoScreenSaver.
|
* The Original Code is NanoScreenSaver.
|
*
|
*
|
* The Initial Developer of the Original Code is Alex Holden.
|
* The Initial Developer of the Original Code is Alex Holden.
|
* Portions created by Alex Holden are Copyright (C) 2000
|
* Portions created by Alex Holden are Copyright (C) 2000
|
* Alex Holden <alex@linuxhacker.org>. All Rights Reserved.
|
* Alex Holden <alex@linuxhacker.org>. All Rights Reserved.
|
*
|
*
|
* Contributor(s):
|
* Contributor(s):
|
*
|
*
|
* Alternatively, the contents of this file may be used under the terms
|
* Alternatively, the contents of this file may be used under the terms
|
* of the GNU General Public license (the "[GNU] License"), in which case the
|
* of the GNU General Public license (the "[GNU] License"), in which case the
|
* provisions of [GNU] License are applicable instead of those
|
* provisions of [GNU] License are applicable instead of those
|
* above. If you wish to allow use of your version of this file only
|
* above. If you wish to allow use of your version of this file only
|
* under the terms of the [GNU] License and not to allow others to use
|
* under the terms of the [GNU] License and not to allow others to use
|
* your version of this file under the MPL, indicate your decision by
|
* your version of this file under the MPL, indicate your decision by
|
* deleting the provisions above and replace them with the notice and
|
* deleting the provisions above and replace them with the notice and
|
* other provisions required by the [GNU] License. If you do not delete
|
* other provisions required by the [GNU] License. If you do not delete
|
* the provisions above, a recipient may use your version of this file
|
* the provisions above, a recipient may use your version of this file
|
* under either the MPL or the [GNU] License.
|
* under either the MPL or the [GNU] License.
|
*/
|
*/
|
/*
|
/*
|
* A collection of screen savers for Nano-X by Alex Holden.
|
* A collection of screen savers for Nano-X by Alex Holden.
|
*/
|
*/
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <time.h>
|
#include <time.h>
|
#include <math.h>
|
#include <math.h>
|
#include <sys/time.h>
|
#include <sys/time.h>
|
|
|
#define MWINCLUDECOLORS
|
#define MWINCLUDECOLORS
|
#include "nano-X.h"
|
#include "nano-X.h"
|
#include "nsaver.h"
|
#include "nsaver.h"
|
|
|
void *my_malloc(size_t size)
|
void *my_malloc(size_t size)
|
{
|
{
|
void *ret;
|
void *ret;
|
|
|
if(!(ret = malloc(size))) {
|
if(!(ret = malloc(size))) {
|
fprintf(stderr, "Out of memory\n");
|
fprintf(stderr, "Out of memory\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
|
|
return ret;
|
return ret;
|
}
|
}
|
|
|
void get_random_point_on_screen(nstate *state, GR_COORD *x, GR_COORD *y,
|
void get_random_point_on_screen(nstate *state, GR_COORD *x, GR_COORD *y,
|
GR_COLOR *c)
|
GR_COLOR *c)
|
{
|
{
|
if(x) {
|
if(x) {
|
*x = (int) RANDRANGE(0, (state->si.cols - 1.0));
|
*x = (int) RANDRANGE(0, (state->si.cols - 1.0));
|
}
|
}
|
if(y) {
|
if(y) {
|
*y = (int) RANDRANGE(0, (state->si.rows - 1.0));
|
*y = (int) RANDRANGE(0, (state->si.rows - 1.0));
|
}
|
}
|
if(c) {
|
if(c) {
|
*c = MWPALINDEX((int)RANDRANGE(0, (state->si.ncolors - 1)));
|
*c = MWPALINDEX((int)RANDRANGE(0, (state->si.ncolors - 1)));
|
}
|
}
|
}
|
}
|
|
|
void saver1_init(nstate *state) {}
|
void saver1_init(nstate *state) {}
|
|
|
void saver1_exposure(nstate *state)
|
void saver1_exposure(nstate *state)
|
{
|
{
|
GrClearWindow(state->main_window, 0);
|
GrClearWindow(state->main_window, 0);
|
}
|
}
|
|
|
void saver1_animate(nstate *state) {}
|
void saver1_animate(nstate *state) {}
|
|
|
void saver2_init(nstate *state)
|
void saver2_init(nstate *state)
|
{
|
{
|
(int)state->priv = SAVER2_MAXPIXELS;
|
(int)state->priv = SAVER2_MAXPIXELS;
|
state->animate_interval = SAVER2_DELAY;
|
state->animate_interval = SAVER2_DELAY;
|
}
|
}
|
|
|
void saver2_exposure(nstate *state)
|
void saver2_exposure(nstate *state)
|
{
|
{
|
GrClearWindow(state->main_window, 0);
|
GrClearWindow(state->main_window, 0);
|
}
|
}
|
|
|
void saver2_animate(nstate *state)
|
void saver2_animate(nstate *state)
|
{
|
{
|
GR_COORD x, y;
|
GR_COORD x, y;
|
GR_COLOR c;
|
GR_COLOR c;
|
int pixels = SAVER2_PIXELS_PER_FRAME;
|
int pixels = SAVER2_PIXELS_PER_FRAME;
|
|
|
while(pixels--) {
|
while(pixels--) {
|
if(!((int)state->priv--)) {
|
if(!((int)state->priv--)) {
|
(int)state->priv = SAVER2_MAXPIXELS;
|
(int)state->priv = SAVER2_MAXPIXELS;
|
GrClearWindow(state->main_window, 0);
|
GrClearWindow(state->main_window, 0);
|
}
|
}
|
get_random_point_on_screen(state, &x, &y, &c);
|
get_random_point_on_screen(state, &x, &y, &c);
|
GrSetGCForeground(state->main_gc, c);
|
GrSetGCForeground(state->main_gc, c);
|
GrPoint(state->main_window, state->main_gc, x, y);
|
GrPoint(state->main_window, state->main_gc, x, y);
|
}
|
}
|
}
|
}
|
|
|
void saver3_init(nstate *state)
|
void saver3_init(nstate *state)
|
{
|
{
|
s3state *s = my_malloc(sizeof(s3state));
|
s3state *s = my_malloc(sizeof(s3state));
|
state->priv = s;
|
state->priv = s;
|
s->maxsegments = SAVER3_MAXSEGMENTS;
|
s->maxsegments = SAVER3_MAXSEGMENTS;
|
s->lastx = 0;
|
s->lastx = 0;
|
s->lasty = 0;
|
s->lasty = 0;
|
state->animate_interval = SAVER3_DELAY;
|
state->animate_interval = SAVER3_DELAY;
|
}
|
}
|
|
|
void saver3_exposure(nstate *state)
|
void saver3_exposure(nstate *state)
|
{
|
{
|
GrClearWindow(state->main_window, 0);
|
GrClearWindow(state->main_window, 0);
|
}
|
}
|
|
|
void saver3_animate(nstate *state)
|
void saver3_animate(nstate *state)
|
{
|
{
|
GR_COORD newx, newy;
|
GR_COORD newx, newy;
|
GR_COLOR c;
|
GR_COLOR c;
|
s3state *s = state->priv;
|
s3state *s = state->priv;
|
int pixels = SAVER3_SEGMENTS_PER_FRAME;
|
int pixels = SAVER3_SEGMENTS_PER_FRAME;
|
|
|
while(pixels--) {
|
while(pixels--) {
|
if(!(s->maxsegments--)) {
|
if(!(s->maxsegments--)) {
|
s->maxsegments = SAVER3_MAXSEGMENTS;
|
s->maxsegments = SAVER3_MAXSEGMENTS;
|
GrClearWindow(state->main_window, 0);
|
GrClearWindow(state->main_window, 0);
|
}
|
}
|
get_random_point_on_screen(state, &newx, &newy, &c);
|
get_random_point_on_screen(state, &newx, &newy, &c);
|
GrSetGCForeground(state->main_gc, c);
|
GrSetGCForeground(state->main_gc, c);
|
GrLine(state->main_window, state->main_gc, s->lastx, s->lasty,
|
GrLine(state->main_window, state->main_gc, s->lastx, s->lasty,
|
newx, newy);
|
newx, newy);
|
s->lastx = newx;
|
s->lastx = newx;
|
s->lasty = newy;
|
s->lasty = newy;
|
}
|
}
|
}
|
}
|
|
|
void saver4_init(nstate *state)
|
void saver4_init(nstate *state)
|
{
|
{
|
int i;
|
int i;
|
|
|
s4state *s = my_malloc(sizeof(s4state));
|
s4state *s = my_malloc(sizeof(s4state));
|
state->priv = s;
|
state->priv = s;
|
|
|
s->length = 0;
|
s->length = 0;
|
|
|
for(i = 0; i < SAVER4_NUMWORMS; i++) {
|
for(i = 0; i < SAVER4_NUMWORMS; i++) {
|
s->tip = 0;
|
s->tip = 0;
|
get_random_point_on_screen(state, &s->worms[i].points[0].x,
|
get_random_point_on_screen(state, &s->worms[i].points[0].x,
|
&s->worms[i].points[0].y,
|
&s->worms[i].points[0].y,
|
&s->worms[i].colour);
|
&s->worms[i].colour);
|
}
|
}
|
|
|
state->animate_interval = SAVER4_DELAY;
|
state->animate_interval = SAVER4_DELAY;
|
}
|
}
|
|
|
void saver4_exposure(nstate *state)
|
void saver4_exposure(nstate *state)
|
{
|
{
|
int i;
|
int i;
|
s4state *s = state->priv;
|
s4state *s = state->priv;
|
|
|
GrClearWindow(state->main_window, 0);
|
GrClearWindow(state->main_window, 0);
|
|
|
if(!s->length) return;
|
if(!s->length) return;
|
|
|
for(i = 0; i < SAVER4_NUMWORMS; i++) {
|
for(i = 0; i < SAVER4_NUMWORMS; i++) {
|
GrSetGCForeground(state->main_gc, s->worms[i].colour);
|
GrSetGCForeground(state->main_gc, s->worms[i].colour);
|
GrPoints(state->main_window, state->main_gc, s->length,
|
GrPoints(state->main_window, state->main_gc, s->length,
|
s->worms[i].points);
|
s->worms[i].points);
|
}
|
}
|
}
|
}
|
|
|
void saver4_get_new_worm_position(nstate *state, s4state *s, int worm,
|
void saver4_get_new_worm_position(nstate *state, s4state *s, int worm,
|
GR_COORD *newx, GR_COORD *newy)
|
GR_COORD *newx, GR_COORD *newy)
|
{
|
{
|
int i;
|
int i;
|
GR_COORD oldx = s->worms[worm].points[s->tip].x;
|
GR_COORD oldx = s->worms[worm].points[s->tip].x;
|
GR_COORD oldy = s->worms[worm].points[s->tip].y;
|
GR_COORD oldy = s->worms[worm].points[s->tip].y;
|
|
|
do {
|
do {
|
i = (int)RANDRANGE(0, 3.0);
|
i = (int)RANDRANGE(0, 3.0);
|
switch(i) {
|
switch(i) {
|
case 0:
|
case 0:
|
*newx = oldx + 1;
|
*newx = oldx + 1;
|
if(*newx == state->si.cols) *newx = 0;
|
if(*newx == state->si.cols) *newx = 0;
|
break;
|
break;
|
case 1:
|
case 1:
|
*newx = oldx - 1;
|
*newx = oldx - 1;
|
if(*newx == -1) *newx = state->si.cols - 1;
|
if(*newx == -1) *newx = state->si.cols - 1;
|
break;
|
break;
|
case 2:
|
case 2:
|
*newx = oldx;
|
*newx = oldx;
|
break;
|
break;
|
}
|
}
|
|
|
i = (int)RANDRANGE(0, 3.0);
|
i = (int)RANDRANGE(0, 3.0);
|
switch(i) {
|
switch(i) {
|
case 0:
|
case 0:
|
*newy = oldy + 1;
|
*newy = oldy + 1;
|
if(*newy == state->si.rows) *newy = 0;
|
if(*newy == state->si.rows) *newy = 0;
|
break;
|
break;
|
case 1:
|
case 1:
|
*newy = oldy - 1;
|
*newy = oldy - 1;
|
if(*newy == -1) *newy = state->si.rows - 1;
|
if(*newy == -1) *newy = state->si.rows - 1;
|
break;
|
break;
|
case 2:
|
case 2:
|
*newy = oldy;
|
*newy = oldy;
|
break;
|
break;
|
}
|
}
|
} while((*newx == oldx) && (*newy == oldy));
|
} while((*newx == oldx) && (*newy == oldy));
|
}
|
}
|
|
|
int saver4_worm_collides(nstate *state, s4state *s, int x, int y, int thisworm,
|
int saver4_worm_collides(nstate *state, s4state *s, int x, int y, int thisworm,
|
int thispoint)
|
int thispoint)
|
{
|
{
|
int i, n;
|
int i, n;
|
|
|
for(i = 0; i < SAVER4_NUMWORMS; i++) {
|
for(i = 0; i < SAVER4_NUMWORMS; i++) {
|
for(n = 0; n < s->length; n++) {
|
for(n = 0; n < s->length; n++) {
|
if((i == thisworm) && (n == thispoint)) continue;
|
if((i == thisworm) && (n == thispoint)) continue;
|
if((s->worms[i].points[n].x == x) &&
|
if((s->worms[i].points[n].x == x) &&
|
(s->worms[i].points[n].y) == y) {
|
(s->worms[i].points[n].y) == y) {
|
return 1;
|
return 1;
|
}
|
}
|
}
|
}
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
void saver4_animate(nstate *state)
|
void saver4_animate(nstate *state)
|
{
|
{
|
int i, newx, newy, tail, newtip, tries;
|
int i, newx, newy, tail, newtip, tries;
|
s4state *s = state->priv;
|
s4state *s = state->priv;
|
|
|
if(s->length == SAVER4_WORMLENGTH) tail = s->tip + 1;
|
if(s->length == SAVER4_WORMLENGTH) tail = s->tip + 1;
|
else tail = 0;
|
else tail = 0;
|
if(tail == SAVER4_WORMLENGTH) tail = 0;
|
if(tail == SAVER4_WORMLENGTH) tail = 0;
|
newtip = s->tip + 1;
|
newtip = s->tip + 1;
|
if(newtip == SAVER4_WORMLENGTH) newtip = 0;
|
if(newtip == SAVER4_WORMLENGTH) newtip = 0;
|
|
|
for(i = 0; i < SAVER4_NUMWORMS; i++) {
|
for(i = 0; i < SAVER4_NUMWORMS; i++) {
|
if(!saver4_worm_collides(state, s, s->worms[i].points[tail].x,
|
if(!saver4_worm_collides(state, s, s->worms[i].points[tail].x,
|
s->worms[i].points[tail].y, i, tail)) {
|
s->worms[i].points[tail].y, i, tail)) {
|
GrSetGCForeground(state->main_gc, BLACK);
|
GrSetGCForeground(state->main_gc, BLACK);
|
GrPoint(state->main_window, state->main_gc,
|
GrPoint(state->main_window, state->main_gc,
|
s->worms[i].points[tail].x,
|
s->worms[i].points[tail].x,
|
s->worms[i].points[tail].y);
|
s->worms[i].points[tail].y);
|
}
|
}
|
for(tries = SAVER4_COLLISION_RELUCTANCE; tries; tries--) {
|
for(tries = SAVER4_COLLISION_RELUCTANCE; tries; tries--) {
|
saver4_get_new_worm_position(state, s, i, &newx,
|
saver4_get_new_worm_position(state, s, i, &newx,
|
&newy);
|
&newy);
|
if(!saver4_worm_collides(state, s, newx, newy, -1, -1))
|
if(!saver4_worm_collides(state, s, newx, newy, -1, -1))
|
break;
|
break;
|
}
|
}
|
s->worms[i].points[newtip].x = newx;
|
s->worms[i].points[newtip].x = newx;
|
s->worms[i].points[newtip].y = newy;
|
s->worms[i].points[newtip].y = newy;
|
if(tries) {
|
if(tries) {
|
GrSetGCForeground(state->main_gc, s->worms[i].colour);
|
GrSetGCForeground(state->main_gc, s->worms[i].colour);
|
GrPoint(state->main_window, state->main_gc, newx, newy);
|
GrPoint(state->main_window, state->main_gc, newx, newy);
|
}
|
}
|
}
|
}
|
|
|
s->tip = newtip;
|
s->tip = newtip;
|
if(s->length < SAVER4_WORMLENGTH) s->length++;
|
if(s->length < SAVER4_WORMLENGTH) s->length++;
|
}
|
}
|
|
|
void saver5_init(nstate *state)
|
void saver5_init(nstate *state)
|
{
|
{
|
int i;
|
int i;
|
|
|
s5state *s = my_malloc(sizeof(s5state));
|
s5state *s = my_malloc(sizeof(s5state));
|
state->priv = s;
|
state->priv = s;
|
|
|
s->numstars = 0;
|
s->numstars = 0;
|
|
|
for(i = 0; i < SAVER5_NUMSTARS; i++) {
|
for(i = 0; i < SAVER5_NUMSTARS; i++) {
|
s->stars[i].angle = RANDRANGE(0, (2 * M_PI));
|
s->stars[i].angle = RANDRANGE(0, (2 * M_PI));
|
s->stars[i].pos = 1;
|
s->stars[i].pos = 1;
|
}
|
}
|
|
|
state->animate_interval = SAVER5_DELAY;
|
state->animate_interval = SAVER5_DELAY;
|
}
|
}
|
|
|
int saver5_drawstar(nstate *state, s5state *s, int star, int delete)
|
int saver5_drawstar(nstate *state, s5state *s, int star, int delete)
|
{
|
{
|
int opp, adj;
|
int opp, adj;
|
GR_COORD x, y;
|
GR_COORD x, y;
|
|
|
if(delete) GrSetGCForeground(state->main_gc, BLACK);
|
if(delete) GrSetGCForeground(state->main_gc, BLACK);
|
else GrSetGCForeground(state->main_gc, WHITE);
|
else GrSetGCForeground(state->main_gc, WHITE);
|
|
|
opp = (int)(sin(s->stars[star].angle) * s->stars[star].pos);
|
opp = (int)(sin(s->stars[star].angle) * s->stars[star].pos);
|
adj = (int)(cos(s->stars[star].angle) * s->stars[star].pos);
|
adj = (int)(cos(s->stars[star].angle) * s->stars[star].pos);
|
|
|
x = (state->si.cols / 2) + adj;
|
x = (state->si.cols / 2) + adj;
|
y = (state->si.rows / 2) + opp;
|
y = (state->si.rows / 2) + opp;
|
|
|
if((x < 0) || (y < 0) || (x >= state->si.cols) || (y >= state->si.rows))
|
if((x < 0) || (y < 0) || (x >= state->si.cols) || (y >= state->si.rows))
|
return 1;
|
return 1;
|
|
|
GrPoint(state->main_window, state->main_gc, x, y);
|
GrPoint(state->main_window, state->main_gc, x, y);
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
void saver5_exposure(nstate *state)
|
void saver5_exposure(nstate *state)
|
{
|
{
|
int i;
|
int i;
|
s5state *s = state->priv;
|
s5state *s = state->priv;
|
|
|
GrClearWindow(state->main_window, 0);
|
GrClearWindow(state->main_window, 0);
|
|
|
for(i = 0; i < SAVER5_NUMSTARS; i++) {
|
for(i = 0; i < SAVER5_NUMSTARS; i++) {
|
saver5_drawstar(state, s, i, 0);
|
saver5_drawstar(state, s, i, 0);
|
}
|
}
|
}
|
}
|
|
|
void saver5_animate(nstate *state)
|
void saver5_animate(nstate *state)
|
{
|
{
|
int i;
|
int i;
|
double position, scale, increment;
|
double position, scale, increment;
|
s5state *s = state->priv;
|
s5state *s = state->priv;
|
|
|
if(s->numstars < SAVER5_NUMSTARS) {
|
if(s->numstars < SAVER5_NUMSTARS) {
|
s->numstars += SAVER5_STARS_INCREMENT;
|
s->numstars += SAVER5_STARS_INCREMENT;
|
if(s->numstars > SAVER5_NUMSTARS)
|
if(s->numstars > SAVER5_NUMSTARS)
|
s->numstars = SAVER5_NUMSTARS;
|
s->numstars = SAVER5_NUMSTARS;
|
}
|
}
|
|
|
for(i = 0; i < s->numstars; i++) {
|
for(i = 0; i < s->numstars; i++) {
|
saver5_drawstar(state, s, i, 1);
|
saver5_drawstar(state, s, i, 1);
|
position = (double)s->stars[i].pos /
|
position = (double)s->stars[i].pos /
|
(double)(state->si.cols / 2);
|
(double)(state->si.cols / 2);
|
scale = sin((position * M_PI_2) + M_PI + M_PI_2) + 1.0;
|
scale = sin((position * M_PI_2) + M_PI + M_PI_2) + 1.0;
|
increment = (scale * SAVER5_STARS_ACCEL_RATE) + 1;
|
increment = (scale * SAVER5_STARS_ACCEL_RATE) + 1;
|
s->stars[i].pos += (int) increment;
|
s->stars[i].pos += (int) increment;
|
if(saver5_drawstar(state, s, i, 0)) {
|
if(saver5_drawstar(state, s, i, 0)) {
|
s->stars[i].pos = 1;
|
s->stars[i].pos = 1;
|
s->stars[i].angle = RANDRANGE(0, (2 * M_PI));
|
s->stars[i].angle = RANDRANGE(0, (2 * M_PI));
|
saver5_drawstar(state, s, i, 0);
|
saver5_drawstar(state, s, i, 0);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
void saver6_init(nstate *state)
|
void saver6_init(nstate *state)
|
{
|
{
|
int i, n;
|
int i, n;
|
|
|
s6state *s = my_malloc(sizeof(s6state));
|
s6state *s = my_malloc(sizeof(s6state));
|
state->priv = s;
|
state->priv = s;
|
|
|
s->new_bolt_time = 0;
|
s->new_bolt_time = 0;
|
|
|
for(i = 0; i < SAVER6_MAXBOLTS; i++) {
|
for(i = 0; i < SAVER6_MAXBOLTS; i++) {
|
s->bolts[i].duration = 0;
|
s->bolts[i].duration = 0;
|
for(n = 0; n < SAVER6_MAXFORKS; n++) {
|
for(n = 0; n < SAVER6_MAXFORKS; n++) {
|
s->bolts[i].forks[n].valid = 0;
|
s->bolts[i].forks[n].valid = 0;
|
}
|
}
|
}
|
}
|
|
|
state->animate_interval = SAVER6_DELAY;
|
state->animate_interval = SAVER6_DELAY;
|
}
|
}
|
|
|
void saver6_drawfork(nstate *state, s6state *s, int bolt, int fork, int delete)
|
void saver6_drawfork(nstate *state, s6state *s, int bolt, int fork, int delete)
|
{
|
{
|
int i;
|
int i;
|
|
|
if(delete) GrSetGCForeground(state->main_gc, BLACK);
|
if(delete) GrSetGCForeground(state->main_gc, BLACK);
|
for(i = 0; i < SAVER6_THICKNESS; i++) {
|
for(i = 0; i < SAVER6_THICKNESS; i++) {
|
if(!delete) {
|
if(!delete) {
|
if((i < 2) || (i >= SAVER6_THICKNESS - 2))
|
if((i < 2) || (i >= SAVER6_THICKNESS - 2))
|
GrSetGCForeground(state->main_gc, LTBLUE);
|
GrSetGCForeground(state->main_gc, LTBLUE);
|
else GrSetGCForeground(state->main_gc, WHITE);
|
else GrSetGCForeground(state->main_gc, WHITE);
|
}
|
}
|
GrPoly(state->main_window, state->main_gc,
|
GrPoly(state->main_window, state->main_gc,
|
s->bolts[bolt].forks[fork].valid,
|
s->bolts[bolt].forks[fork].valid,
|
s->bolts[bolt].forks[fork].vertices[i]);
|
s->bolts[bolt].forks[fork].vertices[i]);
|
}
|
}
|
}
|
}
|
|
|
void saver6_drawbolt(nstate *state, s6state *s, int bolt, int delete)
|
void saver6_drawbolt(nstate *state, s6state *s, int bolt, int delete)
|
{
|
{
|
int n;
|
int n;
|
|
|
for(n = 0; n < SAVER6_MAXFORKS; n++)
|
for(n = 0; n < SAVER6_MAXFORKS; n++)
|
if(s->bolts[bolt].forks[n].valid)
|
if(s->bolts[bolt].forks[n].valid)
|
saver6_drawfork(state, s, bolt, n, delete);
|
saver6_drawfork(state, s, bolt, n, delete);
|
}
|
}
|
|
|
void saver6_drawlightning(nstate *state, s6state *s, int delete)
|
void saver6_drawlightning(nstate *state, s6state *s, int delete)
|
{
|
{
|
int i;
|
int i;
|
|
|
for(i = 0; i < SAVER6_MAXBOLTS; i++) {
|
for(i = 0; i < SAVER6_MAXBOLTS; i++) {
|
if(s->bolts[i].duration) {
|
if(s->bolts[i].duration) {
|
if(delete) s->bolts[i].duration--;
|
if(delete) s->bolts[i].duration--;
|
saver6_drawbolt(state, s, i, delete);
|
saver6_drawbolt(state, s, i, delete);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
void saver6_exposure(nstate *state)
|
void saver6_exposure(nstate *state)
|
{
|
{
|
s6state *s = state->priv;
|
s6state *s = state->priv;
|
|
|
GrClearWindow(state->main_window, 0);
|
GrClearWindow(state->main_window, 0);
|
|
|
saver6_drawlightning(state, s, 0);
|
saver6_drawlightning(state, s, 0);
|
}
|
}
|
|
|
void saver6_setvertices(s6state *s, int bolt, int fork, int vert, GR_COORD x,
|
void saver6_setvertices(s6state *s, int bolt, int fork, int vert, GR_COORD x,
|
GR_COORD y)
|
GR_COORD y)
|
{
|
{
|
int i;
|
int i;
|
|
|
for(i = 0; i < SAVER6_THICKNESS; i++) {
|
for(i = 0; i < SAVER6_THICKNESS; i++) {
|
s->bolts[bolt].forks[fork].vertices[i][vert].x = x + i;
|
s->bolts[bolt].forks[fork].vertices[i][vert].x = x + i;
|
s->bolts[bolt].forks[fork].vertices[i][vert].y = y;
|
s->bolts[bolt].forks[fork].vertices[i][vert].y = y;
|
}
|
}
|
}
|
}
|
|
|
void saver6_perturb(nstate *state, GR_COORD *x, GR_COORD *y, int maxperturb)
|
void saver6_perturb(nstate *state, GR_COORD *x, GR_COORD *y, int maxperturb)
|
{
|
{
|
*x += (int)RANDRANGE(0, (maxperturb - 1.0)) -
|
*x += (int)RANDRANGE(0, (maxperturb - 1.0)) -
|
(double)(maxperturb / 2.0);
|
(double)(maxperturb / 2.0);
|
if(*x < 0) *x = 0;
|
if(*x < 0) *x = 0;
|
if(*x > (state->si.cols - 1)) *x = state->si.cols - 1;
|
if(*x > (state->si.cols - 1)) *x = state->si.cols - 1;
|
|
|
*y += (int)RANDRANGE(0, (maxperturb - 1.0)) -
|
*y += (int)RANDRANGE(0, (maxperturb - 1.0)) -
|
(double)(maxperturb / 2.0);
|
(double)(maxperturb / 2.0);
|
if(*y < 0) *y = 0;
|
if(*y < 0) *y = 0;
|
if(*y > (state->si.cols - 1)) *y = state->si.cols - 1;
|
if(*y > (state->si.cols - 1)) *y = state->si.cols - 1;
|
}
|
}
|
|
|
void saver6_makefork(nstate *state, s6state *s, int bolt, int fork, GR_COORD x,
|
void saver6_makefork(nstate *state, s6state *s, int bolt, int fork, GR_COORD x,
|
GR_COORD y)
|
GR_COORD y)
|
{
|
{
|
int i, vertices;
|
int i, vertices;
|
double length, incr, pos, angle, scale;
|
double length, incr, pos, angle, scale;
|
GR_COORD ex, ey, nx, ny, xlen, ylen;
|
GR_COORD ex, ey, nx, ny, xlen, ylen;
|
|
|
saver6_setvertices(s, bolt, fork, 0, x , y);
|
saver6_setvertices(s, bolt, fork, 0, x , y);
|
|
|
scale = (double)(state->si.rows - y) / (double)state->si.rows;
|
scale = (double)(state->si.rows - y) / (double)state->si.rows;
|
|
|
vertices = (int)(scale * RANDRANGE(SAVER6_MINFULLVERTICES,
|
vertices = (int)(scale * RANDRANGE(SAVER6_MINFULLVERTICES,
|
SAVER6_MAXVERTICES));
|
SAVER6_MAXVERTICES));
|
|
|
if(vertices < SAVER6_MINVERTICES) vertices = SAVER6_MINVERTICES;
|
if(vertices < SAVER6_MINVERTICES) vertices = SAVER6_MINVERTICES;
|
|
|
s->bolts[bolt].forks[fork].valid = vertices;
|
s->bolts[bolt].forks[fork].valid = vertices;
|
|
|
ey = state->si.rows - SAVER6_MAXEND_Y +
|
ey = state->si.rows - SAVER6_MAXEND_Y +
|
(int)RANDRANGE(0, SAVER6_MAXEND_Y - 1.0);
|
(int)RANDRANGE(0, SAVER6_MAXEND_Y - 1.0);
|
if((ey - y) <= 0) ey = SAVER6_MINDROP;
|
if((ey - y) <= 0) ey = SAVER6_MINDROP;
|
if(ey >= (state->si.rows - 1)) ey = state->si.rows - 1;
|
if(ey >= (state->si.rows - 1)) ey = state->si.rows - 1;
|
|
|
if(!fork) {
|
if(!fork) {
|
ex = x + (int)RANDRANGE(0, ((state->si.cols - 1.0) / 2.0));
|
ex = x + (int)RANDRANGE(0, ((state->si.cols - 1.0) / 2.0));
|
} else {
|
} else {
|
ex = x + (int)(RANDRANGE(0, (ey - y)) / 2.0) - ((ey - y) / 2.0);
|
ex = x + (int)(RANDRANGE(0, (ey - y)) / 2.0) - ((ey - y) / 2.0);
|
}
|
}
|
|
|
if(ex >= state->si.cols) ex = state->si.cols - 1;
|
if(ex >= state->si.cols) ex = state->si.cols - 1;
|
if(ex < 0) ex = 0;
|
if(ex < 0) ex = 0;
|
|
|
xlen = MAX(x, ex) - MIN(x, ex);
|
xlen = MAX(x, ex) - MIN(x, ex);
|
ylen = MAX(y, ey) - MIN(y, ey);
|
ylen = MAX(y, ey) - MIN(y, ey);
|
|
|
length = sqrt(((double)(xlen * xlen) + (double)(ylen * ylen)));
|
length = sqrt(((double)(xlen * xlen) + (double)(ylen * ylen)));
|
incr = length / (vertices - 1);
|
incr = length / (vertices - 1);
|
angle = atan(((double)xlen / (double)ylen));
|
angle = atan(((double)xlen / (double)ylen));
|
|
|
for(i = vertices - 1; i ; i--) {
|
for(i = vertices - 1; i ; i--) {
|
pos = (incr * (i - 1)) + (RANDRANGE(0, SAVER6_MAXZIGZAG) -
|
pos = (incr * (i - 1)) + (RANDRANGE(0, SAVER6_MAXZIGZAG) -
|
((double)SAVER6_MAXZIGZAG / 2.0));
|
((double)SAVER6_MAXZIGZAG / 2.0));
|
if(pos < 0) pos = 0;
|
if(pos < 0) pos = 0;
|
if(pos > length) pos = length;
|
if(pos > length) pos = length;
|
nx = x - (pos * sin(angle));
|
nx = x - (pos * sin(angle));
|
ny = y + pos * cos(angle);
|
ny = y + pos * cos(angle);
|
saver6_perturb(state, &nx, &ny, SAVER6_MAXZIGZAG);
|
saver6_perturb(state, &nx, &ny, SAVER6_MAXZIGZAG);
|
saver6_setvertices(s, bolt, fork, i, nx , ny);
|
saver6_setvertices(s, bolt, fork, i, nx , ny);
|
}
|
}
|
}
|
}
|
|
|
int saver6_makeforks(nstate *state, s6state *s, int bolt, int fork,
|
int saver6_makeforks(nstate *state, s6state *s, int bolt, int fork,
|
int *vert, int *nextfork)
|
int *vert, int *nextfork)
|
{
|
{
|
int thisvert = 1, thisfork;
|
int thisvert = 1, thisfork;
|
double prob;
|
double prob;
|
|
|
if(*vert == (s->bolts[bolt].forks[fork].valid - 1)) return 0;
|
if(*vert == (s->bolts[bolt].forks[fork].valid - 1)) return 0;
|
if(*nextfork == SAVER6_MAXFORKS) return 0;
|
if(*nextfork == SAVER6_MAXFORKS) return 0;
|
|
|
prob = (double)SAVER6_FORK_PROBABILITY * ((double)*vert /
|
prob = (double)SAVER6_FORK_PROBABILITY * ((double)*vert /
|
(double)s->bolts[bolt].forks[fork].valid) *
|
(double)s->bolts[bolt].forks[fork].valid) *
|
(1.0 / ((double)fork + 1.0));
|
(1.0 / ((double)fork + 1.0));
|
if(RANDRANGE(0, 1) < prob) {
|
if(RANDRANGE(0, 1) < prob) {
|
thisfork = *nextfork;
|
thisfork = *nextfork;
|
saver6_makefork(state, s, bolt, thisfork,
|
saver6_makefork(state, s, bolt, thisfork,
|
s->bolts[bolt].forks[fork].vertices[0][*vert].x,
|
s->bolts[bolt].forks[fork].vertices[0][*vert].x,
|
s->bolts[bolt].forks[fork].vertices[0][*vert].y);
|
s->bolts[bolt].forks[fork].vertices[0][*vert].y);
|
*nextfork += 1;
|
*nextfork += 1;
|
while(saver6_makeforks(state, s, bolt, thisfork, &thisvert,
|
while(saver6_makeforks(state, s, bolt, thisfork, &thisvert,
|
nextfork));
|
nextfork));
|
}
|
}
|
|
|
*vert += 1;
|
*vert += 1;
|
|
|
return 1;
|
return 1;
|
}
|
}
|
|
|
void saver6_makebolt(nstate *state, s6state *s, int bolt)
|
void saver6_makebolt(nstate *state, s6state *s, int bolt)
|
{
|
{
|
GR_COORD x;
|
GR_COORD x;
|
int vert = 1, nextfork = 1, n;
|
int vert = 1, nextfork = 1, n;
|
|
|
for(n = 0; n < SAVER6_MAXFORKS; n++)
|
for(n = 0; n < SAVER6_MAXFORKS; n++)
|
s->bolts[bolt].forks[n].valid = 0;
|
s->bolts[bolt].forks[n].valid = 0;
|
|
|
x = (int)RANDRANGE(0, (state->si.cols - 1.0));
|
x = (int)RANDRANGE(0, (state->si.cols - 1.0));
|
|
|
saver6_makefork(state, s, bolt, 0, x, 0);
|
saver6_makefork(state, s, bolt, 0, x, 0);
|
|
|
while(saver6_makeforks(state, s, bolt, 0, &vert, &nextfork));
|
while(saver6_makeforks(state, s, bolt, 0, &vert, &nextfork));
|
}
|
}
|
|
|
void saver6_newbolt(nstate *state, s6state *s)
|
void saver6_newbolt(nstate *state, s6state *s)
|
{
|
{
|
int i;
|
int i;
|
|
|
for(i = 0; i < SAVER6_MAXBOLTS; i++) {
|
for(i = 0; i < SAVER6_MAXBOLTS; i++) {
|
if(!s->bolts[i].duration) {
|
if(!s->bolts[i].duration) {
|
saver6_makebolt(state, s, i);
|
saver6_makebolt(state, s, i);
|
s->bolts[i].duration = RANDRANGE(SAVER6_MINDURATION,
|
s->bolts[i].duration = RANDRANGE(SAVER6_MINDURATION,
|
SAVER6_MAXDURATION);
|
SAVER6_MAXDURATION);
|
saver6_drawbolt(state, s, i, 0);
|
saver6_drawbolt(state, s, i, 0);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
s->new_bolt_time = RANDRANGE(1, SAVER6_MAXNEWBOLTTIME);
|
s->new_bolt_time = RANDRANGE(1, SAVER6_MAXNEWBOLTTIME);
|
}
|
}
|
|
|
void saver6_perturb_bolt(nstate *state, s6state *s, int bolt, int fork)
|
void saver6_perturb_bolt(nstate *state, s6state *s, int bolt, int fork)
|
{
|
{
|
int m, o;
|
int m, o;
|
GR_COORD x, ox, y, oy;
|
GR_COORD x, ox, y, oy;
|
|
|
for(m = 1; m < s->bolts[bolt].forks[fork].valid; m++) {
|
for(m = 1; m < s->bolts[bolt].forks[fork].valid; m++) {
|
ox = x = s->bolts[bolt].forks[fork].vertices[0][m].x;
|
ox = x = s->bolts[bolt].forks[fork].vertices[0][m].x;
|
oy = y = s->bolts[bolt].forks[fork].vertices[0][m].y;
|
oy = y = s->bolts[bolt].forks[fork].vertices[0][m].y;
|
saver6_perturb(state, &x, &y, SAVER6_MAXZIGZAG);
|
saver6_perturb(state, &x, &y, SAVER6_MAXZIGZAG);
|
saver6_setvertices(s, bolt, fork, m, x, y);
|
saver6_setvertices(s, bolt, fork, m, x, y);
|
for(o = fork + 1; o < SAVER6_MAXFORKS; o++) {
|
for(o = fork + 1; o < SAVER6_MAXFORKS; o++) {
|
if((s->bolts[bolt].forks[o].vertices[0][0].x == ox) &&
|
if((s->bolts[bolt].forks[o].vertices[0][0].x == ox) &&
|
(s->bolts[bolt].forks[o].vertices[0][0].y
|
(s->bolts[bolt].forks[o].vertices[0][0].y
|
== oy)) {
|
== oy)) {
|
saver6_setvertices(s, bolt, o, 0, x, y);
|
saver6_setvertices(s, bolt, o, 0, x, y);
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
void saver6_perturb_lightning(nstate *state, s6state *s)
|
void saver6_perturb_lightning(nstate *state, s6state *s)
|
{
|
{
|
int i, n;
|
int i, n;
|
|
|
for(i = 0; i < SAVER6_MAXBOLTS; i++) {
|
for(i = 0; i < SAVER6_MAXBOLTS; i++) {
|
if(!s->bolts[i].duration) continue;
|
if(!s->bolts[i].duration) continue;
|
for(n = 0; n < SAVER6_MAXFORKS; n++) {
|
for(n = 0; n < SAVER6_MAXFORKS; n++) {
|
if(!s->bolts[i].forks[n].valid) continue;
|
if(!s->bolts[i].forks[n].valid) continue;
|
saver6_perturb_bolt(state, s, i, n);
|
saver6_perturb_bolt(state, s, i, n);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
void saver6_animate(nstate *state)
|
void saver6_animate(nstate *state)
|
{
|
{
|
s6state *s = state->priv;
|
s6state *s = state->priv;
|
|
|
saver6_drawlightning(state, s, 1);
|
saver6_drawlightning(state, s, 1);
|
saver6_perturb_lightning(state, s);
|
saver6_perturb_lightning(state, s);
|
saver6_drawlightning(state, s, 0);
|
saver6_drawlightning(state, s, 0);
|
|
|
if(!s->new_bolt_time--) saver6_newbolt(state, s);
|
if(!s->new_bolt_time--) saver6_newbolt(state, s);
|
}
|
}
|
|
|
/* The algorithm used in saver7 was adapted from "grav" by Greg Bowering */
|
/* The algorithm used in saver7 was adapted from "grav" by Greg Bowering */
|
|
|
void saver7_drawstar(nstate *state, s7state *s)
|
void saver7_drawstar(nstate *state, s7state *s)
|
{
|
{
|
GrSetGCForeground(state->main_gc, SAVER7_STARCOLOUR);
|
GrSetGCForeground(state->main_gc, SAVER7_STARCOLOUR);
|
GrFillEllipse(state->main_window, state->main_gc, s->starx, s->stary,
|
GrFillEllipse(state->main_window, state->main_gc, s->starx, s->stary,
|
SAVER7_STARRADIUS, SAVER7_STARRADIUS);
|
SAVER7_STARRADIUS, SAVER7_STARRADIUS);
|
}
|
}
|
|
|
void saver7_drawplanet(nstate *state, s7state *s, int planet, int erase)
|
void saver7_drawplanet(nstate *state, s7state *s, int planet, int erase)
|
{
|
{
|
if(erase) GrSetGCForeground(state->main_gc, BLACK);
|
if(erase) GrSetGCForeground(state->main_gc, BLACK);
|
else GrSetGCForeground(state->main_gc, s->planets[planet].colour);
|
else GrSetGCForeground(state->main_gc, s->planets[planet].colour);
|
|
|
if((s->planets[planet].ax < 0) || (s->planets[planet].ay < 0) ||
|
if((s->planets[planet].ax < 0) || (s->planets[planet].ay < 0) ||
|
(s->planets[planet].ax >= state->si.cols) ||
|
(s->planets[planet].ax >= state->si.cols) ||
|
(s->planets[planet].ay >= state->si.rows)) {
|
(s->planets[planet].ay >= state->si.rows)) {
|
return;
|
return;
|
}
|
}
|
|
|
GrFillEllipse(state->main_window, state->main_gc, s->planets[planet].ax,
|
GrFillEllipse(state->main_window, state->main_gc, s->planets[planet].ax,
|
s->planets[planet].ay,
|
s->planets[planet].ay,
|
SAVER7_PLANETRADIUS, SAVER7_PLANETRADIUS);
|
SAVER7_PLANETRADIUS, SAVER7_PLANETRADIUS);
|
}
|
}
|
|
|
void saver7_calc_planet_position(nstate *state, s7state *s, int planet)
|
void saver7_calc_planet_position(nstate *state, s7state *s, int planet)
|
{
|
{
|
if(s->planets[planet].r > -SAVER7_ALMOSTDIST) {
|
if(s->planets[planet].r > -SAVER7_ALMOSTDIST) {
|
s->planets[planet].ax = (int)((double) state->si.cols *
|
s->planets[planet].ax = (int)((double) state->si.cols *
|
(0.5 + (s->planets[planet].x / (s->planets[planet].r +
|
(0.5 + (s->planets[planet].x / (s->planets[planet].r +
|
SAVER7_DIST))));
|
SAVER7_DIST))));
|
s->planets[planet].ay = (int)((double) state->si.rows *
|
s->planets[planet].ay = (int)((double) state->si.rows *
|
(0.5 + (s->planets[planet].y / (s->planets[planet].r +
|
(0.5 + (s->planets[planet].y / (s->planets[planet].r +
|
SAVER7_DIST))));
|
SAVER7_DIST))));
|
} else {
|
} else {
|
s->planets[planet].ax = -1;
|
s->planets[planet].ax = -1;
|
s->planets[planet].ay = -1;
|
s->planets[planet].ay = -1;
|
}
|
}
|
}
|
}
|
|
|
void saver7_init(nstate *state)
|
void saver7_init(nstate *state)
|
{
|
{
|
int i;
|
int i;
|
s7state *s = my_malloc(sizeof(s7state));
|
s7state *s = my_malloc(sizeof(s7state));
|
state->priv = s;
|
state->priv = s;
|
|
|
s->starx = state->si.cols / 2;
|
s->starx = state->si.cols / 2;
|
s->stary = state->si.rows / 2;
|
s->stary = state->si.rows / 2;
|
|
|
for(i = 0; i < SAVER7_PLANETS; i++) {
|
for(i = 0; i < SAVER7_PLANETS; i++) {
|
s->planets[i].r = RANDRANGE(SAVER7_MIN_STARTDIM,
|
s->planets[i].r = RANDRANGE(SAVER7_MIN_STARTDIM,
|
SAVER7_MAX_STARTDIM);
|
SAVER7_MAX_STARTDIM);
|
s->planets[i].x = RANDRANGE(SAVER7_MIN_STARTDIM,
|
s->planets[i].x = RANDRANGE(SAVER7_MIN_STARTDIM,
|
SAVER7_MAX_STARTDIM);
|
SAVER7_MAX_STARTDIM);
|
s->planets[i].y = RANDRANGE(SAVER7_MIN_STARTDIM,
|
s->planets[i].y = RANDRANGE(SAVER7_MIN_STARTDIM,
|
SAVER7_MAX_STARTDIM);
|
SAVER7_MAX_STARTDIM);
|
s->planets[i].rv = RANDRANGE(SAVER7_MIN_STARTVEL,
|
s->planets[i].rv = RANDRANGE(SAVER7_MIN_STARTVEL,
|
SAVER7_MAX_STARTVEL);
|
SAVER7_MAX_STARTVEL);
|
s->planets[i].xv = RANDRANGE(SAVER7_MIN_STARTVEL,
|
s->planets[i].xv = RANDRANGE(SAVER7_MIN_STARTVEL,
|
SAVER7_MAX_STARTVEL);
|
SAVER7_MAX_STARTVEL);
|
s->planets[i].yv = RANDRANGE(SAVER7_MIN_STARTVEL,
|
s->planets[i].yv = RANDRANGE(SAVER7_MIN_STARTVEL,
|
SAVER7_MAX_STARTVEL);
|
SAVER7_MAX_STARTVEL);
|
s->planets[i].colour = RANDRANGE(0, (state->si.ncolors - 1));
|
s->planets[i].colour = RANDRANGE(0, (state->si.ncolors - 1));
|
saver7_calc_planet_position(state, s, i);
|
saver7_calc_planet_position(state, s, i);
|
saver7_drawplanet(state, s, i, 0);
|
saver7_drawplanet(state, s, i, 0);
|
}
|
}
|
|
|
saver7_drawstar(state, s);
|
saver7_drawstar(state, s);
|
|
|
state->animate_interval = SAVER7_DELAY;
|
state->animate_interval = SAVER7_DELAY;
|
}
|
}
|
|
|
void saver7_exposure(nstate *state)
|
void saver7_exposure(nstate *state)
|
{
|
{
|
int i;
|
int i;
|
s7state *s = state->priv;
|
s7state *s = state->priv;
|
|
|
GrClearWindow(state->main_window, 0);
|
GrClearWindow(state->main_window, 0);
|
|
|
for(i = 0; i < SAVER7_PLANETS; i++)
|
for(i = 0; i < SAVER7_PLANETS; i++)
|
saver7_drawplanet(state, s, i, 0);
|
saver7_drawplanet(state, s, i, 0);
|
|
|
saver7_drawstar(state, s);
|
saver7_drawstar(state, s);
|
}
|
}
|
|
|
void saver7_moveplanet(nstate *state, s7state *s, int planet)
|
void saver7_moveplanet(nstate *state, s7state *s, int planet)
|
{
|
{
|
double dist;
|
double dist;
|
double accel;
|
double accel;
|
|
|
dist = (s->planets[planet].x * s->planets[planet].x) +
|
dist = (s->planets[planet].x * s->planets[planet].x) +
|
(s->planets[planet].y * s->planets[planet].y) +
|
(s->planets[planet].y * s->planets[planet].y) +
|
(s->planets[planet].r * s->planets[planet].r);
|
(s->planets[planet].r * s->planets[planet].r);
|
if(dist < SAVER7_COLLIDE) dist = SAVER7_COLLIDE;
|
if(dist < SAVER7_COLLIDE) dist = SAVER7_COLLIDE;
|
dist = sqrt(dist);
|
dist = sqrt(dist);
|
dist = dist * dist * dist;
|
dist = dist * dist * dist;
|
|
|
#ifdef SAVER7_USE_DAMPING
|
#ifdef SAVER7_USE_DAMPING
|
accel = s->planets[planet].r * SAVER7_G / dist;
|
accel = s->planets[planet].r * SAVER7_G / dist;
|
if(accel > SAVER7_MAX_ACCEL) accel = SAVER7_MAX_ACCEL;
|
if(accel > SAVER7_MAX_ACCEL) accel = SAVER7_MAX_ACCEL;
|
else 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) *
|
s->planets[planet].rv = (s->planets[planet].rv + accel) *
|
SAVER7_DAMPING_FACTOR;
|
SAVER7_DAMPING_FACTOR;
|
s->planets[planet].r += s->planets[planet].rv;
|
s->planets[planet].r += s->planets[planet].rv;
|
accel = s->planets[planet].x * SAVER7_G / dist;
|
accel = s->planets[planet].x * SAVER7_G / dist;
|
if(accel > SAVER7_MAX_ACCEL) accel = SAVER7_MAX_ACCEL;
|
if(accel > SAVER7_MAX_ACCEL) accel = SAVER7_MAX_ACCEL;
|
else 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) *
|
s->planets[planet].xv = (s->planets[planet].xv + accel) *
|
SAVER7_DAMPING_FACTOR;
|
SAVER7_DAMPING_FACTOR;
|
s->planets[planet].x += s->planets[planet].xv;
|
s->planets[planet].x += s->planets[planet].xv;
|
accel = s->planets[planet].y * SAVER7_G / dist;
|
accel = s->planets[planet].y * SAVER7_G / dist;
|
if(accel > SAVER7_MAX_ACCEL) accel = SAVER7_MAX_ACCEL;
|
if(accel > SAVER7_MAX_ACCEL) accel = SAVER7_MAX_ACCEL;
|
else 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) *
|
s->planets[planet].yv = (s->planets[planet].yv + accel) *
|
SAVER7_DAMPING_FACTOR;
|
SAVER7_DAMPING_FACTOR;
|
s->planets[planet].y += s->planets[planet].yv;
|
s->planets[planet].y += s->planets[planet].yv;
|
#else
|
#else
|
accel = s->planets[planet].r * SAVER7_G / dist;
|
accel = s->planets[planet].r * SAVER7_G / dist;
|
s->planets[planet].rv += accel;
|
s->planets[planet].rv += accel;
|
s->planets[planet].r += s->planets[planet].rv;
|
s->planets[planet].r += s->planets[planet].rv;
|
accel = s->planets[planet].x * SAVER7_G / dist;
|
accel = s->planets[planet].x * SAVER7_G / dist;
|
s->planets[planet].xv += accel;
|
s->planets[planet].xv += accel;
|
s->planets[planet].x += s->planets[planet].xv;
|
s->planets[planet].x += s->planets[planet].xv;
|
accel = s->planets[planet].y * SAVER7_G / dist;
|
accel = s->planets[planet].y * SAVER7_G / dist;
|
s->planets[planet].yv += accel;
|
s->planets[planet].yv += accel;
|
s->planets[planet].y += s->planets[planet].yv;
|
s->planets[planet].y += s->planets[planet].yv;
|
#endif
|
#endif
|
}
|
}
|
|
|
void saver7_animate(nstate *state)
|
void saver7_animate(nstate *state)
|
{
|
{
|
int i;
|
int i;
|
s7state *s = state->priv;
|
s7state *s = state->priv;
|
|
|
for(i = 0; i < SAVER7_PLANETS; i++) {
|
for(i = 0; i < SAVER7_PLANETS; i++) {
|
saver7_moveplanet(state, s, i);
|
saver7_moveplanet(state, s, i);
|
saver7_drawplanet(state, s, i, 1);
|
saver7_drawplanet(state, s, i, 1);
|
saver7_calc_planet_position(state, s, i);
|
saver7_calc_planet_position(state, s, i);
|
saver7_drawplanet(state, s, i, 0);
|
saver7_drawplanet(state, s, i, 0);
|
}
|
}
|
saver7_drawstar(state, s);
|
saver7_drawstar(state, s);
|
}
|
}
|
|
|
/* The algorithm used in saver8 is based on that found at:
|
/* The algorithm used in saver8 is based on that found at:
|
http://www.go2net.com/internet/deep/1997/04/16/body.html */
|
http://www.go2net.com/internet/deep/1997/04/16/body.html */
|
|
|
void saver8_init(nstate *state)
|
void saver8_init(nstate *state)
|
{
|
{
|
int red = 0, green = 0, blue = 0, step, i = 0;
|
int red = 0, green = 0, blue = 0, step, i = 0;
|
|
|
s8state *s = my_malloc(sizeof(s8state));
|
s8state *s = my_malloc(sizeof(s8state));
|
state->priv = s;
|
state->priv = s;
|
|
|
s->current_line = 0;
|
s->current_line = 0;
|
|
|
step = 512 / SAVER8_NUMCOLOURS;
|
step = 512 / SAVER8_NUMCOLOURS;
|
|
|
for(green = 255; green > 0; green -= step, blue += step, i++)
|
for(green = 255; green > 0; green -= step, blue += step, i++)
|
s->colours[i] = GR_RGB(0, green, blue);
|
s->colours[i] = GR_RGB(0, green, blue);
|
for(blue = 255; blue > 0; blue -= step, red += step, i++)
|
for(blue = 255; blue > 0; blue -= step, red += step, i++)
|
s->colours[i] = GR_RGB(red, 0, blue);
|
s->colours[i] = GR_RGB(red, 0, blue);
|
|
|
state->animate_interval = SAVER8_DELAY;
|
state->animate_interval = SAVER8_DELAY;
|
}
|
}
|
|
|
void saver8_drawpattern(nstate *state)
|
void saver8_drawpattern(nstate *state)
|
{
|
{
|
int x, col, lines = SAVER8_LINES_PER_FRAME;
|
int x, col, lines = SAVER8_LINES_PER_FRAME;
|
s8state *s = state->priv;
|
s8state *s = state->priv;
|
|
|
if(!s->current_line)
|
if(!s->current_line)
|
s->factor = RANDRANGE(SAVER8_MINFACTOR, SAVER8_MAXFACTOR);
|
s->factor = RANDRANGE(SAVER8_MINFACTOR, SAVER8_MAXFACTOR);
|
|
|
while(s->current_line < state->si.rows) {
|
while(s->current_line < state->si.rows) {
|
if(!--lines) return;
|
if(!--lines) return;
|
for(x = 0; x < state->si.cols; x++) {
|
for(x = 0; x < state->si.cols; x++) {
|
col = ((((x * x) + (s->current_line * s->current_line))
|
col = ((((x * x) + (s->current_line * s->current_line))
|
/ s->factor) % SAVER8_NUMCOLOURS);
|
/ s->factor) % SAVER8_NUMCOLOURS);
|
GrSetGCForeground(state->main_gc, s->colours[col]);
|
GrSetGCForeground(state->main_gc, s->colours[col]);
|
GrPoint(state->main_window, state->main_gc, x,
|
GrPoint(state->main_window, state->main_gc, x,
|
s->current_line);
|
s->current_line);
|
}
|
}
|
s->current_line++;
|
s->current_line++;
|
}
|
}
|
s->current_line = 0;
|
s->current_line = 0;
|
}
|
}
|
|
|
void saver8_exposure(nstate *state)
|
void saver8_exposure(nstate *state)
|
{
|
{
|
s8state *s = state->priv;
|
s8state *s = state->priv;
|
|
|
GrClearWindow(state->main_window, 0);
|
GrClearWindow(state->main_window, 0);
|
s->current_line = 0;
|
s->current_line = 0;
|
saver8_drawpattern(state);
|
saver8_drawpattern(state);
|
}
|
}
|
|
|
void saver8_animate(nstate *state)
|
void saver8_animate(nstate *state)
|
{
|
{
|
saver8_drawpattern(state);
|
saver8_drawpattern(state);
|
}
|
}
|
|
|
int init(nstate *state)
|
int init(nstate *state)
|
{
|
{
|
GR_WM_PROPERTIES props;
|
GR_WM_PROPERTIES props;
|
GR_BITMAP cursor = 0;
|
GR_BITMAP cursor = 0;
|
|
|
if(!GrOpen()) {
|
if(!GrOpen()) {
|
fprintf(stderr, "Couldn't connect to Nano-X server\n");
|
fprintf(stderr, "Couldn't connect to Nano-X server\n");
|
return 3;
|
return 3;
|
}
|
}
|
|
|
GrGetScreenInfo(&state->si);
|
GrGetScreenInfo(&state->si);
|
|
|
state->main_window = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0,
|
state->main_window = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0,
|
state->si.cols, state->si.rows, 0, BLACK, 0);
|
state->si.cols, state->si.rows, 0, BLACK, 0);
|
|
|
GrSelectEvents(state->main_window, GR_EVENT_MASK_EXPOSURE |
|
GrSelectEvents(state->main_window, GR_EVENT_MASK_EXPOSURE |
|
GR_EVENT_MASK_BUTTON_UP |
|
GR_EVENT_MASK_BUTTON_UP |
|
GR_EVENT_MASK_BUTTON_DOWN |
|
GR_EVENT_MASK_BUTTON_DOWN |
|
GR_EVENT_MASK_MOUSE_MOTION |
|
GR_EVENT_MASK_MOUSE_MOTION |
|
GR_EVENT_MASK_KEY_UP |
|
GR_EVENT_MASK_KEY_UP |
|
GR_EVENT_MASK_KEY_DOWN |
|
GR_EVENT_MASK_KEY_DOWN |
|
GR_EVENT_MASK_FOCUS_OUT |
|
GR_EVENT_MASK_FOCUS_OUT |
|
GR_EVENT_MASK_CLOSE_REQ);
|
GR_EVENT_MASK_CLOSE_REQ);
|
|
|
props.flags = GR_WM_FLAGS_PROPS;
|
props.flags = GR_WM_FLAGS_PROPS;
|
props.props = GR_WM_PROPS_NOMOVE | GR_WM_PROPS_NODECORATE |
|
props.props = GR_WM_PROPS_NOMOVE | GR_WM_PROPS_NODECORATE |
|
GR_WM_PROPS_NOAUTOMOVE | GR_WM_PROPS_NOAUTORESIZE;
|
GR_WM_PROPS_NOAUTOMOVE | GR_WM_PROPS_NOAUTORESIZE;
|
GrSetWMProperties(state->main_window, &props);
|
GrSetWMProperties(state->main_window, &props);
|
|
|
state->main_gc = GrNewGC();
|
state->main_gc = GrNewGC();
|
GrSetGCForeground(state->main_gc, WHITE);
|
GrSetGCForeground(state->main_gc, WHITE);
|
GrSetGCBackground(state->main_gc, BLACK);
|
GrSetGCBackground(state->main_gc, BLACK);
|
|
|
state->animate_interval = 0;
|
state->animate_interval = 0;
|
|
|
srand(time(0));
|
srand(time(0));
|
|
|
init_functions[state->saver](state);
|
init_functions[state->saver](state);
|
|
|
calculate_timeout(state);
|
calculate_timeout(state);
|
|
|
GrSelectEvents(GR_ROOT_WINDOW_ID, GR_EVENT_MASK_SCREENSAVER);
|
GrSelectEvents(GR_ROOT_WINDOW_ID, GR_EVENT_MASK_SCREENSAVER);
|
|
|
GrSetCursor(state->main_window, 1, 1, 1, 1, 0, 0, &cursor, &cursor);
|
GrSetCursor(state->main_window, 1, 1, 1, 1, 0, 0, &cursor, &cursor);
|
|
|
GrMapWindow(state->main_window);
|
GrMapWindow(state->main_window);
|
|
|
GrSetFocus(state->main_window);
|
GrSetFocus(state->main_window);
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
void calculate_timeout(nstate *state)
|
void calculate_timeout(nstate *state)
|
{
|
{
|
struct timeval t;
|
struct timeval t;
|
long u;
|
long u;
|
|
|
gettimeofday(&t, NULL);
|
gettimeofday(&t, NULL);
|
u = t.tv_usec + (state->animate_interval * 1000);
|
u = t.tv_usec + (state->animate_interval * 1000);
|
state->timeout.tv_sec = t.tv_sec + (u / 1000000);
|
state->timeout.tv_sec = t.tv_sec + (u / 1000000);
|
state->timeout.tv_usec = u % 1000000;
|
state->timeout.tv_usec = u % 1000000;
|
}
|
}
|
|
|
unsigned long timeout_delay(nstate *state)
|
unsigned long timeout_delay(nstate *state)
|
{
|
{
|
struct timeval t;
|
struct timeval t;
|
signed long s, m, ret;
|
signed long s, m, ret;
|
|
|
gettimeofday(&t, NULL);
|
gettimeofday(&t, NULL);
|
|
|
if(!state->animate_interval) return 0;
|
if(!state->animate_interval) return 0;
|
|
|
if((t.tv_sec > state->timeout.tv_sec) ||
|
if((t.tv_sec > state->timeout.tv_sec) ||
|
((t.tv_sec == state->timeout.tv_sec) &&
|
((t.tv_sec == state->timeout.tv_sec) &&
|
t.tv_usec >= state->timeout.tv_usec)) return 1;
|
t.tv_usec >= state->timeout.tv_usec)) return 1;
|
|
|
s = state->timeout.tv_sec - t.tv_sec;
|
s = state->timeout.tv_sec - t.tv_sec;
|
m = ((state->timeout.tv_usec - t.tv_usec) / 1000);
|
m = ((state->timeout.tv_usec - t.tv_usec) / 1000);
|
ret = (unsigned long)((1000 * s) + m);
|
ret = (unsigned long)((1000 * s) + m);
|
|
|
if(ret <= 0) return 1;
|
if(ret <= 0) return 1;
|
else return ret;
|
else return ret;
|
}
|
}
|
|
|
void do_animate(nstate *state)
|
void do_animate(nstate *state)
|
{
|
{
|
struct timeval t;
|
struct timeval t;
|
|
|
if(!state->animate_interval) return;
|
if(!state->animate_interval) return;
|
|
|
gettimeofday(&t, NULL);
|
gettimeofday(&t, NULL);
|
|
|
if((t.tv_sec > state->timeout.tv_sec) ||
|
if((t.tv_sec > state->timeout.tv_sec) ||
|
((t.tv_sec == state->timeout.tv_sec) &&
|
((t.tv_sec == state->timeout.tv_sec) &&
|
(t.tv_usec >= state->timeout.tv_usec))) {
|
(t.tv_usec >= state->timeout.tv_usec))) {
|
animate_functions[state->saver](state);
|
animate_functions[state->saver](state);
|
calculate_timeout(state);
|
calculate_timeout(state);
|
}
|
}
|
}
|
}
|
|
|
int do_screensaver_event(nstate *state)
|
int do_screensaver_event(nstate *state)
|
{
|
{
|
GR_EVENT_SCREENSAVER *event = &state->event.screensaver;
|
GR_EVENT_SCREENSAVER *event = &state->event.screensaver;
|
|
|
if(event->activate != GR_FALSE) {
|
if(event->activate != GR_FALSE) {
|
fprintf(stderr, "Got a non-deactivate screensaver event\n");
|
fprintf(stderr, "Got a non-deactivate screensaver event\n");
|
return 0;
|
return 0;
|
}
|
}
|
|
|
return 1;
|
return 1;
|
}
|
}
|
|
|
int handle_event(nstate *state)
|
int handle_event(nstate *state)
|
{
|
{
|
switch(state->event.type) {
|
switch(state->event.type) {
|
case GR_EVENT_TYPE_EXPOSURE:
|
case GR_EVENT_TYPE_EXPOSURE:
|
exposure_functions[state->saver](state);
|
exposure_functions[state->saver](state);
|
case GR_EVENT_TYPE_TIMEOUT:
|
case GR_EVENT_TYPE_TIMEOUT:
|
case GR_EVENT_TYPE_NONE:
|
case GR_EVENT_TYPE_NONE:
|
break;
|
break;
|
case GR_EVENT_TYPE_SCREENSAVER:
|
case GR_EVENT_TYPE_SCREENSAVER:
|
if(do_screensaver_event(state)) return 0;
|
if(do_screensaver_event(state)) return 0;
|
break;
|
break;
|
case GR_EVENT_TYPE_CLOSE_REQ:
|
case GR_EVENT_TYPE_CLOSE_REQ:
|
case GR_EVENT_MASK_BUTTON_UP:
|
case GR_EVENT_MASK_BUTTON_UP:
|
case GR_EVENT_MASK_BUTTON_DOWN:
|
case GR_EVENT_MASK_BUTTON_DOWN:
|
case GR_EVENT_MASK_MOUSE_MOTION:
|
case GR_EVENT_MASK_MOUSE_MOTION:
|
case GR_EVENT_MASK_KEY_UP:
|
case GR_EVENT_MASK_KEY_UP:
|
case GR_EVENT_MASK_KEY_DOWN:
|
case GR_EVENT_MASK_KEY_DOWN:
|
case GR_EVENT_MASK_FOCUS_OUT:
|
case GR_EVENT_MASK_FOCUS_OUT:
|
return 0;
|
return 0;
|
default:
|
default:
|
fprintf(stderr, "Got unknown event type %d\n",
|
fprintf(stderr, "Got unknown event type %d\n",
|
state->event.type);
|
state->event.type);
|
break;
|
break;
|
}
|
}
|
do_animate(state);
|
do_animate(state);
|
return(1);
|
return(1);
|
}
|
}
|
|
|
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
{
|
{
|
int ret;
|
int ret;
|
nstate *state = my_malloc(sizeof(nstate));
|
nstate *state = my_malloc(sizeof(nstate));
|
|
|
if(argc == 2) {
|
if(argc == 2) {
|
state->saver = atoi(argv[1]) - 1;
|
state->saver = atoi(argv[1]) - 1;
|
if((state->saver) < 0 || (state->saver >= NUM_SAVERS)) {
|
if((state->saver) < 0 || (state->saver >= NUM_SAVERS)) {
|
fprintf(stderr, "Invalid saver number \"%s\"\n",
|
fprintf(stderr, "Invalid saver number \"%s\"\n",
|
argv[1]);
|
argv[1]);
|
return 2;
|
return 2;
|
}
|
}
|
} else state->saver = 0;
|
} else state->saver = 0;
|
|
|
if((ret = init(state))) return ret;
|
if((ret = init(state))) return ret;
|
|
|
do {
|
do {
|
GrGetNextEventTimeout(&state->event, timeout_delay(state));
|
GrGetNextEventTimeout(&state->event, timeout_delay(state));
|
} while(handle_event(state));
|
} while(handle_event(state));
|
|
|
GrClose();
|
GrClose();
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|