xlib_playground

Xlib playground for experiments.
Log | Files | Refs

commit 800429750907d7f1041a9af4199bc2ae6d45969b
parent 9abbafd3e1c0f82f85bd210d5958f802a246b98c
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Fri, 23 Dec 2022 13:11:41 +0900

add menu

Diffstat:
Mex3/ex3.c | 167+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 133 insertions(+), 34 deletions(-)

diff --git a/ex3/ex3.c b/ex3/ex3.c @@ -2,6 +2,7 @@ #include <stdlib.h> #include <time.h> #include <unistd.h> +#include <string.h> #include <math.h> #include <X11/Xlib.h> @@ -15,18 +16,24 @@ #define COUNT_FPS */ - enum keys { KEY_D, - KEY_S, - KEY_A, - KEY_W, - KEY_SPACE, - NUM_KEY, //number of keys in this enum + KEY_S, + KEY_A, + KEY_W, + KEY_Q, + KEY_SPACE, + NUM_KEY, //number of keys in this enum }; enum key_state { - KEY_UP, - KEY_DOWN, + KEY_UP, + KEY_DOWN, +}; +enum next_menu { + START_MENU, + GAME_PLAY, + GAME_OVER, + QUIT, }; /* variables */ @@ -35,18 +42,21 @@ Window window; unsigned int win_width = INIT_WIDTH, win_height = INIT_HEIGHT; GC gc; Atom wm_delete_window; -int key_state[NUM_KEY]; -int quit; float px = 200, py = 200; float vx = 0, vy = 0; int width = 40, height = 40; +int next_menu = START_MENU; /* function prototypes */ void setup(void); void cleanup(void); -void receive_events(void); -void handle_inputs(void); +void start_menu(void); +void game_play(void); +void receive_events(int *); +void handle_inputs(int *); +void next_tick(long); +void game_over(void); void @@ -66,19 +76,74 @@ setup(void) XStoreName(display, window, "UNKO"); gc = XCreateGC(display, window, 0, NULL); - wm_delete_window = XInternAtom(display, + wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False); XSetWMProtocols(display, window, &wm_delete_window, 1); XSelectInput(display, window, ExposureMask|KeyPressMask|KeyReleaseMask); - + XSetForeground(display, gc, 0x00FFFF); XMapWindow(display, window); } void -receive_events(void) +start_menu(void) +{ + XEvent event; + char *menu_char_q = "press q to quit."; + char *menu_char_s = "press <space> to start."; + + XClearArea(display, window, + 0, 0, // position + win_width, win_height, // width and height + False); + XDrawString(display, window, gc, + win_width/2 - strlen(menu_char_q)/2, win_height/2, + menu_char_q, strlen(menu_char_q)); + XDrawString(display, window, gc, + win_width/2 - strlen(menu_char_s)/2, win_height/2 + 20, + menu_char_s, strlen(menu_char_s)); + + while (next_menu == START_MENU) { + XNextEvent(display, &event); + switch (event.type) { + case Expose: { + XDrawString(display, window, gc, + win_width/2 - strlen(menu_char_q)/2, + win_height/2, + menu_char_q, strlen(menu_char_q)); + XDrawString(display, window, gc, + win_width/2 - strlen(menu_char_s)/2, + win_height/2 + 20, + menu_char_s, strlen(menu_char_s)); + + } break; + case KeyPress: { + switch (XLookupKeysym(&event.xkey, 0)) { + case 'q': + next_menu = QUIT; + break; + case ' ': + next_menu = GAME_PLAY; + break; + default: + break; + } + } break; + case ClientMessage: { + if ((Atom) event.xclient.data.l[0] == wm_delete_window) { + next_menu = QUIT; + } + } break; + default: + break; + } + } +} + +void +receive_events(int key_state[]) { XEvent event; XWindowAttributes wattr; @@ -94,7 +159,8 @@ receive_events(void) case KeyPress: { switch (XLookupKeysym(&event.xkey, 0)) { case 'q': - quit = 1; + //next_menu = GAME_OVER; + key_state[KEY_Q] = KEY_DOWN; break; case 'd': key_state[KEY_D] = KEY_DOWN; @@ -114,6 +180,9 @@ receive_events(void) } break; case KeyRelease: { switch (XLookupKeysym(&event.xkey, 0)) { + case 'q': + key_state[KEY_Q] = KEY_UP; + break; case 'd': key_state[KEY_D] = KEY_UP; break; @@ -132,7 +201,7 @@ receive_events(void) } break; case ClientMessage: { if ((Atom) event.xclient.data.l[0] == wm_delete_window) { - quit = 1; + next_menu = QUIT; } } break; default: @@ -142,8 +211,12 @@ receive_events(void) } void -handle_inputs(void) +handle_inputs(int key_state[]) { + if (key_state[KEY_Q] == KEY_DOWN){ + next_menu = GAME_OVER; + return; + } vx = vy = 0; if (key_state[KEY_D] == KEY_DOWN) vx += 300; @@ -159,7 +232,7 @@ void next_tick(long ndt) // nano second { px = px + vx * ndt / 1000 / 1000 / 1000; - py = py + vy * ndt / 1000 / 1000 / 1000; + py = py + vy * ndt / 1000 / 1000 / 1000; // bind within the window if (px < 0) px = 0; @@ -172,30 +245,24 @@ next_tick(long ndt) // nano second } void -cleanup(void) -{ - XCloseDisplay(display); -} - -int -main(void) +game_play(void) { + int key_state[NUM_KEY]; long t0, t1, dt; #ifdef COUNT_FPS int fps_count = 0; #endif struct timespec ts; - setup(); - quit = 0; - clock_gettime(CLOCK_MONOTONIC, &ts); - t0 = ts.tv_nsec; - - while (!quit){ - receive_events(); - handle_inputs(); + while (next_menu == GAME_PLAY){ + clock_gettime(CLOCK_MONOTONIC, &ts); + t0 = ts.tv_nsec; + receive_events(key_state); + handle_inputs(key_state); // fix fps + // TODO: This method create some strange stripe when + // rendered in 60fps monitor. dt = 0; while (dt < 1.0 * 1000 * 1000 * 1000 / FPS){ clock_gettime(CLOCK_MONOTONIC, &ts); @@ -223,7 +290,39 @@ main(void) XFillRectangle(display, window, gc, px, py, // position width, height); // width and height + } +} + +void +game_over(void) +{ + next_menu = START_MENU; +} +void +cleanup(void) +{ + XCloseDisplay(display); +} + +int +main(void) +{ + setup(); + while (next_menu != QUIT){ + switch (next_menu){ + case START_MENU: + start_menu(); + break; + case GAME_PLAY: + game_play(); + break; + case GAME_OVER: + game_over(); + break; + default: + break; + } } cleanup();