xlib_playground

Xlib playground for experiments.
Log | Files | Refs

commit bf99ee5e45e20f75539e34d4cae7a236a5638430
parent fcd90e72f24211f1accd6c1413711e1169591e54
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Thu,  5 Jan 2023 07:54:24 +0900

delete original

Diffstat:
DMakefile | 14--------------
Dmain.c | 393-------------------------------------------------------------------------------
Dobj.h | 101-------------------------------------------------------------------------------
3 files changed, 0 insertions(+), 508 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,14 +0,0 @@ -INCS=-I/usr/X11R6/include -CFLAGS=-Wall -W -Wextra -Wpointer-arith -Wbad-function-cast -std=c11 -LIBS=-L/usr/X11R6/lib -lX11 -lXext -IN=*.c -OUT=main - -all: $(IN) - $(CC) $(INCS) $(CFLAGS) -o $(OUT) $(IN) $(LIBS) - -run: all - ./$(OUT) - -clean: - rm -f $(OUT) diff --git a/main.c b/main.c @@ -1,393 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <time.h> -#include <string.h> - -#include <X11/Xlib.h> - -#include "obj.h" - -/* macros */ -#define INIT_WIDTH 800 -#define INIT_HEIGHT 600 -#define FPS 60 -#define BLOCK_COUNT 3 - - -/* variables */ -Display *display; -Window window; -unsigned int win_width = INIT_WIDTH, win_height = INIT_HEIGHT; -GC pgc, fgc, bgc; -Atom wm_delete_window; -Obj *square; -Obj *blocks[BLOCK_COUNT]; -int quit = 0; -enum Keys { - Key_D, - Key_S, - Key_A, - Key_W, - Key_Space, - Num_Key, //number of keys in this enum -}; -enum Key_State { - Key_Up, - Key_Down, -}; -int key_state[Num_Key]; -enum Next_Menu { - Start_Menu, - Game_Play, - End_Menu, - Quit, -}; -int next_menu = Start_Menu; - - -/* function prototypes */ -void setup(void); -void start_menu(void); -void game_init(void); -void game_play(void); -void draw_object(Obj *, GC); -void handle_collision(void); -void handle_inputs(void); -void end_menu(void); -void next_tick(float); -void cleanup(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"); - pgc = XCreateGC(display, window, 0, NULL); - fgc = XCreateGC(display, window, 0, NULL); - bgc = 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); - - XSetForeground(display, pgc, 0x00FF00); - XSetForeground(display, fgc, 0xFFFFFF); - XSetForeground(display, bgc, 0x0000FF); - 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, win_width, win_height, False); - - XDrawString(display, window, fgc, - win_width/2 - strlen(menu_char_q)/2, win_height/2, - menu_char_q, strlen(menu_char_q)); - XDrawString(display, window, fgc, - 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, fgc, - win_width/2 - strlen(menu_char_q)/2, win_height/2, - menu_char_q, strlen(menu_char_q)); - XDrawString(display, window, fgc, - 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 -game_init(void) -{ - if(!square) // not allocated - if(!(square = obj_create(100, 100, 0, 0, 0, 0, 400, 20, 20))){ - fprintf(stderr, "couldn't create object: square"); - exit(1); - } - for (int i = 0; i < BLOCK_COUNT; i++){ - struct timespec t; - clock_gettime(CLOCK_REALTIME, &t); - srand(t.tv_nsec); - if(!blocks[i]) // not allocated - if(!(blocks[i] = obj_create((i + 1) * 100, - 200, - 0, 0, - 0, 0, 100, 10, 10))){ - fprintf(stderr, "couldn't create object: block"); - exit(1); - } - } - - square->px = 100; - square->py = 100; - square->vx = square->vy = 0; - square->ax = square->ay = 0; -} - -void -game_play(void) -{ - long t0, t1, dt; - struct timespec ts; - - game_init(); - - clock_gettime(CLOCK_MONOTONIC, &ts); - t0 = ts.tv_nsec; - - while (next_menu == Game_Play){ - XWindowAttributes window_attributes_return; - XGetWindowAttributes(display, window, &window_attributes_return); - win_width = window_attributes_return.width; - win_height = window_attributes_return.height; - - clock_gettime(CLOCK_MONOTONIC, &ts); - t1 = ts.tv_nsec; - dt = t1 - t0 > 0 ? t1 - t0 : t1 - t0 + 1000 * 1000 * 1000; - while(dt < 1.0/FPS * 1000 * 1000 * 1000){ - clock_gettime(CLOCK_MONOTONIC, &ts); - t1 = ts.tv_nsec; - dt = t1 - t0 > 0 ? t1 - t0 : t1 - t0 + 1000 * 1000 * 1000; - } - - //handle_interactions(); //handle interactions between objects - handle_inputs(); - obj_next_tick(square, 1.0/FPS); - for (int i = 0; i < BLOCK_COUNT; i++) - obj_next_tick(blocks[i], 1.0/FPS); - handle_collision(); - - clock_gettime(CLOCK_MONOTONIC, &ts); - t0 = ts.tv_nsec; - - XClearArea(display, window, 0, 0, win_width, win_height, False); - draw_object(square, pgc); - for (int i = 0; i < BLOCK_COUNT; i++){ - XSetForeground(display, bgc, 255 << 8 * i); - draw_object(blocks[i], bgc); - } - //XDrawString(display, window, fgc, square->px, square->py, "player", 6); - } -} - -void -draw_object(Obj *obj, GC gc) -{ - XFillRectangle(display, window, gc, obj->px, obj->py, obj->width, obj->height); -} - -void -end_menu(void) -{ - next_menu = Start_Menu; -} - -void -handle_inputs(void) -{ - while (XPending(display) > 0) { - XEvent event; - XNextEvent(display, &event); - switch (event.type) { - case KeyPress: { - switch (XLookupKeysym(&event.xkey, 0)) { - case 'q': - next_menu = End_Menu; - break; - case 'd': - key_state[Key_D] = Key_Down; - break; - case 'a': - key_state[Key_A] = Key_Down; - break; - case 'w': - key_state[Key_W] = Key_Down; - break; - case 's': - key_state[Key_S] = Key_Down; - break; - case ' ': - key_state[Key_Space] = Key_Down; - break; - default: - break; - } - } break; - case KeyRelease: { - switch (XLookupKeysym(&event.xkey, 0)) { - case 'd': - key_state[Key_D] = Key_Up; - break; - case 'a': - key_state[Key_A] = Key_Up; - break; - case 'w': - key_state[Key_W] = Key_Up; - break; - case 's': - key_state[Key_S] = Key_Up; - break; - case ' ': - key_state[Key_Space] = Key_Up; - break; - default: - break; - } - } break; - case ClientMessage: { - if ((Atom) event.xclient.data.l[0] == wm_delete_window) { - next_menu = Quit; - } - } break; - default: - break; - } - } - - square->vx = 0; - if (key_state[Key_D] == Key_Down) - square->vx += 100; - else - square->vx -= 100; - if (key_state[Key_A] == Key_Down) - square->vx += -100; - else - square->vx -= -100; - - square->vy = 0; - if (key_state[Key_S] == Key_Down) - square->vy += 100; - else - square->vy -= 100; - if (key_state[Key_W] == Key_Down) - square->vy += -100; - else - square->vy -= -100; -} - -void -handle_collision(void) -{ - for (int i = 0; i < BLOCK_COUNT; i++){ - if (blocks[i]->px <= 0){ - blocks[i]->px = 0; - blocks[i]->vx *= -1; - } - if (win_width <= blocks[i]->px + blocks[i]->width){ - blocks[i]->px = win_width - blocks[i]->width; - blocks[i]->vx *= -1; - } - - if (blocks[i]->py <= 0){ - blocks[i]->py = 0; - blocks[i]->vy *= -1; - } - if (win_height <= blocks[i]->py + blocks[i]->height){ - blocks[i]->py = win_height - blocks[i]->height; - blocks[i]->vy *= -1; - } - } - - if (square->px <= 0){ - square->px = 0; - square->vx *= -1; - } - if (win_width <= square->px + square->width){ - square->px = win_width - square->width; - square->vx *= -1; - } - if (square->py <= 0){ - square->py = 0; - square->vy *= -1; - } - if (win_height <= square->py + square->height){ - square->py = win_height - square->height; - square->vy *= -1; - } - - for (int i = 0; i < BLOCK_COUNT; i++){ - for (int j = i; j < BLOCK_COUNT; j++){ - obj_handle_collision(blocks[i], blocks[j]); - } - } - for (int i = 0; i < BLOCK_COUNT; i++){ - obj_handle_collision(blocks[i], square); - } -} - - -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 End_Menu: - end_menu(); - break; - default: - break; - } - } - - cleanup(); - return 0; -} diff --git a/obj.h b/obj.h @@ -1,101 +0,0 @@ -typedef struct Obj{ - float ppx, ppy; //previous position - float px, py; //current position - float vx, vy; //velocity - float ax, ay; //acceleration - float m; //mass - float width, height; -} Obj; - -Obj *obj_create(float px, float py, - float vx, float vy, - float ax, float ay, - float m, - float width, float height); -void obj_move(Obj *obj, float px, float py); // move obj to the pos -void obj_next_tick(Obj *obj, float dt); // move obj by velocity * dt -void obj_accel(Obj *obj, float ax, float ay); // accelerate obj by accel -int obj_test_collision(Obj *obj1, Obj *obj2); -void obj_handle_collision(Obj *obj1, Obj *obj2); - -Obj -*obj_create(float px, float py, - float vx, float vy, - float ax, float ay, - float m, - float width, float height) -{ - Obj *obj; - obj = (Obj *) malloc(sizeof(Obj)); - obj->ppx = obj->px = px; - obj->ppy = obj->py = py; - obj->vx = vx; - obj->vy = vy; - obj->ax = ax; - obj->ay = ay; - obj->m = m; - obj->width = width; - obj->height = height; - return obj; -} - -void -obj_move(Obj *obj, float px, float py) -{ - obj->ppx = obj->px = px; - obj->ppy = obj->py = py; -} - -void -obj_next_tick(Obj *obj, float dt) -{ - obj->ppx = obj->px; - obj->ppy = obj->py; - obj->vx += obj->ax * dt; - obj->vy += obj->ay * dt; - obj->px += obj->vx * dt; - obj->py += obj->vy * dt; -} - -void -obj_accel(Obj *obj, float ax, float ay) -{ - obj->vx += ax; - obj->vy += ay; -} - - -int -obj_test_collision(Obj *obj1, Obj *obj2) -{ - return obj1->py < obj2->py + obj2->height && - obj2->py < obj1->py + obj1->height && - obj1->px < obj2->px + obj2->width && - obj2->px < obj1->px + obj1->width; -} - -void -obj_handle_collision(Obj *obj1, Obj *obj2) -{ - if(!obj_test_collision(obj1, obj2)) - return; - - float v1, v2; - float m1 = obj1->m; - float m2 = obj2->m; - - if (obj2->ppy + obj2->height <= obj1->ppy || - obj1->ppy + obj1->height <= obj2->ppy){ - v1 = obj1->vy; - v2 = obj2->vy; - obj1->vy = 2*m2/(m1+m2)*v2 + (m1-m2)/(m1+m2)*v1; - obj2->vy = 2*m1/(m1+m2)*v1 + (m2-m1)/(m1+m2)*v2; - }else if (obj2->ppx + obj2->width <= obj1->ppx || - obj1->ppx + obj1->width <= obj2->ppx){ - v1 = obj1->vx; - v2 = obj2->vx; - obj1->vx = 2*m2/(m1+m2)*v2 + (m1-m2)/(m1+m2)*v1; - obj2->vx = 2*m1/(m1+m2)*v1 + (m2-m1)/(m1+m2)*v2; - } - -}