animation.cpp 3.11 KB
Newer Older
Daniel Vogel's avatar
Daniel Vogel committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
/*
CS 349 Code Examples: X Windows and XLib

    animation.cpp   Ball bouncing in window (minimal version)

- - - - - - - - - - - - - - - - - - - - - -

See associated makefile for compiling instructions

*/

#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <sys/time.h>

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



// get microseconds
unsigned long now() {
	timeval tv;
	gettimeofday(&tv, NULL);
	return tv.tv_sec * 1000000 + tv.tv_usec;
}


using namespace std;

Display* display;
Window window;

// frames per second to run animation loop
int FPS = 120;

int main( int argc, char *argv[] ) {
	display = XOpenDisplay("");
	if (display == NULL) exit (-1);
	int screennum = DefaultScreen(display);
	long background = WhitePixel(display, screennum);
	long foreground = BlackPixel(display, screennum);
	window = XCreateSimpleWindow(display, DefaultRootWindow(display),
	                             10, 10, 300, 200, 2, foreground, background);
	XSelectInput(display, window,
	             ButtonPressMask | KeyPressMask); // select events
	XMapRaised(display, window);
	XFlush(display);

	XEvent event; // save the event here

	// ball postition, size, and velocity
	XPoint ballPos;
	ballPos.x = 50;
	ballPos.y = 50;
	int ballSize = 50;
	XPoint ballDir;
	ballDir.x = 3;
	ballDir.y = 3;

	// create gc for drawing
	GC gc = XCreateGC(display, window, 0, 0);

	// time of last window paint
	unsigned long lastRepaint = 0;

	XWindowAttributes w;
	XGetWindowAttributes(display, window, &w);

	// event loop
	while ( true ) {

		// TRY THIS
		// comment out this conditional to see what happens when
		// events block (run the program and keep pressing the mouse)
		if (XPending(display) > 0) { 
			XNextEvent( display, &event ); 

			switch ( event.type ) {

			// mouse button press
        	case ButtonPress:
	            cout << "CLICK" << endl;
            break;

			case KeyPress: // any keypress
			    KeySym key;
				char text[10];
          		int i = XLookupString( (XKeyEvent*)&event, text, 10, &key, 0 );
            	if ( i == 1 && text[0] == 'q' ) {
                	XCloseDisplay(display);
                	exit(0);
            	}
				break;
			}
		}

		unsigned long end = now();

		if (end - lastRepaint > 1000000 / FPS) { 

			// clear background
			XClearWindow(display, window);

			// draw ball from centre
			XFillArc(display, window, gc, 
				ballPos.x - ballSize/2, 
				ballPos.y - ballSize/2, 
				ballSize, ballSize,
				0, 360*64);

			// update ball position
			ballPos.x += ballDir.x;
			ballPos.y += ballDir.y;

			// bounce ball
			if (ballPos.x + ballSize/2 > w.width ||
				ballPos.x - ballSize/2 < 0)
				ballDir.x = -ballDir.x;
			if (ballPos.y + ballSize/2 > w.height ||
				ballPos.y - ballSize/2 < 0)
				ballDir.y = -ballDir.y;

			XFlush( display );

			lastRepaint = now(); // remember when the paint happened
		}

		// IMPORTANT: sleep for a bit to let other processes work
		if (XPending(display) == 0) {
			usleep(1000000 / FPS - (end - lastRepaint));
		}


	}
	XCloseDisplay(display);
}