/*
  Program Seven
  Bert Nelson
  Copyright 1992 Bert Nelson

  Purpose: 	display a simple animation 


  Compile Instructions:  cc file.c -lX11 -lm -o file

  Run Instructions:  type 'file' after compiling and click a button
		     on the mouse to start the animation.
	             Press 'q' to quit.


   Permission to use, copy, modify, and distribute this software and its
   documentation for any purpose and without fee is hereby granted,
   provided that the above copyright notice appear in all copies and that
   both that copyright notice and this permission notice appear in
   supporting documentation.  It is provided "as is" without any express or
   implied warranty.

   Bert Nelson DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
   Bert Nelson BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
   ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   SOFTWARE.

    
  */



#include <X11/Xlib.h>
#include <X11/Xutil.h>


/* set strings as global */

char hello[] = "Animation by Bert Nelson";
unsigned long white,black;

main(argc,argv)
int argc;
char **argv;
{
	Display *mydisplay;
	Window  mywindow;
	GC mygc;
	XEvent myevent;
	KeySym mykey;
	XSizeHints myhint;

	int myscreen;
	unsigned long myforeground, mybackground;
	int i;
	char text[10];
	int done;

	/* set up display and foreground/background */

	mydisplay = XOpenDisplay("");

	myscreen = DefaultScreen (mydisplay);
	white = mybackground = WhitePixel (mydisplay, myscreen);
	black = myforeground = BlackPixel (mydisplay, myscreen);

	/* create a window with a width of 1000 x 700 */

	myhint.x = 0;
	myhint.y = 0;
	myhint.width = 1000;
	myhint.height = 700;
	myhint.flags = PPosition | PSize;
	mywindow = XCreateSimpleWindow (mydisplay,
	    DefaultRootWindow (mydisplay),
	    myhint.x, myhint.y, myhint.width, myhint.height,
	    5, myforeground, mybackground);



	XSetStandardProperties (mydisplay, mywindow, hello, hello,
	    None, argv, argc, &myhint);

	mygc = XCreateGC (mydisplay, mywindow, 0, 0);

	XSetBackground (mydisplay, mygc, mybackground);
	XSetForeground (mydisplay, mygc, myforeground);

	XSelectInput (mydisplay, mywindow,
	    ButtonPressMask | KeyPressMask | ExposureMask);

	/* map window to the screen */

	XMapRaised (mydisplay, mywindow);


	/* Loop through until a q is press when the cursor is in
           the window, which will cause the application to quit */

	done = 0;
	while (done == 0) {
		XNextEvent (mydisplay, &myevent );


		switch (myevent.type) {

		case Expose:
			if (myevent.xexpose.count == 0)

				break;


		case MappingNotify:
			XRefreshKeyboardMapping (&myevent);
			break;


	/* When there is a mouse click fire up the graphics subroutines */

		case ButtonPress:

			animate(mydisplay,mywindow,mygc);
			break;

			/* If a 'q' was pressed while the cursor is within
           the window set done to 1, which causes the loop
           to be broken and the program finishes */


		case KeyPress:
			i = XLookupString (&myevent, text, 10, &mykey, 0);
			if (i == 1 && text[0] == 'q')
				done = 1;
			break;


		} /* switch */


	} /* while (done == 0) */


	/* Free up and clean up the window created */


	XFreeGC (mydisplay, mygc);
	XDestroyWindow (mydisplay, mywindow);
	XCloseDisplay (mydisplay);

	exit(0);

} /* main */

/* The purpose of animate is to show a simple animation of two
   black and white triangles coming at each other and crashing */


animate(the_display,the_window,the_gc)
Display *the_display;
Drawable the_window;
GC the_gc;


{
	int k;
	int i;
	int j;
	float speed;
	XPoint figure2[4];
	XPoint figure1[4];

	/* set up the two triangles at opposite edges of the screen */

	figure1[0].x = 100;
	figure1[0].y = 350;
	figure1[1].x = 200;
	figure1[1].y = 350;
	figure1[2].x = 100;
	figure1[2].y = 250;
	figure1[3].x = 100;
	figure1[3].y = 350;
	figure2[0].x = 800;
	figure2[0].y = 350;
	figure2[1].x = 900;
	figure2[1].y = 350;
	figure2[2].x = 900;
	figure2[2].y = 250;
	figure2[3].x = 800;
	figure2[3].y = 350;


	XClearWindow(the_display,the_window);

	/* set up initial speed */

	speed = 4;

	/* draw the two figures */


	for (i=0; i<14; i++)

	{
		/* draw the two triangles */
		XDrawLines(the_display,the_window,the_gc,
			figure2,4,CoordModeOrigin);
		XDrawLines(the_display,the_window,the_gc,
			figure1,4,CoordModeOrigin);


		/* add to the speed, which will make it culmulative and give
           the appeareance that the triangles are speeding up as they
           get closer and closer */

		speed = speed + 2.5;


		/* move the figures over an increment/decement of speed */

		for (j=0; j<4; j++)
		{
			figure1[j].x = figure1[j].x + speed ;
			figure2[j].x = figure2[j].x  - speed ;
		}

		/* clear the window for the next frame */

		XClearWindow(the_display,the_window);

	}


	/* do the crash by stretching and pulling the triangles apart */

	for (i=0; i<25; i= i + 1)
	{
		/* draw the triangles */

		XDrawLines(the_display,the_window,the_gc,
			figure1,4,CoordModeOrigin);
		XDrawLines(the_display,the_window,the_gc,
			figure2,4,CoordModeOrigin);

		/* stretch the triangles by moving the points around */

		for (j=0; j<4; j++)
		{
			figure1[j].y = figure1[j].y - 4 * (j);
			figure1[j].x = figure1[j].x - 4 * (j) ;
			figure2[j].y = figure2[j].y + 4 * (j);
			figure2[j].x = figure2[j].x + 4 * (j) ;

		}

		/* clear the screen for the next frame 
			to give a animation effect */

		XClearWindow(the_display,the_window);

	}


}



