home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume2
/
spaceout
/
spaceout.c
< prev
Wrap
C/C++ Source or Header
|
1991-08-07
|
18KB
|
887 lines
/*
*
* SpaceOut for X11.
* Version 1.1
*
* By John Pochmara (jpochma@polyslo)
* at Cal Poly
* 1988
*
* Random number generator writen by Pual Shupak.
*
* Copyright (c) 1988, John H. Pochmara
*
* You may copy Spaceout in whole or in part as long as you don't
* try to make money off it, or pretend that you wrote it.
*
*
* Original SpaceOut writen in Mesa for Xerox workstations by
* Jef Poskanzer at Versatec, a Xerox Company.
*
*
* Options:
* R - run in root window.
* r - reverse screen.
* f - full screen.
* c - all stars go right down the center of the screen.
* C - Color Space.
*
*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#define STIPPLE_DRAW
#define NUM_STARS (70) /* Number of Stars */
#define STAR_MAXSIZE (400) /* Max size of Stars */
#define SPEEDZ (270) /* Speed at which Stars move forward */
#define MIN_VISIBLEZ (400) /* Closets you can get to a star */
#define MAX_VISIBLEZ (65000) /* Farthest away star you can see */
#define MINX (-20000) /* Min value of X cordanit */
#define MAXX (20000) /* Max value of X cordanit */
#define MINY (-20000) /* Min value of Y cordanit */
#define MAXY (20000) /* Max value of Y cordanit */
#define MINZ (30000) /* Min value of Z cordanit */
#define MAXZ (65535) /* Max value of Z cordanit */
#define SCREENZ (1500) /* Distance of projected image */
#define RADIUS (40) /* Size of a Star at SCREENZ */
#define MAG_RAD (1) /* Magnification factor of Star Radius */
#define TRUE (1)
#define FALSE (0)
#define RNDRANGE( min, max ) \
( ( ( (max) - (min) ) ? ( randomLong() % ( (max) - (min) ) ) : 0 ) + (min) )
#define OBSCURED (1)
#define UNOBSCURED (0)
/*
* Star Types.
*/
#define ROUND (0)
#define RINGED (1)
#define PLANETX (2)
/*
* Init. Window Postion & Dimension.
*/
#define INT_WIDTH (400)
#define INT_HEIGHT (250)
#define INT_X (50)
#define INT_Y (50)
#define WHITE (0)
#define COLOR1 (1)
#define COLOR2 (2)
#define COLOR3 (3)
#define COLOR4 (4)
#define COLOR5 (5)
#define COLOR6 (6)
char *color1[] = {
"pink",
"plum",
"red",
"IndianRed",
"MediumVioletRed",
"OrangeRed",
"VioletRed",
""
};
char *color2[] = {
"Green",
"DarkGreen",
"DarkOliveGreen",
"ForestGreen",
"LimeGreen",
"MediumForestGreen",
"MediumSeaGreen",
"MediumSpringGreen",
"PaleGreen",
"SeaGreen",
"SpringGreen",
"YellowGreen",
""
};
char *color3[] = {
"Blue",
"CadetBlue",
"CornflowerBlue",
"DarkSlateBlue",
"LightBlue",
"LightSteelBlue",
"MediumBlue",
"MediumSlateBlue",
"MidnightBlue",
"NavyBlue",
"Navy",
"SkyBlue",
"SlateBlue",
"SteelBlue",
""
};
char *color4[] = {
"Yellow",
"GreenYellow",
"Wheat",
"Turquoise",
"Sienna",
""
};
char *color5[] = {
"orange",
"Khaki",
"Maroon",
"Orchid",
""
};
char *color6[] = {
"violet",
"BlueViolet",
"Salmon",
"Gold",
"Goldenrod",
"Coral",
""
};
#define MAX_USED_COLORS ( 7 )
XColor starColors[MAX_USED_COLORS];
typedef struct starrec {
int sx,sy;
int x,y,z;
int radius;
int displayed;
int type;
int color;
} StarRec;
StarRec Stars[NUM_STARS];
Pixmap Starpix[STAR_MAXSIZE];
Pixmap Ringpix[STAR_MAXSIZE];
Pixmap Xpix[STAR_MAXSIZE];
Display *dpy;
Window SpaceWin;
Window root;
Window parent;
Colormap cmap;
int screen;
int depth;
int SpaceVis;
/*
* Option Var.
*
*/
int rootwin = FALSE;
int fullscreen = FALSE;
int reverse = FALSE;
int color = FALSE;
int center = FALSE;
char *host = NULL;
int winwidth;
int winheight;
int winx;
int winy;
static void init(), initwin(), initpos(), initpix(), initstar();
static void initcolors(), setcolor();
static void MoveStars(), DisplayStar(), NewStar(), ShowStar();
static void DrawStar(), Newpixmap(), ProcEvent(), ReDrawStars();
static void ReStart(), ClearStars(), usage(), prev();
static unsigned long int randomLong();
main(argc,argv)
int argc;
char *argv[];
{
while(--argc > 0) {
if(index(argv[argc],':') != 0) {
if(host != NULL)
usage();
else
host = argv[argc];
} else if(argv[argc][0] == '-') {
int i = 1;
while(argv[argc][i] != NULL) {
switch(argv[argc][i]) {
case 'f': fullscreen = TRUE;
break;
case 'r': reverse = TRUE;
break;
case 'c': center = TRUE;
break;
case 'C': color = TRUE;
break;
case 'R': rootwin = TRUE;
break;
default: usage();
}
i++;
}
}
}
if(host == NULL) {
if((host = (char *) getenv("DISPLAY")) == NULL) {
usage();
}
}
init(host);
MoveStars(Stars);
}
static void init(host)
char *host;
{
initwin(host);
srandom((int) time(0));
initstar();
initpix();
SpaceVis = UNOBSCURED;
}
static void MoveStars(stars)
StarRec stars[];
{
int i;
while(TRUE) {
ProcEvent();
for(i=0;i<NUM_STARS;i++) {
if(stars[i].z > SPEEDZ) {
stars[i].z = stars[i].z - SPEEDZ;
} else {
stars[i].z = MIN_VISIBLEZ/2;
}
DisplayStar(&stars[i]);
}
XFlush(dpy);
}
}
static void DisplayStar(star)
StarRec *star;
{
int scrx;
int scry;
int scrradius;
if(star->z <= 0 ) star->z = 1;
scrx = (star->x * SCREENZ) / star->z;
scry = (star->y * SCREENZ) / star->z;
scrradius = (RADIUS * SCREENZ) / star->z;
scrx = (winwidth/2 + scrx);
scry = (winheight/2 + scry);
if((scrx == star->sx)
&& (scry == star->sy)
&& ( scrradius == star->radius ))
return;
if(star->z < MIN_VISIBLEZ) {
if(star->displayed == TRUE) {
ShowStar(star);
star->displayed = FALSE;
}
NewStar(star);
return;
}
if(star->z > MAX_VISIBLEZ) {
if(star->displayed == TRUE) {
ShowStar(star);
star->displayed = FALSE;
}
return;
}
if(star->displayed == TRUE) {
ShowStar(star);
star->displayed = FALSE;
}
if((scrx > winwidth) || (scrx < -(2 * star->radius)) ||
(scry > winheight) || (scry < -(2 * star->radius))) {
NewStar(star);
return;
}
star->sx = scrx;
star->sy = scry;
star->radius = scrradius;
ShowStar(star);
star->displayed = TRUE;
}
static void NewStar(star)
StarRec *star;
{
int rnd = RNDRANGE(0,100);
int x_range, y_range;
star->z = RNDRANGE(MINZ,MAXZ);
if(center != TRUE) {
x_range = (star->z * winwidth) / ( 2 * SCREENZ);
y_range = (star->z * winheight) / (2 * SCREENZ);
star->x = RNDRANGE(-(x_range),x_range);
star->y = RNDRANGE(-(y_range),y_range);
} else {
star->x = 0;
star->y = 0;
}
star->sx = (star->x * SCREENZ) / star->z;
star->sy = (star->y * SCREENZ) / star->z;
star->radius = (RADIUS * SCREENZ) / star->z;
star->displayed = FALSE;
star->color = WHITE;
if(rnd < 3)
star->type = PLANETX;
else if(rnd < 10)
star->type = RINGED;
else {
star->type = ROUND;
star->color = RNDRANGE(0, MAX_USED_COLORS - 1);
}
}
static void ShowStar(star)
StarRec *star;
{
if(star->radius <= 0)
star->radius = 1;
if(star->radius > STAR_MAXSIZE)
star->radius = STAR_MAXSIZE;
switch(star->type) {
case RINGED:
if(Ringpix[star->radius] == 0) Newpixmap(star);
break;
case ROUND:
if(Starpix[star->radius] == 0) Newpixmap(star);
break;
case PLANETX:
if(Xpix[star->radius] == 0) Newpixmap(star);
break;
}
DrawStar(star);
}
static void DrawStar(star)
StarRec *star;
{
static GC gc[MAX_USED_COLORS] = { 0 };
int p_width = 2 * ((star->radius) * MAG_RAD);
int p_height = 2 * ((star->radius) * MAG_RAD);
Pixmap drawpix;
GC stargc;
int sx,sy;
int i;
if(gc[0] == 0) {
for(i = 0; i < MAX_USED_COLORS; i++) {
gc[i] = XCreateGC(dpy,SpaceWin,0,NULL);
XSetFunction(dpy,gc[i],GXxor);
XSetBackground(dpy,gc[i],BlackPixel(dpy,screen));
if( color == TRUE )
XSetForeground(dpy,gc[i],starColors[i].pixel);
else
XSetForeground(dpy,gc[i],WhitePixel(dpy,screen));
#ifdef STIPPLE_DRAW
XSetFillStyle(dpy,gc[i],FillStippled);
#else
XSetGraphicsExposures(dpy,gc[i],FALSE);
#endif STIPPLE_DRAW
}
}
stargc = gc[star->color];
switch(star->type) {
case ROUND:
drawpix = Starpix[star->radius];
break;
case RINGED:
drawpix = Ringpix[star->radius];
p_width *= 2;
break;
case PLANETX:
drawpix = Xpix[star->radius];
break;
default:
drawpix = Starpix[star->radius];
break;
}
sx = star->sx - p_width/2;
sy = star->sy - p_height/2;
#ifdef STIPPLE_DRAW
XSetStipple(dpy,stargc,drawpix);
XSetTSOrigin(dpy,stargc,sx,sy);
XFillRectangle(dpy,SpaceWin,stargc,sx,sy,p_width,p_height);
#else
XCopyArea(dpy,drawpix,SpaceWin,stargc,0,0,p_width,p_height,sx,sy);
#endif STIPPLE_DRAW
}
static void Newpixmap(star)
StarRec *star;
{
static GC gc = 0;
Pixmap pixtmp;
int i;
int p_width = 2 * ((star->radius) * MAG_RAD);
int p_height = 2 * ((star->radius) * MAG_RAD);
int r = star->radius;
if(star->type == RINGED) {
p_width = 2 * p_width;
}
#ifdef STIPPLE_DRAW
pixtmp = XCreatePixmap(dpy,SpaceWin,p_width,p_height,1);
#else
pixtmp = XCreatePixmap(dpy,SpaceWin,p_width,p_height,depth);
#endif STIPPLE_DRAW
if(gc == 0) {
gc = XCreateGC(dpy,pixtmp,0,NULL);
XSetBackground(dpy,gc,BlackPixel(dpy,screen));
XSetForeground(dpy,gc,WhitePixel(dpy,screen));
XSetFillStyle(dpy,gc,FillSolid);
}
switch(star->type) {
case ROUND:
XSetFunction(dpy,gc,GXxor);
XFillArc(dpy,pixtmp,gc,0,0,p_width,p_height,0,360*64);
Starpix[star->radius] = pixtmp;
break;
case RINGED:
XSetFunction(dpy,gc,GXxor);
XSetLineAttributes(dpy,gc,1,LineSolid,CapRound,JoinBevel);
XFillArc(dpy,pixtmp,gc,r,0,p_height,p_height,0,360*64);
XDrawArc(dpy,pixtmp,gc,0,r/2,p_width,p_height/2,
0,360*64);
Ringpix[star->radius] = pixtmp;
break;
case PLANETX:
XSetFunction(dpy,gc,GXxor);
XFillArc(dpy,pixtmp,gc,0,0,p_width,p_height,0,360*64);
i = r/4;
if(i < 1) i = 1;
XSetLineAttributes(dpy,gc,i,LineSolid,CapRound,JoinBevel);
XSetFunction(dpy,gc,GXclear);
XDrawLine(dpy,pixtmp,gc,r/2,r/2,r+r/2,r+r/2);
XDrawLine(dpy,pixtmp,gc,r+r/2,r/2,r/2,r+r/2);
Xpix[star->radius] = pixtmp;
break;
}
}
static void initstar()
{
int i;
for(i=0;i<NUM_STARS;i++) {
NewStar(&Stars[i]);
}
}
static void initpix()
{
int i;
for(i=0;i<STAR_MAXSIZE;i++) {
Starpix[i] = 0;
Ringpix[i] = 0;
Xpix[i] = 0;
}
}
static void initpos()
{
if(fullscreen == TRUE) {
winwidth = XDisplayWidth(dpy,screen);
winheight = XDisplayHeight(dpy,screen);
winx = 0;
winy = 0;
} else {
winwidth = INT_WIDTH;
winheight = INT_HEIGHT;
winx = INT_X;
winy = INT_Y;
}
}
extern int XCheckTypedEvent();
static void ProcEvent()
{
XEvent ev;
int block = FALSE;
while((XPending(dpy) > 0) || (block == TRUE)) {
XNextEvent(dpy,&ev);
switch(ev.type) {
case ReparentNotify:
if(ev.xreparent.window != SpaceWin ) break;
XSelectInput(dpy,ev.xreparent.parent,
StructureNotifyMask);
XSelectInput(dpy,parent,0);
parent = ev.xreparent.parent;
break;
case UnmapNotify:
if((ev.xunmap.window != SpaceWin) &&
(ev.xunmap.window != parent)) break;
block = TRUE;
break;
case VisibilityNotify:
if(ev.xvisibility.window != SpaceWin) break;
if(ev.xvisibility.state ==
VisibilityFullyObscured) {
block = TRUE;
break;
}
if((ev.xvisibility.state ==
VisibilityUnobscured) &&
(SpaceVis == OBSCURED)) {
ReStart();
SpaceVis = UNOBSCURED;
block = FALSE;
break;
}
if(ev.xvisibility.state ==
VisibilityPartiallyObscured) {
SpaceVis = OBSCURED;
block = FALSE;
}
break;
case Expose:
ReStart();
block = FALSE;
break;
case MapNotify:
if((ev.xmap.window != SpaceWin) &&
(ev.xmap.window != parent)) break;
ReStart();
block = FALSE;
break;
case ConfigureNotify:
if(ev.xconfigure.window != SpaceWin) break;
ReStart();
if((winwidth == ev.xconfigure.width) &&
(winheight == ev.xconfigure.height))
break;
winwidth = ev.xconfigure.width;
winheight = ev.xconfigure.height;
ReDrawStars();
block = FALSE;
break;
default:
break;
}
}
}
static void ReDrawStars()
{
int i;
for(i=0;i<NUM_STARS;i++) {
DisplayStar(&Stars[i]);
}
}
static void ReStart()
{
XClearWindow(dpy,SpaceWin);
XSync(dpy, 0);
ClearStars();
}
static void ClearStars()
{
int i;
for(i=0;i<NUM_STARS;i++) {
Stars[i].displayed = FALSE;
}
}
static void initcolors()
{
unsigned long backgrd;
if( reverse == TRUE )
backgrd = WhitePixel(dpy,screen);
else
backgrd = BlackPixel(dpy,screen);
starColors[WHITE].pixel = WhitePixel(dpy,screen);
setcolor(color1,&starColors[COLOR1]);
starColors[COLOR1].pixel ^= backgrd;
setcolor(color2,&starColors[COLOR2]);
starColors[COLOR2].pixel ^= backgrd;
setcolor(color3,&starColors[COLOR3]);
starColors[COLOR3].pixel ^= backgrd;
setcolor(color4,&starColors[COLOR4]);
starColors[COLOR4].pixel ^= backgrd;
setcolor(color5,&starColors[COLOR5]);
starColors[COLOR5].pixel ^= backgrd;
setcolor(color6,&starColors[COLOR6]);
starColors[COLOR6].pixel ^= backgrd;
}
static void setcolor(cnames,xcolor)
char *cnames[];
XColor *xcolor;
{
int i = 0;
int count = 0;
XColor ecolor;
while( *cnames[count] != NULL ) {
count++;
}
i = RNDRANGE(0,count-1);
if( XAllocNamedColor(dpy,cmap,cnames[i],xcolor,&ecolor) > 0)
return;
else {
i = 0;
while( *cnames[i] != NULL ) {
if( XAllocNamedColor(dpy,cmap,cnames[i],
xcolor,&ecolor) > 0)
return;
else
continue;
}
}
xcolor->pixel = starColors[WHITE].pixel;
}
static void initwin(hostmon)
char *hostmon;
{
XSetWindowAttributes attr;
char *name;
if((dpy = XOpenDisplay(hostmon)) == NULL) {
fprintf(stderr,"Connection not made.\n");
exit(1);
}
screen = DefaultScreen(dpy);
cmap = DefaultColormap(dpy,screen);
parent = root = RootWindow(dpy,screen);
depth = DefaultDepth(dpy,screen);
if( color == TRUE )
initcolors();
initpos();
XSelectInput(dpy,root,SubstructureNotifyMask);
attr.event_mask = StructureNotifyMask
| SubstructureNotifyMask
| VisibilityChangeMask
| ExposureMask;
if(reverse == TRUE)
attr.background_pixel = WhitePixel(dpy,screen);
else
attr.background_pixel = BlackPixel(dpy,screen);
if(rootwin == TRUE) {
SpaceWin = root;
XChangeWindowAttributes(dpy,SpaceWin,
CWEventMask|CWBackPixel,&attr);
} else {
SpaceWin = XCreateWindow(dpy,root,winx,winy,winwidth,winheight,
0,depth,InputOutput,
DefaultVisual(dpy,screen),
CWEventMask|CWBackPixel,&attr);
if( color == TRUE )
name = "Color SpaceOut";
else
name = "SpaceOut";
XChangeProperty(dpy,SpaceWin,XA_WM_NAME,XA_STRING,8,
PropModeReplace,name,strlen(name));
XMapWindow(dpy,SpaceWin);
}
XClearWindow(dpy,SpaceWin);
XSync(dpy, 0);
}
static void usage()
{
fprintf(stderr,"usage: space [host:screen] [-frCc]\n");
exit(0);
}
static int randomBit()
{
register unsigned long int tmp ;
static unsigned long int state = 0x10 ;
/* Linear Feedback Shift Register
* Length = 31 Bits
* Taps at 3 & 31
* Period = ( 2 ** 31 ) - 1
*/
tmp = state ;
/* Next State */
state = ( ( ( tmp << 2 ) ^ ( tmp << 30 ) ) & 0x80000000 ) | ( tmp >> 1 ) ;
return tmp >> 31 ;
}
/* Random Number Generator State Variables */
static unsigned long int lastRandom = 1 ;
static unsigned long int oldRandom ;
static unsigned long int randomLong()
{
register unsigned long int tmpA ;
register unsigned long int tmpB ;
register unsigned long int tmpH ;
register unsigned long int tmpM1 ;
register unsigned long int tmpM2 ;
register unsigned long int tmpL ;
register long int SumOldL ;
register long int SumOldH ;
register long int SumLastL ;
register long int SumLastH ;
/*
* Modular Congruence Method
* Period >= ( 2 ** 31 ) - 1
* X(n) =
* ( 271,828,183 * X(n-1) - 314,159,269 * X(n-2) ) mod ( ( 2 ** 31 ) - 1 )
* = ( 0x1033C4D7 * X(n-1) - 0x12B9B0A5 * X(n-2) ) mod ( ( 2 ** 31 ) - 1 )
* To Avoid OverFlow USE:
* ( ( x1 * ( 2 ** 16 ) ) + x2 ) * ( ( y1 * ( 2 ** 15 ) ) + y2 ) =
* ( x1 * y1 * ( 2 ** 31 ) )
* + ( x2 * y1 * ( 2 ** 15 ) )
* + ( x1 * y2 * ( 2 ** 16 ) )
* + ( x2 * y2 )
* NOTE:
* 0x1033C4D7 == ( 0x2067 * 0x08000 ) + 0x44D7
* == ( 0x1033 * 0x10000 ) + 0xC4D7
* 0x12B9B0A5 == ( 0x2573 * 0x08000 ) + 0x30A5
* == ( 0x12B9 * 0x10000 ) + 0xB0A5
*/
tmpA = oldRandom ;
tmpB = tmpA & 0xFFFF ; /* Low Order 16 Bits of X(n-2) */
tmpM1 = tmpB * 0x2573 ; /* Offset 16 Bits */
tmpL = tmpB * 0x30A5 ; /* Offset 0 Bits */
tmpA >>= 16 ; /* High Order 15 Bits of X(n-2)
tmpH = tmpA * 0x2573 ; /* Offset 31 Bits */
tmpM2 = tmpA * 0x30A5 ; /* Offset 15 Bits */
/* Now Sum Them */
SumOldL = tmpL & 0x7FFF ;
tmpA = ( tmpL >> 15 ) + tmpM2 + ( tmpM1 << 1 ) ;
SumOldL |= ( ( tmpA << 15 ) & 0x7FFF8000 ) ; /* Bottom 31 Bits */
SumOldH = ( ( tmpA >> 16 ) + tmpH ) ; /* Top 31 Bits */
oldRandom = tmpA = lastRandom ;
tmpB = tmpA & 0xFFFF ; /* Low Order 16 Bits of X(n-1) */
tmpM1 = tmpB * 0x2067 ; /* Offset 15 bits */
tmpL = tmpB * 0x44D7 ; /* Offset 0 bits */
tmpA >>= 16 ; /* High Order 15 Bits of X(n-1)*/
tmpH = tmpA * 0x2067 ; /* Offset 31 bits */
tmpM2 = tmpA * 0x44D7 ; /* Offset 16 bits */
/* Now Sum Them */
SumLastL = tmpL & 0x7FFF ;
tmpA = ( tmpL >> 15 ) + tmpM2 + ( tmpM1 << 1 ) ;
SumLastL |= ( ( tmpA << 15 ) & 0x7FFF8000 ) ; /* Bottom 31 Bits */
SumLastH = ( ( tmpA >> 16 ) + tmpH ) ; /* Top 31 Bits */
tmpA = SumLastH - SumOldH ;
tmpB = SumLastL - SumOldL ;
if ( SumLastL < SumOldL ) {
tmpB &= 0x7FFFFFFF ;
tmpA-- ;
}
return lastRandom = ( ( tmpA + tmpB ) & 0x7FFFFFFF ) ;
}
static void prev(ev)
XEvent *ev;
{
printf("event->type: %d\n",ev->type);
}