xlib_playground

Xlib playground for experiments.
Log | Files | Refs

ex2.c (3977B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <time.h>
      4 #include <unistd.h>
      5 #include <math.h>
      6 
      7 #include <X11/Xlib.h>
      8 
      9 /* macros */
     10 #define INIT_WIDTH 800
     11 #define INIT_HEIGHT 600
     12 #define FPS 60
     13 
     14 /*
     15 #define COUNT_FPS
     16 */
     17 
     18 
     19 enum Keys {
     20 	Key_D,
     21     Key_S,
     22     Key_A,
     23     Key_W,
     24     Key_Space,
     25     Num_Key, //number of keys in this enum
     26 };
     27 enum Key_State {
     28     Key_Up,
     29     Key_Down,
     30 };
     31 
     32 /* variables */
     33 Display     *display;
     34 Window       window;
     35 unsigned int win_width = INIT_WIDTH, win_height = INIT_HEIGHT;
     36 GC           gc;
     37 Atom         wm_delete_window;
     38 int          key_state[Num_Key];
     39 int          quit;
     40 float        px = 200, py = 200;
     41 float        vx = 0, vy = 0;
     42 int          width = 40, height = 40;
     43 
     44 
     45 /* function prototypes */
     46 void setup(void);
     47 void cleanup(void);
     48 void handle_inputs(void);
     49 
     50 
     51 void
     52 setup(void)
     53 {
     54 	if ((display = XOpenDisplay(NULL)) == NULL){
     55 	    fprintf(stderr, "ERROR: could not open display\n");
     56 	    exit(1);
     57 	}
     58 	window = XCreateSimpleWindow(
     59 	                    display,
     60 	                    XDefaultRootWindow(display),
     61 	                    0, 0,
     62 	                    win_width, win_height,
     63 	                    0, 0,
     64 						0);
     65 	XStoreName(display, window, "UNKO");
     66 	gc = XCreateGC(display, window, 0, NULL);
     67 
     68 	wm_delete_window = XInternAtom(display, 
     69 	                               "WM_DELETE_WINDOW", False);
     70 	XSetWMProtocols(display, window, &wm_delete_window, 1);
     71 
     72 	XSelectInput(display, window,
     73 	             ExposureMask|KeyPressMask|KeyReleaseMask);
     74 	
     75 	XSetForeground(display, gc, 0x00FFFF);
     76 	XMapWindow(display, window);
     77 }
     78 
     79 void
     80 handle_inputs(void)
     81 {
     82 	XEvent event;
     83 	while (XPending(display) > 0) {
     84 		XNextEvent(display, &event);
     85 		switch (event.type) {
     86 		case KeyPress: {
     87 			switch (XLookupKeysym(&event.xkey, 0)) {
     88 			case 'q':
     89 				quit = 1;
     90 				break;
     91 			case 'd':
     92 				key_state[Key_D] = Key_Down;
     93 				break;
     94 			case 'a':
     95 				key_state[Key_A] = Key_Down;
     96 				break;
     97 			case 'w':
     98 				key_state[Key_W] = Key_Down;
     99 				break;
    100 			case 's':
    101 				key_state[Key_S] = Key_Down;
    102 				break;
    103 			default:
    104 				break;
    105 			}
    106 		} break;
    107 		case KeyRelease: {
    108 			switch (XLookupKeysym(&event.xkey, 0)) {
    109 			case 'd':
    110 				key_state[Key_D] = Key_Up;
    111 				break;
    112 			case 'a':
    113 				key_state[Key_A] = Key_Up;
    114 				break;
    115 			case 'w':
    116 				key_state[Key_W] = Key_Up;
    117 				break;
    118 			case 's':
    119 				key_state[Key_S] = Key_Up;
    120 				break;
    121 			default:
    122 				break;
    123 			}
    124 		} break;
    125 		case ClientMessage: {
    126 			if ((Atom) event.xclient.data.l[0] == wm_delete_window) {
    127 				quit = 1;
    128 			}
    129 		} break;
    130 		default:
    131 			break;
    132 		}
    133 	}
    134 
    135 
    136 	vx = vy = 0;
    137 	if (key_state[Key_D] == Key_Down)
    138 		vx += 300;
    139 	if (key_state[Key_A] == Key_Down)
    140 		vx += -300;
    141 	if (key_state[Key_S] == Key_Down)
    142 		vy += 300;
    143 	if (key_state[Key_W] == Key_Down)
    144 		vy += -300;
    145 
    146 }
    147 
    148 void
    149 cleanup(void)
    150 {
    151 	XCloseDisplay(display);
    152 }
    153 
    154 int
    155 main(void)
    156 {
    157 	long t0, t1, dt;
    158 #ifdef COUNT_FPS
    159 	int fps_count = 0;
    160 #endif
    161 	struct timespec ts;
    162 
    163 	setup();
    164 	quit = 0;
    165 	clock_gettime(CLOCK_MONOTONIC, &ts);
    166 	t0 = ts.tv_nsec;
    167 
    168 	while (!quit){
    169 		handle_inputs();
    170 
    171 		// fix fps
    172 		dt = 0;
    173 		while (dt < 1.0 * 1000 * 1000 * 1000 / FPS){
    174 			clock_gettime(CLOCK_MONOTONIC, &ts);
    175 			t1 = ts.tv_nsec;
    176 			dt = t1 > t0 ? t1 - t0 : t1 - t0 + 1000 * 1000 * 1000;
    177 		}
    178 #ifdef COUNT_FPS
    179 		// count fps.
    180 		// simple but not precise.
    181 		fps_count++;
    182 		if (t1 < t0){
    183 			printf("fps: %u\n", fps_count);
    184 			fps_count = 0;
    185 		}
    186 #endif
    187 
    188 		clock_gettime(CLOCK_MONOTONIC, &ts);
    189 		t0 = ts.tv_nsec;
    190 
    191 		px = px + vx * dt / 1000 / 1000 / 1000;
    192 		py = py + vy * dt / 1000 / 1000 / 1000; 
    193 		// bind within the window
    194 		if (px < 0)
    195 			px = 0;
    196 		if (win_width < px + width)
    197 			px = win_width - width;
    198 		if (py < 0)
    199 			py = 0;
    200 		if (win_height < py + height)
    201 			py = win_height - height;
    202 
    203 		XClearArea(display, window,
    204 				   0, 0,                  // position
    205 				   win_width, win_height, // width and height
    206 				   False);
    207 		XFillRectangle(display, window, gc,
    208 					   px, py,    // position
    209 					   width, height);   // width and height
    210 
    211 	}
    212 
    213 	cleanup();
    214 	return 0;
    215 }