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 }