home *** CD-ROM | disk | FTP | other *** search
- /*
- * Simple demo, animated (bouncing balls) background.
- *
- * Author: Bernard Hatt (bmh@terminus.ericsson.se)
- *
- * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
- *
- */
-
- #include <stdio.h>
- #include <signal.h>
- #include <ctype.h>
- #include <sys/time.h>
-
- #include <X11/X.h>
- #include <X11/Xlib.h>
- #include <X11/cursorfont.h>
-
- Display *Disp;
- int Scr;
- Window Root;
- GC GcF,GcB;
-
- #define NONE 0 /* not in a window */
- #define V 1 /* vertical */
- #define H 2 /* horizontal */
- #define B 3 /* ball */
-
- #define MOUSEH 24
- #define MOUSEW 24
-
- #define DEFRAD 16 /* default diameter */
- #define DEFNO 6
- #define SPEED 128
- #define SQLIMIT (SPEED*SPEED/(20*20)) /* square of lower speed limit */
-
- int dispx,dispy;
-
- typedef struct rectangle_struct
- {
- int x1,y1; /* x and y coords top left */
- int x2,y2; /* x and y coords bottom right */
- } RECTANGLE;
-
- int nor;
- RECTANGLE *rp=NULL;
-
- typedef struct ball_struct
- {
- int x,y; /* x and y coords */
- int dx,dy; /* x and y velocity */
- } BALL;
-
- int noballs=DEFNO;
- int radius=DEFRAD;
- BALL *bp;
- int coeff=85;
- int attop=100;
-
- int backflag=0;
- int invertflag=0;
- int trailflag=0;
- int mouseflag=1;
- int sizeflag=0;
- int momentumflag=0;
- int interact=0;
- int mx,my,mn,mdx,mdy;
- int failed=0;
- int currmax=0; /* current maximum number of windows */
-
- char *getenv();
-
- int lasttime;
-
-
- long lastsec=0;
- struct timezone tz={0,0};
- struct timeval tv;
- struct timeval tv2;
-
- int
- rnd(n)
- int n;
- {
- return((rand()/153)%n);
- }
-
-
- void /* because Ultrix doesn't provide the nice SunOS usleep() */
- myusleep(val)
- int val;
- {
- tv2.tv_sec=0;
- tv2.tv_usec=val;
-
- select(0,NULL,NULL,NULL,&tv2);
- }
-
- void
- dointr()
- {
- clearballs();
- exit(1);
- }
-
- void
- Xerr()
- {
- failed++;
- }
-
- void
- Xfatal()
- {
- exit(1);
- }
-
- void
- randomball(i)
- int i;
- {
- int x,y;
- int dum;
- int attempts;
- attempts=0;
- do
- {
- x=rnd(dispx);
- y=rnd(dispy);
- if(rnd(100)<attop)
- y=0;
- attempts++;
- if(attempts>2000)
- {
- clearballs();
- exit(1);
- }
- }
- while(inwin(x,y,0,0,&dum)!=NONE);
- bp[i].x=x;
- bp[i].y=y;
- bp[i].dx=rnd(SPEED)+(SPEED/2);
- bp[i].dy=rnd(SPEED)+(SPEED/2);
- switch(rnd(4))
- {
- case 0:
- break;
- case 1:
- bp[i].dx=(0-bp[i].dx);
- break;
- case 2:
- bp[i].dy=(0-bp[i].dy);
- break;
- case 3:
- bp[i].dx=(0-bp[i].dx);
- bp[i].dy=(0-bp[i].dy);
- break;
- }
- }
-
- #ifdef SYSV
- # include <sys/timeb.h>
- #endif /*SYSV*/
- int
- gettime()
- {
- #ifdef SYSV
- struct timeb tb;
-
- ftime(&tb);
- tv.tv_sec = tb.time;
- tv.tv_usec = tb.millitm * 1000;
- #else /*SYSV*/
- gettimeofday(&tv,&tz);
- #endif /*SYSV*/
- if(lastsec==0)
- lastsec=tv.tv_sec;
- return((tv.tv_sec-lastsec)*100+(tv.tv_usec/10000));
- }
-
- int
- inwin(x,y,dx,dy,n)
- int x,y,dx,dy;
- int *n;
- {
- int i,diffx,diffy;
- int coln;
- coln=(-1);
- if((x<0)||(x>dispx))
- return(V);
- if((y<0)||(y>dispy))
- return(H);
- for(i=0;i<nor;i++)
- {
- if((x<rp[i].x1)||(y<rp[i].y1)||(y>rp[i].y2)||(x>rp[i].x2))
- continue;
- coln=i;
- break;
- }
- if(coln==(-1))
- {
- if(!interact)
- return(NONE);
- for(i=0;i<noballs;i++)
- {
- if(i==(*n))
- break;
- diffx=(bp[i].x-x);
- diffy=(bp[i].y-y);
- if((diffx*diffx+diffy*diffy)<(radius*radius*4))
- {
- (*n)=i;
- return(B);
- }
- }
- return(NONE);
- }
- *n=coln;
- x-=dx;
- if((x<rp[i].x1)||(y<rp[i].y1)||(y>rp[i].y2)||(x>rp[i].x2))
- return(V);
- return(H);
- }
-
- clearballs()
- {
- int i;
- XClearWindow(Disp,Root);
- XFlush(Disp);
- }
-
- void
- doballs()
- {
- int i,n;
- int newtime,td;
- int dx,dy,x,y,nx,ny;
- int redo;
- int diffx,diffy;
- int dumint;
- Window dumwin;
-
- newtime=gettime();
- td=newtime-lasttime;
- if(td>20)
- td=20;
-
- if(mouseflag)
- {
- XQueryPointer(Disp,Root,&dumwin,&dumwin,&nx,&ny,&dumint,&dumint,&dumint);
- mdx=nx-mx;
- mx=nx;
- mdy=ny-my;
- my=ny;
- rp[mn].x1=mx-(MOUSEW/2);
- rp[mn].y1=my-(MOUSEH/2);
- rp[mn].x2=mx+(MOUSEW/2);
- rp[mn].y2=my+(MOUSEH/2);
- }
-
- for(i=0;i<noballs;i++)
- {
- if(backflag||trailflag)
- XFillArc(Disp,Root,GcB,bp[i].x-(radius/2),bp[i].y-(radius/2),radius,radius,0,360*64);
- else
- XClearArea(Disp,Root,bp[i].x-(radius/2),bp[i].y-(radius/2),radius,radius,0);
- redo=0;
- if((bp[i].dx*bp[i].dx+bp[i].dy*bp[i].dy)<SQLIMIT)
- redo=10;
- do
- {
- dx=(td*bp[i].dx)/100;
- dy=(td*bp[i].dy)/100;
- if(redo>5)
- {
- redo=0;
- randomball(i);
- }
-
-
- /* printf("coords are %d,%d [%d,%d]\n",bp[i].x,bp[i].y,bp[i].dx,bp[i].dy);*/
- n=i;
- switch(inwin(dx+bp[i].x,dy+bp[i].y,dx,dy,&n))
- {
- case NONE:
- bp[i].x+=dx;
- bp[i].y+=dy;
- redo=0;
- break;
- case V:
- if((n==mn)&momentumflag)
- {
- bp[i].dx=mdx;
- bp[i].dy=mdy;
- bp[i].x+=dx;
- bp[i].y+=dy;
- }
- else
- bp[i].dx=(coeff*bp[i].dx)/100;
-
- redo++;
- break;
- case H:
- if((n==mn)&momentumflag)
- {
- bp[i].dy=mdy;
- bp[i].dx=mdx;
- bp[i].x+=dx;
- bp[i].y+=dy;
- }
- else
- bp[i].dy=(coeff*bp[i].dy)/100;
-
- if(coeff!=100)
- {
- /* printf("[%d] y=%d dy=%d\n",i,bp[i].y,dy);*/
- if((bp[i].y>=(dispy-3))&&(dy<=5))
- redo=10;
- if((dx==0)&&(dy<=3))
- redo=10;
- }
-
- redo++;
- break;
- case B:
- diffx=bp[i].x-bp[n].x;
- diffy=bp[i].y-bp[n].y;
-
- break;
- }
- if(n==mn)
- redo=0;
- }
- while(redo);
- bp[i].dy+=td;
-
- XFillArc(Disp,Root,GcF,bp[i].x-(radius/2),bp[i].y-(radius/2),radius,radius,0,360*64);
- XFlush(Disp);
- }
- lasttime=newtime;
- }
-
-
- int
- getwins()
- {
- int i;
- Window dummy1,dummy2,*list;
- XWindowAttributes WAttrib;
- XEvent Event;
-
- unsigned int listsize;
-
- XQueryTree(Disp,Root,&dummy1,&dummy2,&list,&listsize);
-
- if((listsize+2)>currmax)
- {
- if(rp!=NULL)
- free(rp);
- currmax=listsize+20;
- /* printf("currmax=%d\n",currmax);*/
- rp=(RECTANGLE*)malloc(sizeof(RECTANGLE)*currmax);
- }
- else
- {
- while(XCheckWindowEvent(Disp,Root,SubstructureNotifyMask,&Event))
- {
- while(XCheckWindowEvent(Disp,Root,SubstructureNotifyMask,&Event));
- lasttime=gettime();
- myusleep(50*1000);
- }
- }
- if(rp==NULL)
- {
- fprintf(stderr,"Failed to malloc %d bytes\n",sizeof(RECTANGLE)*listsize*2);
- exit(1);
- }
-
- nor=0;
- for(i=0;i<listsize;i++)
- {
- failed=0;
- XGetWindowAttributes(Disp,list[i],&WAttrib);
- if((!failed)&&WAttrib.map_state==IsViewable)
- {
- rp[nor].x1=WAttrib.x;
- rp[nor].y1=WAttrib.y;
- rp[nor].x2=WAttrib.x+WAttrib.width;
- rp[nor].y2=WAttrib.y+WAttrib.height;
- /* printf("Window id 0x%x, x1=%d,y1=%d,x2=%d,y2=%d\n",list[nor],rp[nor].x1,rp[nor].y1,rp[nor].x2,rp[nor].y2);*/
- nor++;
- }
- }
- if(mouseflag)
- {
- mn=nor;
- nor++;
- }
- XFree(list);
- }
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- unsigned long bg,fg;
- char *dispname;
- int i,j;
- int x,y;
- char *p;
- XEvent Event;
-
- srand(time(0));
- dispname=getenv("DISPLAY");
- for(i=1;i<argc;i++)
- {
- p=argv[i];
- if(*p++=='-')
- {
- switch(*p++)
- {
- case 'd':
- if(*p=='\0')
- dispname=argv[++i];
- else
- dispname=p;
- break;
- case 'n':
- if(*p=='\0')
- noballs=atoi(argv[++i]);
- else
- noballs=atoi(p);
- break;
- case 'r':
- if(*p=='\0')
- radius=atoi(argv[++i]);
- else
- radius=atoi(p);
- break;
- case 'c':
- if(*p=='\0')
- coeff=atoi(argv[++i]);
- else
- coeff=atoi(p);
- break;
- case 't':
- if(*p=='\0')
- attop=atoi(argv[++i]);
- else
- attop=atoi(p);
- break;
- case 'b':
- backflag=(!backflag);
- break;
- case 'i':
- invertflag=(!invertflag);
- break;
- case 'm':
- mouseflag=(!mouseflag);
- break;
- case 'M':
- momentumflag=(!momentumflag);
- break;
- case 'I':
- interact=(!interact);
- break;
- case 'l':
- trailflag=(!trailflag);
- break;
- case 's':
- sizeflag=(!sizeflag);
- break;
- default:
- /* usage */
- break;
- }
- }
- }
- if(coeff>100)
- coeff=100;
- if(coeff<0)
- coeff=0;
- coeff=(0-coeff);
- bp=(BALL*)malloc(sizeof(BALL)*noballs);
- if(bp==NULL)
- {
- fprintf(stderr,"Failed to malloc %d bytes\n",sizeof(BALL)*noballs);
- exit(1);
- }
- Disp=XOpenDisplay(dispname);
-
- Root=XDefaultRootWindow(Disp);
- Scr=DefaultScreen(Disp);
-
- clearballs();
- if(noballs==0)
- exit(0);
-
-
- if(invertflag)
- {
- fg=BlackPixel(Disp,Scr);
- bg=WhitePixel(Disp,Scr);
- }
- else
- {
- bg=BlackPixel(Disp,Scr);
- fg=WhitePixel(Disp,Scr);
- }
-
- GcF=XCreateGC(Disp,Root,0,0);
- GcB=XCreateGC(Disp,Root,0,0);
- XSetForeground(Disp,GcF,fg);
- XSetForeground(Disp,GcB,bg);
-
- dispx=XDisplayWidth(Disp,Scr);
- dispy=XDisplayHeight(Disp,Scr);
-
- if(sizeflag)
- fprintf(stderr,"Screen size is %dX by %dY\n",dispx,dispy);
-
- if(backflag)
- {
- XSetWindowBackground(Disp,Root,bg);
- XClearWindow(Disp,Root);
- }
- XSelectInput(Disp,Root,SubstructureNotifyMask);
-
- /* printf("Width and Height are %d,%d\n",dispx,dispy);*/
- getwins();
- XFlush(Disp);
- for(i=0;i<noballs;i++)
- {
- randomball(i);
- }
- lasttime=gettime();
- signal(SIGINT,dointr);
- signal(SIGHUP,dointr);
- signal(SIGTERM,dointr);
- XSetErrorHandler(Xerr);
- XSetIOErrorHandler(Xfatal);
- while(1)
- {
- if(XCheckWindowEvent(Disp,Root,SubstructureNotifyMask,&Event))
- {
- getwins();
- }
- doballs();
- myusleep(50*1000);
- }
- }
-
-