xlib_playground

Xlib playground for experiments.
Log | Files | Refs

commit ad942f879d3fa0060e08e1d16a5c3aec54ce77de
parent b4f731f69d4f3a8b5ababa66670dcab173ceb07d
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Tue, 10 Jan 2023 08:52:07 +0900

Divide headers completely...

Divided main.h into x.h and object.h. And renamed x.h to draw.h.
Some functions still uses interfaces from multiple header files.
These are defined in the main.c file. Is there some way to write
these functions more cleanly?

Diffstat:
Mex9/main.c | 36+++++++++++++++++++++++++++++++++++-
Dex9/main.h | 91-------------------------------------------------------------------------------
Dex9/util.c | 186-------------------------------------------------------------------------------
Dex9/x.c | 168-------------------------------------------------------------------------------
4 files changed, 35 insertions(+), 446 deletions(-)

diff --git a/ex9/main.c b/ex9/main.c @@ -5,7 +5,8 @@ #include <unistd.h> #include <string.h> -#include "main.h" +#include "object.h" +#include "draw.h" #include "list.h" #include "world_map.h" @@ -64,7 +65,12 @@ void handle_inputs(enum key_state[]); void col_pf(struct Object *, struct Object *); // player-flag void col_pb(struct Object *, struct Object *); // player-block +/* misc: these functions use interfaces from multiple header files */ +/* TODO: I want to rewrite these more cleanly */ void sort_list_dist(struct List *, struct Object *); +void draw_object(const struct Object *); +void draw_object_scroll(const struct Object *, int); + void start_menu(void) @@ -464,6 +470,34 @@ sort_list_dist(struct List *lp, struct Object *o) } } +void +draw_object(const struct Object *o) +{ + if (o->shape == SRECTANGLE) { + x_draw_rectangle(o->color, + o->p.x, o->p.y, + o->body.rectangle.w, + o->body.rectangle.h); + } else { + fprintf(stderr, "draw_object: Drawing object other than rectangle is" + "not implemented yet.\n"); + } +} + +void +draw_object_scroll(const struct Object *o, int sd) +{ + if (o->shape == SRECTANGLE) { + x_draw_rectangle(o->color, + o->p.x - sd, o->p.y, + o->body.rectangle.w, + o->body.rectangle.h); + } else { + fprintf(stderr, "draw_object_scroll: Drawing object other than" + "rectangle is not implemented yet.\n"); + } +} + int main(void) { diff --git a/ex9/main.h b/ex9/main.h @@ -1,91 +0,0 @@ -/* - * util.c - */ -enum object_shape { - SRECTANGLE, - STRIANGLE, - SCIRCLE, -}; - -enum object_type { - TPLAYER, - TBLOCK, - TENEMY, - TFLAG, - NUM_OBJ_TYPE, -}; - -struct Point { - float x; - float y; -}; - -struct Rectangle { // origin is top left corner - int w, h; -}; - -struct Triangle { - struct Point v2; - struct Point v3; -}; - -struct Circle { // origin is center - float r; -}; - -union Body { - struct Circle circle; - struct Triangle triangle; - struct Rectangle rectangle; -}; - -struct Object { - enum object_type type; - enum object_shape shape; - uint32_t color; - struct Point pp; - struct Point p; - struct Point v; - struct Point a; - union Body body; - int m; -}; - -extern void (* col_func[NUM_OBJ_TYPE][NUM_OBJ_TYPE])(struct Object *, struct Object *); - -int object_dist(struct Object *, struct Object *); -void handle_collision(struct Object *, struct Object *); -int test_collision(struct Object *, struct Object *); // 1 if collide, 0 if not -void next_tick(struct Object *o, long); -void handle_collision_mf(struct Object *, struct Object *); -int object_is_falling(struct Object *o, struct Object *fb, int num_f); -struct Object *create_object(enum object_type, uint32_t, - float, float, float, float, float, float, - int, int, int); -void free_object(struct Object *); -int is_on_floor_before(struct Object *, struct Object *); - - -/* - * x.c - */ -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 draw_object(const struct Object *); -void draw_object_scroll(const struct Object *, int); -void x_flush(void); -void x_clean_up(void); -int x_next_event(char *c); -int x_pending(void); -void x_get_win_wh(int *, int *); diff --git a/ex9/util.c b/ex9/util.c @@ -1,186 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> - -#include "main.h" - -static int test_collision_rr(struct Object *, struct Object *); -static void rect_next_tick(struct Object *, long); -static void rect_handle_collision_mf(struct Object *, struct Object *); - -struct Object * -create_object(enum object_type t, uint32_t color, - float px, float py, float vx, float vy, float ax, float ay, - int w, int h, int m) -{ - struct Object *o; - o = (struct Object *)malloc(sizeof(struct Object)); - o->type = t; - o->color = color; - o->shape = SRECTANGLE; - o->pp.x = o->p.x = px; - o->pp.y = o->p.y = py; - o->v.x = vx; - o->v.y = vy; - o->a.x = ax; - o->a.y = ay; - o->body.rectangle.w = w; - o->body.rectangle.h = h; - o->m = m; - return o; -} - -void -free_object(struct Object *o) -{ - free(o); -} - -/* - * 1 if collide, 0 if not - */ -int -test_collision(struct Object *o1, struct Object *o2) -{ - if (o1->shape == SRECTANGLE && o2->shape == SRECTANGLE) - return test_collision_rr(o1, o2); - else { - fprintf(stderr, "test_collision for other shapes is not implemented yet\n"); - return -1; - } -} - -static int -test_collision_rr(struct Object *o1, struct Object *o2) -{ - if (o1->shape != SRECTANGLE || o2->shape != SRECTANGLE) { - fprintf(stderr, "test_collision_rr: invalid objects\n"); - return -1; - } - return o1->p.x < o2->p.x + o2->body.rectangle.w && - o2->p.x < o1->p.x + o1->body.rectangle.w && - o2->p.y < o1->p.y + o1->body.rectangle.h && - o1->p.y < o2->p.y + o2->body.rectangle.h; -} - -void -next_tick(struct Object *o, long ndt) -{ - switch (o->shape) { - case SRECTANGLE: - rect_next_tick(o, ndt); - break; - default: - fprintf(stderr, "next_tick: not implemented for other shapes\n"); - break; - } -} - -static void -rect_next_tick(struct Object *o, long ndt) -{ - if (o->shape != SRECTANGLE) { - fprintf(stderr, "rect_next_tick: invalid object shape\n"); - return; - } - o->pp.x = o->p.x; - o->pp.y = o->p.y; - o->v.x += o->a.x * ndt / 1e9; - o->v.y += o->a.y * ndt / 1e9; - o->p.x += o->v.x * ndt / 1e9; - o->p.y += o->v.y * ndt / 1e9; -} - -void -handle_collision_mf(struct Object *om, struct Object *of) -{ - // TODO: too many testing? - if (!test_collision(om, of)) - return; - if (om->shape == SRECTANGLE && of->shape == SRECTANGLE) - rect_handle_collision_mf(om, of); - else { - fprintf(stderr, "handle_collision_mf: not implemented for other shapes\n"); - return; - } -} - -/* - * Handle collision of a moving rect against fixed rect - */ -static void -rect_handle_collision_mf(struct Object *om, struct Object *of) -{ - // TODO: too many testing? - if (!test_collision(om, of)) - return; - if (om->pp.x + om->body.rectangle.w <= of->pp.x && - of->p.x < om->p.x + om->body.rectangle.w) { - // collisioin from left to right - om->p.x = of->p.x - om->body.rectangle.w; - om->v.x = 0; - } - if (of->pp.x + of->body.rectangle.w <= om->pp.x && - om->p.x < of->p.x + of->body.rectangle.w) { - // collision from right to left - om->p.x = of->p.x + of->body.rectangle.w; - om->v.x = 0; - } - - if (om->pp.y + om->body.rectangle.h <= of->pp.y && - of->p.y < om->p.y + om->body.rectangle.h) { - // collision from up to down - om->p.y = of->p.y - om->body.rectangle.h; - om->v.y = 0; - } - if (of->pp.y + of->body.rectangle.h <= om->pp.y && - om->p.y < of->p.y + of->body.rectangle.h) { - // collision from down to up - om->p.y = of->p.y + of->body.rectangle.h; - om->v.y = 0; - } - -} - -/* - * Test if object o is not on top of one of fb (floor blocks). - * o: object to be tested, fb: floor blocks, num_f: count of fb. - */ -int -object_is_falling(struct Object *o, struct Object *fb, int num_f) -{ - struct Object p = *o; - - p.v.x = 0; p.v.y = 1; - p.a.x = 0; p.a.y = 0; - - next_tick(&p, 1e9); - - for (int i = 0; i < num_f; i++) - if (test_collision(&p, &fb[i])) - return 0; - return 1; -} - -int -object_dist(struct Object *o1, struct Object *o2) -{ - return (o1->p.x - o2->p.x) * (o1->p.x - o2->p.x) + - (o1->p.y - o2->p.y) * (o1->p.y - o2->p.y); -} - -int -is_on_floor_before(struct Object *player, struct Object *floor) -{ - struct Object o = *player; - o.p.x = o.pp.x; o.p.y = o.pp.y; - o.v.x = 0; o.v.y = 5; - o.a.x = 0; o.a.y = 0; - next_tick(&o, 1e9); - int col = test_collision(&o, floor); - return col; -} - -void handle_collision(struct Object *o0, struct Object *o1) { - (* col_func[o0->type][o1->type])(o0, o1); -} diff --git a/ex9/x.c b/ex9/x.c @@ -1,168 +0,0 @@ -#include <stdio.h> -#include <stdint.h> - -#include <X11/Xlib.h> - -#include "main.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); - - 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 -draw_object(const struct Object *op) -{ - if (op->shape == SRECTANGLE) { - x_draw_rectangle(op->color, - op->p.x, op->p.y, - op->body.rectangle.w, - op->body.rectangle.h); - } else { - fprintf(stderr, "draw_object: Drawing object other than rectangle is" - "not implemented yet.\n"); - } -} - -void -draw_object_scroll(const struct Object *op, int sd) -{ - if (op->shape == SRECTANGLE) { - x_draw_rectangle(op->color, - op->p.x - sd, op->p.y, - op->body.rectangle.w, - op->body.rectangle.h); - } else { - fprintf(stderr, "draw_object_scroll: Drawing object other than" - "rectangle is not implemented yet.\n"); - } -} - -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); - if (c == NULL) - return NOEVENT; - 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); -} - -void -x_get_win_wh(int *w, int *h) -{ - *w = win_width; - *h = win_height; -}