commit 2e345056ce414a0b80e7e7f26210b106a6c27112
parent 3f9b4e6f1a3cb716f36c7770eadb9294567a000f
Author: Matsuda Kenji <info@mtkn.jp>
Date: Tue, 27 Dec 2022 14:53:40 +0900
split Xlib related operation into separate files.
Diffstat:
M | ex7/ex7.c | | | 186 | +++++++++++++++++++++++++------------------------------------------------------ |
A | ex7/x.c | | | 131 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | ex7/x.h | | | 17 | +++++++++++++++++ |
3 files changed, 207 insertions(+), 127 deletions(-)
diff --git a/ex7/ex7.c b/ex7/ex7.c
@@ -5,7 +5,7 @@
#include <string.h>
#include <math.h>
-#include <X11/Xlib.h>
+#include "x.h"
/* macros */
#define INIT_WIDTH (800)
@@ -123,19 +123,14 @@ char world_map[WORLD_WIDTH * WORLD_HEIGHT + 1] =
"........................b.......b......................b...b....................";
/* variables */
-Display *display;
-Window window;
-unsigned int win_width = INIT_WIDTH, win_height = INIT_HEIGHT;
-GC gc, sgc[NUM_RECT];
-Atom wm_delete_window;
struct rect block[NUM_RECT];
struct rect player;
int player_is_falling;
int next_menu = START_MENU;
+extern int win_width, win_height;
/* function prototypes */
-void setup(void);
void cleanup(void);
void start_menu(void);
void game_play(void);
@@ -151,73 +146,43 @@ int circle_test_collision(struct circle *, struct circle *);
void update_falling_status(struct rect *, long);
void game_over(void);
-
-void
-setup(void)
-{
- if ((display = XOpenDisplay(NULL)) == NULL){
- fprintf(stderr, "ERROR: could not open display\n");
- exit(1);
- }
- window = XCreateSimpleWindow(
- display,
- XDefaultRootWindow(display),
- 0, 0,
- win_width, win_height,
- 0, 0,
- 0);
- XStoreName(display, window, "UNKO");
- gc = XCreateGC(display, window, 0, NULL);
- XSetForeground(display, gc, 0x00FFFF);
- for (int i = 0; i < NUM_RECT; i++){
- sgc[i] = XCreateGC(display, window, 0, NULL);
- XSetForeground(display, sgc[i], 0x00FF00);
- }
-
- wm_delete_window = XInternAtom(display,
- "WM_DELETE_WINDOW", False);
- XSetWMProtocols(display, window, &wm_delete_window, 1);
-
- XSelectInput(display, window,
- ExposureMask | KeyPressMask | KeyReleaseMask);
-
- XMapWindow(display, window);
-}
-
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));
+ x_clear_area();
+ x_draw_string(0x00FFFF,
+ win_width/2 - 10 * strlen(menu_char_q)/2,
+ win_height/2,
+ menu_char_q, strlen(menu_char_q));
+ x_draw_string(0x00FFFF,
+ win_width/2 - 10 * 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)) {
+ char c;
+ int event = x_next_event(&c);
+
+ switch (event) {
+ case XEXPOSE:
+ x_draw_string(0x00FFFF,
+ win_width/2 - 10 * strlen(menu_char_q)/2,
+ win_height/2,
+ menu_char_q, strlen(menu_char_q));
+ x_draw_string(0x00FFFF,
+ win_width/2 - 10 * strlen(menu_char_s)/2,
+ win_height/2 + 20,
+ menu_char_s, strlen(menu_char_s));
+
+ break;
+ case XWINDEL:
+ next_menu = QUIT;
+ break;
+ case XKEYPRESS:
+ switch (c) {
case 'q':
next_menu = QUIT;
break;
@@ -227,12 +192,7 @@ start_menu(void)
default:
break;
}
- } break;
- case ClientMessage: {
- if ((Atom) event.xclient.data.l[0] == wm_delete_window) {
- next_menu = QUIT;
- }
- } break;
+ break;
default:
break;
}
@@ -242,21 +202,17 @@ start_menu(void)
void
receive_events(int key_state[])
{
- XEvent event;
- XWindowAttributes wattr;
-
- while (XPending(display) > 0) {
- XNextEvent(display, &event);
- switch (event.type) {
- case Expose: {
- XGetWindowAttributes(display, window, &wattr);
- win_width = wattr.width;
- win_height = wattr.height;
- } break;
- case KeyPress: {
- switch (XLookupKeysym(&event.xkey, 0)) {
+ while (x_pending() > 0) {
+ char c;
+ int event = x_next_event(&c);
+
+ switch (event) {
+ case XWINDEL:
+ next_menu = QUIT;
+ break;
+ case XKEYPRESS:
+ switch (c) {
case 'q':
- //next_menu = GAME_OVER;
key_state[KEY_Q] = KEY_DOWN;
break;
case 'd':
@@ -277,9 +233,9 @@ receive_events(int key_state[])
default:
break;
}
- } break;
- case KeyRelease: {
- switch (XLookupKeysym(&event.xkey, 0)) {
+ break;
+ case XKEYRELEASE:
+ switch (c) {
case 'q':
key_state[KEY_Q] = KEY_UP;
break;
@@ -301,13 +257,6 @@ receive_events(int key_state[])
default:
break;
}
- } break;
- case ClientMessage: {
- if ((Atom) event.xclient.data.l[0] == wm_delete_window) {
- next_menu = QUIT;
- }
- } break;
- default:
break;
}
}
@@ -665,11 +614,6 @@ game_play(void)
collision[i] = 1;
}
}
- for (int i = 0; i < NUM_RECT; i++)
- if (collision[i] == 1)
- XSetForeground(display, sgc[i], 0xFFFF00);
- else
- XSetForeground(display, sgc[i], 0x90FF90);
// fix fps
// TODO: This method create some strange stripe when
@@ -689,23 +633,18 @@ game_play(void)
}
#endif
- XClearArea(display, window,
- 0, 0, // position
- win_width, win_height, // width and height
- False);
+ x_clear_area();
for (int i = 0; i < NUM_RECT; i++) {
- XDrawRectangle(display, window, sgc[i],
- block[i].px,
- block[i].py, // position
+ x_draw_rectangle(0x00FF00,
+ block[i].px, block[i].py, // position
block[i].w, block[i].h);
}
- XDrawRectangle(display, window, gc,
- player.px,
- player.py, // position
+ x_draw_rectangle(0x009FFF,
+ player.px, player.py, // position
player.w, player.h);
char status_string[128];
snprintf(status_string, 128, "falling: %d", player_is_falling);
- XDrawString(display, window, gc,
+ x_draw_string(0x00FFFF,
0, 20,
status_string,
strlen(status_string));
@@ -717,29 +656,22 @@ game_over(void)
{
char *menu_char = "GAME OVER";
- XClearArea(display, window,
- 0, 0, // position
- win_width, win_height, // width and height
- False);
- XDrawString(display, window, gc,
- win_width/2 - strlen(menu_char)/2, win_height/2,
+ x_clear_area();
+ x_draw_string(0x00FFFF,
+ win_width/2 - 10 * strlen(menu_char)/2, win_height/2,
menu_char, strlen(menu_char));
- XFlush(display);
+ x_flush();
sleep(1);
next_menu = START_MENU;
}
-void
-cleanup(void)
-{
- XCloseDisplay(display);
-}
-
int
main(void)
{
- setup();
+ win_width = 800;
+ win_height = 600;
+ x_setup_window(0, 0, win_width, win_height, 0x002240, "UNKO");
while (next_menu != QUIT){
switch (next_menu){
case START_MENU:
@@ -756,6 +688,6 @@ main(void)
}
}
- cleanup();
+ x_clean_up();
return 0;
}
diff --git a/ex7/x.c b/ex7/x.c
@@ -0,0 +1,131 @@
+#include <stdio.h>
+
+#include <X11/Xlib.h>
+
+#include "x.h"
+
+Display *display;
+Atom wm_delete_window;
+GC gc;
+Window window;
+unsigned int win_width, win_height;
+
+/*
+ * Creates a window
+ * If succeeded, returns 0
+ * If error occured, returns -1
+ */
+int
+x_setup_window(int x, int y,
+ unsigned int w, unsigned int h,
+ unsigned long bc, char *win_name)
+{
+ if ((display = XOpenDisplay(NULL)) == NULL){
+ fprintf(stderr, "ERROR: could not open display\n");
+ return -1;
+ }
+ window = XCreateSimpleWindow(
+ display,
+ XDefaultRootWindow(display),
+ x, y,
+ w, h,
+ 0, 0, // I don't need border?
+ bc);
+ win_width = w;
+ win_height = h;
+
+ XStoreName(display, window, win_name);
+ gc = XCreateGC(display, window, 0, NULL);
+ printf("hello\n");
+
+ wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(display, window, &wm_delete_window, 1);
+
+ XSelectInput(display, window,
+ ExposureMask | KeyPressMask | KeyReleaseMask);
+
+ XMapWindow(display, window);
+ return 0;
+}
+
+/*
+ * Clears the window with the background color.
+ * I don't know what the return value of XClearArea means...
+ */
+void
+x_clear_area(void)
+{
+ XClearArea(display, window,
+ 0, 0,
+ win_width, win_height,
+ False);
+}
+
+/*
+ * Draws a string with specified color.
+ */
+void
+x_draw_string(unsigned long color, int x, int y, const char *str, int length)
+{
+ XSetForeground(display, gc, color);
+ XDrawString(display, window, gc, x, y, str, length);
+}
+
+void
+x_draw_rectangle(unsigned long color, int x, int y,
+ unsigned int w, unsigned int h)
+{
+ XSetForeground(display, gc, color);
+ XDrawRectangle(display, window, gc, x, y, w, h);
+}
+
+void
+x_flush(void)
+{
+ XFlush(display);
+}
+
+void
+x_clean_up(void)
+{
+ XCloseDisplay(display);
+}
+
+int
+x_next_event(char *c)
+{
+ XEvent event;
+ XWindowAttributes wattr;
+
+ XNextEvent(display, &event);
+ switch (event.type) {
+ case Expose:
+ XGetWindowAttributes(display, window, &wattr);
+ win_width = wattr.width;
+ win_height = wattr.height;
+ return XEXPOSE;
+ break;
+ case ClientMessage:
+ if ((Atom) event.xclient.data.l[0] == wm_delete_window) {
+ return XWINDEL;
+ }
+ break;
+ case KeyPress:
+ *c = XLookupKeysym(&event.xkey, 0);
+ return XKEYPRESS;
+ break;
+ case KeyRelease:
+ *c = XLookupKeysym(&event.xkey, 0);
+ return XKEYRELEASE;
+ break;
+ default:
+ break;
+ }
+ return NOEVENT;
+}
+
+int
+x_pending(void)
+{
+ return XPending(display);
+}
diff --git a/ex7/x.h b/ex7/x.h
@@ -0,0 +1,17 @@
+enum event_type {
+ XKEYPRESS,
+ XKEYRELEASE,
+ XEXPOSE,
+ XWINDEL,
+ NOEVENT,
+};
+
+int x_setup_window(int, int, unsigned int, unsigned int, unsigned long, char *);
+void x_clear_area(void);
+void x_draw_string(unsigned long color, int x, int y, const char *str, int length);
+void x_draw_rectangle(unsigned long color, int x, int y,
+ unsigned int w, unsigned int h);
+void x_flush(void);
+void x_clean_up(void);
+int x_next_event(char *c);
+int x_pending(void);