#include #include #include #include #include #include #include #include #include Display *disp; Window wnd; Atom windele; int running; int fullscreen = 0; static int attributeList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None}; GLXContext gc; extern int input; int main(); void GLXinit(); void GLXinit() { char *str = "Zoom"; XTextProperty name; XSizeHints shints; XClassHint chint; XVisualInfo *vi; Colormap cmap; XSetWindowAttributes swa; Pixmap pixmap; Cursor cursor; XColor color; vi = glXChooseVisual(disp, DefaultScreen(disp), attributeList); cmap = XCreateColormap(disp, RootWindow(disp, vi->screen), vi->visual, AllocNone); swa.colormap = cmap; swa.border_pixel = 0; swa.event_mask = PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; wnd = XCreateWindow(disp, RootWindow(disp, vi->screen), 0, 0, 640, 480, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa); chint.res_name = "Zoom"; chint.res_class = "zoom"; XSetClassHint(disp, wnd, &chint); shints.flags = PMaxSize | PMinSize; shints.min_width = 640; shints.min_height = 480; shints.max_width = 640; shints.max_height = 480; XSetWMNormalHints(disp, wnd, &shints); if (XStringListToTextProperty(&str, 1, &name) != 0) { XSetWMName(disp, wnd, &name); XFree(name.value); } windele = XInternAtom(disp, "WM_DELETE_WINDOW", False); XSetWMProtocols(disp, wnd, &windele, 1); XMapWindow(disp, wnd); color.pixel = WhitePixel(disp, vi->screen); XQueryColor(disp, cmap, &color); pixmap = XCreatePixmap(disp, wnd, 1, 1, 1); cursor = XCreatePixmapCursor(disp, pixmap, pixmap, &color, &color, 0, 0); XFreePixmap(disp, pixmap); XDefineCursor(disp, wnd, cursor); XGrabPointer(disp, wnd, False, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, wnd, None, CurrentTime); XWarpPointer(disp, None, wnd, 0, 0, 0, 0, 320, 240); gc = glXCreateContext(disp, vi, NULL, True); glXMakeCurrent(disp, wnd, gc); XFree(vi); XSync(disp, 0); } int main() { unsigned long ticks, delta = 0; struct timeval tv; XEvent event; unsigned long frames = 0, tocks = 0; disp = XOpenDisplay(0); GLXinit(); running = InitGame(); gettimeofday(&tv, NULL); ticks = tv.tv_usec; while(running) { while(XPending(disp)) { XNextEvent(disp, &event); switch(event.type) { case ClientMessage: if(event.xclient.data.l[0] == windele) running = 0; break; case ButtonPress: input |= INPUT_OPEN; break; case ButtonRelease: if(event.xbutton.button == Button2) input &= ~INPUT_OPEN; break; case MotionNotify: if(event.xmotion.x == 320 && event.xmotion.y == 240) break; MouseInput(event.xmotion.x - 320, event.xmotion.y - 240); XWarpPointer(disp, None, wnd, 0, 0, 0, 0, 320, 240); break; case KeyPress: switch(XKeycodeToKeysym(disp, event.xkey.keycode, 0)) { case XK_Up: case XK_w: input |= INPUT_UP; break; case XK_Down: case XK_s: input |= INPUT_DOWN; break; case XK_Right: case XK_d: input |= INPUT_RIGHT; break; case XK_Left: case XK_a: input |= INPUT_LEFT; break; case XK_space: input |= INPUT_OPEN; break; case XK_Escape: running = 0; break; } break; case KeyRelease: switch(XKeycodeToKeysym(disp, event.xkey.keycode, 0)) { case XK_Up: case XK_w: input &= ~INPUT_UP; break; case XK_Down: case XK_s: input &= ~INPUT_DOWN; break; case XK_Right: case XK_d: input &= ~INPUT_RIGHT; break; case XK_Left: case XK_a: input &= ~INPUT_LEFT; break; case XK_space: input &= ~INPUT_OPEN; break; } } } if(!running) break; DoInput(delta); Render(); glXSwapBuffers(disp, wnd); XSync(disp, 0); gettimeofday(&tv, NULL); delta = ((tv.tv_usec + 1000000 - ticks)%1000000)/1000; ticks = (ticks + delta*1000) % 1000000; frames++; tocks += delta*1000; if(tocks > 1000000) { fprintf(stderr, "%lu\n", frames); frames = 0; tocks -= 1000000; } } UninitGame(); XUngrabPointer(disp, CurrentTime); XDestroyWindow(disp, wnd); glXDestroyContext(disp, gc); XCloseDisplay(disp); return 0; }