xlib_playground

Xlib playground for experiments.
Log | Files | Refs

commit ab84937dd27fac207c1072ed854a472d00ab3927
parent 9a89b434ece1e2bd1d8d81afe0b5465cd4423f9f
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Fri, 30 Dec 2022 10:03:16 +0900

change name

Diffstat:
Mex7/Makefile | 2+-
Dex7/ex7.c | 403-------------------------------------------------------------------------------
Aex7/main.c | 403+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rex7/ex7.h -> ex7/main.h | 0
Mex7/physics.c | 2+-
Mex7/x.c | 2+-
6 files changed, 406 insertions(+), 406 deletions(-)

diff --git a/ex7/Makefile b/ex7/Makefile @@ -2,7 +2,7 @@ INCS=-I/usr/X11R6/include CFLAGS=-Wall -W -Wextra -Wpointer-arith -Wbad-function-cast -std=c11 LIBS=-L/usr/X11R6/lib -lX11 -lXext -lm IN=*.c -OUT=ex7 +OUT=main all: $(IN) $(CC) $(INCS) $(CFLAGS) -o $(OUT) $(IN) $(LIBS) diff --git a/ex7/ex7.c b/ex7/ex7.c @@ -1,403 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <time.h> -#include <unistd.h> -#include <string.h> - -#include "ex7.h" -#include "world_map.h" - -/* macros */ -#define FPS (60) -#define SUB_TICK (4) -#define NUM_BLOCK (200) -#define GRAVITY (1000) -#define max(a, b) ((a) > (b) ? (a) : (b)) -#define min(a, b) ((a) < (b) ? (a) : (b)) - -/* -#define COUNT_FPS -*/ - -enum keys { - KEY_D, - 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, -}; -enum next_menu { - START_MENU, - GAME_PLAY, - GAME_OVER, - QUIT, -}; - -/* variables */ -struct Object block[NUM_BLOCK]; -struct Object player; -int player_is_falling; -enum next_menu next_menu = START_MENU; - - -/* function prototypes */ -/* menus */ -void start_menu(void); -void game_play(void); -void game_over(void); -/* events */ -void receive_events(enum key_state[]); -void handle_inputs(enum key_state[]); -/* sort */ -void sort_blocks(int colliding_blocks[], int distance[], int count); - -void -start_menu(void) -{ - char *menu_char_q = "press q to quit."; - char *menu_char_s = "press <space> to start."; - - x_clear_area(); - x_draw_string(0x00FFFF, - WORLD_WIDTH * BLOCK_SIZE/2 - 10 * strlen(menu_char_q)/2, - WORLD_HEIGHT * BLOCK_SIZE/2, - menu_char_q, strlen(menu_char_q)); - x_draw_string(0x00FFFF, - WORLD_WIDTH * BLOCK_SIZE/2 - 10 * strlen(menu_char_s)/2, - WORLD_HEIGHT * BLOCK_SIZE/2 + 20, - menu_char_s, strlen(menu_char_s)); - - while (next_menu == START_MENU) { - char c; - int event = x_next_event(&c); - - switch (event) { - case XEXPOSE: - x_draw_string(0x00FFFF, - WORLD_WIDTH * BLOCK_SIZE/2 - 10 * strlen(menu_char_q)/2, - WORLD_HEIGHT * BLOCK_SIZE/2, - menu_char_q, strlen(menu_char_q)); - x_draw_string(0x00FFFF, - WORLD_WIDTH * BLOCK_SIZE/2 - 10 * strlen(menu_char_s)/2, - WORLD_HEIGHT * BLOCK_SIZE/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; - case ' ': - next_menu = GAME_PLAY; - break; - default: - break; - } - break; - default: - break; - } - } -} - -void -game_play(void) -{ - enum key_state key_state[NUM_KEY]; - long t0, t1, dt; -#ifdef COUNT_FPS - int fps_count = 0; -#endif - struct timespec ts; - - int bi = 0; - for (int i = 0; i < WORLD_WIDTH * WORLD_HEIGHT; i++) { - if (world_map[i] == 'b') { - block[bi].pp.x = block[bi].p.x = i % WORLD_WIDTH * BLOCK_SIZE; - block[bi].pp.y = block[bi].p.y = i / WORLD_WIDTH * BLOCK_SIZE; - block[bi].a.x = 0; - block[bi].a.y = 0; - block[bi].v.x = 0; - block[bi].v.y = 0; - block[bi].body.rectangle.w = BLOCK_SIZE; - block[bi].body.rectangle.h = BLOCK_SIZE; - block[bi].m = block[bi].body.rectangle.w * - block[bi].body.rectangle.h; - bi++; - } else if (world_map[i] == 'p') { - player.pp.x = player.p.x = i % WORLD_WIDTH * BLOCK_SIZE; - player.pp.y = player.p.y = i / WORLD_WIDTH * BLOCK_SIZE; - player.v.x = 0; - player.v.y = 0; - player.a.x = 0; - player.a.y = GRAVITY; - player.body.rectangle.w = player.body.rectangle.h = BLOCK_SIZE; - player.m = player.body.rectangle.w * player.body.rectangle.h; - } - } - - while (next_menu == GAME_PLAY){ - clock_gettime(CLOCK_MONOTONIC, &ts); - t0 = ts.tv_nsec; - receive_events(key_state); - handle_inputs(key_state); - - - clock_gettime(CLOCK_MONOTONIC, &ts); - t0 = ts.tv_nsec; - - for (int k = 0; k < SUB_TICK; k++) { - player_is_falling = object_is_falling(&player, block, NUM_BLOCK); - if (player_is_falling) - player.a.y = GRAVITY; - else - player.a.y = 0; - next_tick(&player, 1e9 / FPS / SUB_TICK); - - // game over when fall out of the screen - if (player.p.y > WORLD_HEIGHT * BLOCK_SIZE) { - next_menu = GAME_OVER; - break; - } - // bind within the world - if (player.p.x < 0) { - player.p.x = 0; - } - if (WORLD_WIDTH * BLOCK_SIZE < player.p.x + - player.body.rectangle.w) { - player.p.x = WORLD_WIDTH * BLOCK_SIZE - - player.body.rectangle.w; - } - - - for (int i = 0; i < NUM_BLOCK; i++) - next_tick(&block[i], 1e9 / FPS / SUB_TICK); - - int colliding_blocks[9]; - int distance[9]; - int j = 0; - for (int i = 0; i < NUM_BLOCK; i++) - if (test_collision(&player, &block[i])) { - colliding_blocks[j] = i; - distance[j] = (player.p.x - block[i].p.x) * - (player.p.x - block[i].p.x) + - (player.p.y - block[i].p.y) * - (player.p.y - block[i].p.y); - j++; - } - sort_blocks(colliding_blocks, distance, j); - for (int i = 0; i < j; i++) - handle_collision_mf(&player, &block[colliding_blocks[i]]); - } - - // fix fps - // TODO: This method create some strange stripe when - // rendered in 60fps on a 60fps monitor. - dt = 0; - while (dt < 1.0 * 1e9 / FPS){ - clock_gettime(CLOCK_MONOTONIC, &ts); - t1 = ts.tv_nsec; - dt = t1 > t0 ? t1 - t0 : t1 - t0 + 1e9; - } -#ifdef COUNT_FPS - // count fps. - fps_count++; - if (t1 < t0){ - printf("fps: %u\n", fps_count); - fps_count = 0; - } -#endif - - x_clear_area(); - for (int i = 0; i < NUM_BLOCK; i++) { - x_draw_rectangle(0x00FF00, - block[i].p.x, block[i].p.y, // position - block[i].body.rectangle.w, - block[i].body.rectangle.h); - } - x_draw_rectangle(0x009FFF, - player.p.x, player.p.y, // position - player.body.rectangle.w, player.body.rectangle.h); - char status_string[128]; - snprintf(status_string, 128, "falling: %d", player_is_falling); - x_draw_string(0x00FFFF, - 0, 20, - status_string, - strlen(status_string)); - } -} - -void -game_over(void) -{ - char *menu_char = "GAME OVER"; - - x_clear_area(); - x_draw_string(0x00FFFF, - WORLD_WIDTH * BLOCK_SIZE/2 - 10 * strlen(menu_char)/2, - WORLD_HEIGHT * BLOCK_SIZE/2, - menu_char, strlen(menu_char)); - x_flush(); - - sleep(1); - next_menu = START_MENU; -} - -void -receive_events(enum key_state key_state[]) -{ - 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': - key_state[KEY_Q] = KEY_DOWN; - 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 XKEYRELEASE: - switch (c) { - case 'q': - key_state[KEY_Q] = KEY_UP; - break; - 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; - } - } -} - -void -handle_inputs(enum key_state key_state[]) -{ - if (key_state[KEY_Q] == KEY_DOWN){ - next_menu = GAME_OVER; - return; - } - if (key_state[KEY_D] == KEY_DOWN) { - if (player.v.x > 0) { - player.a.x = 500; - } else { - player.a.x = 1000; - } - } else if (key_state[KEY_A] == KEY_DOWN) { - if (player.v.x > 0) { - player.a.x = -1000; - } else { - player.a.x = -500; - } - } else { - if (player_is_falling) - player.a.x = -player.v.x; - else - player.a.x = -3 * player.v.x; - } - - if (player.v.x < -200) player.v.x = -200; - if (player.v.x > 200) player.v.x = 200; - /* - if (key_state[KEY_S] == KEY_DOWN) - player.v.y += 300; - if (key_state[KEY_W] == KEY_DOWN) - player.v.y += -300; - */ - if (!player_is_falling && key_state[KEY_SPACE] == KEY_DOWN) - player.v.y = -450; -} - -void -swap(int list[], int i, int j) -{ - int tmp = list[i]; - list[i] = list[j]; - list[j] = tmp; -} - -void -sort_blocks(int colliding_blocks[], int distance[], int count) -{ - for (int i = 0; i < count - 1; i++) { - for (int j = i + 1; j < count; j++) { - if (distance[i] > distance[j]) { - swap(colliding_blocks, i, j); - swap(distance, i, j); - } - } - } -} - - -int -main(void) -{ - x_setup_window(0, 0, - WORLD_WIDTH * BLOCK_SIZE, WORLD_HEIGHT * BLOCK_SIZE, - 0x000000, "UNKO"); - 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; - } - } - - x_clean_up(); - return 0; -} diff --git a/ex7/main.c b/ex7/main.c @@ -0,0 +1,403 @@ +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include <string.h> + +#include "main.h" +#include "world_map.h" + +/* macros */ +#define FPS (60) +#define SUB_TICK (4) +#define NUM_BLOCK (200) +#define GRAVITY (1000) +#define max(a, b) ((a) > (b) ? (a) : (b)) +#define min(a, b) ((a) < (b) ? (a) : (b)) + +/* +#define COUNT_FPS +*/ + +enum keys { + KEY_D, + 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, +}; +enum next_menu { + START_MENU, + GAME_PLAY, + GAME_OVER, + QUIT, +}; + +/* variables */ +struct Object block[NUM_BLOCK]; +struct Object player; +int player_is_falling; +enum next_menu next_menu = START_MENU; + + +/* function prototypes */ +/* menus */ +void start_menu(void); +void game_play(void); +void game_over(void); +/* events */ +void receive_events(enum key_state[]); +void handle_inputs(enum key_state[]); +/* sort */ +void sort_blocks(int colliding_blocks[], int distance[], int count); + +void +start_menu(void) +{ + char *menu_char_q = "press q to quit."; + char *menu_char_s = "press <space> to start."; + + x_clear_area(); + x_draw_string(0x00FFFF, + WORLD_WIDTH * BLOCK_SIZE/2 - 10 * strlen(menu_char_q)/2, + WORLD_HEIGHT * BLOCK_SIZE/2, + menu_char_q, strlen(menu_char_q)); + x_draw_string(0x00FFFF, + WORLD_WIDTH * BLOCK_SIZE/2 - 10 * strlen(menu_char_s)/2, + WORLD_HEIGHT * BLOCK_SIZE/2 + 20, + menu_char_s, strlen(menu_char_s)); + + while (next_menu == START_MENU) { + char c; + int event = x_next_event(&c); + + switch (event) { + case XEXPOSE: + x_draw_string(0x00FFFF, + WORLD_WIDTH * BLOCK_SIZE/2 - 10 * strlen(menu_char_q)/2, + WORLD_HEIGHT * BLOCK_SIZE/2, + menu_char_q, strlen(menu_char_q)); + x_draw_string(0x00FFFF, + WORLD_WIDTH * BLOCK_SIZE/2 - 10 * strlen(menu_char_s)/2, + WORLD_HEIGHT * BLOCK_SIZE/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; + case ' ': + next_menu = GAME_PLAY; + break; + default: + break; + } + break; + default: + break; + } + } +} + +void +game_play(void) +{ + enum key_state key_state[NUM_KEY]; + long t0, t1, dt; +#ifdef COUNT_FPS + int fps_count = 0; +#endif + struct timespec ts; + + int bi = 0; + for (int i = 0; i < WORLD_WIDTH * WORLD_HEIGHT; i++) { + if (world_map[i] == 'b') { + block[bi].pp.x = block[bi].p.x = i % WORLD_WIDTH * BLOCK_SIZE; + block[bi].pp.y = block[bi].p.y = i / WORLD_WIDTH * BLOCK_SIZE; + block[bi].a.x = 0; + block[bi].a.y = 0; + block[bi].v.x = 0; + block[bi].v.y = 0; + block[bi].body.rectangle.w = BLOCK_SIZE; + block[bi].body.rectangle.h = BLOCK_SIZE; + block[bi].m = block[bi].body.rectangle.w * + block[bi].body.rectangle.h; + bi++; + } else if (world_map[i] == 'p') { + player.pp.x = player.p.x = i % WORLD_WIDTH * BLOCK_SIZE; + player.pp.y = player.p.y = i / WORLD_WIDTH * BLOCK_SIZE; + player.v.x = 0; + player.v.y = 0; + player.a.x = 0; + player.a.y = GRAVITY; + player.body.rectangle.w = player.body.rectangle.h = BLOCK_SIZE; + player.m = player.body.rectangle.w * player.body.rectangle.h; + } + } + + while (next_menu == GAME_PLAY){ + clock_gettime(CLOCK_MONOTONIC, &ts); + t0 = ts.tv_nsec; + receive_events(key_state); + handle_inputs(key_state); + + + clock_gettime(CLOCK_MONOTONIC, &ts); + t0 = ts.tv_nsec; + + for (int k = 0; k < SUB_TICK; k++) { + player_is_falling = object_is_falling(&player, block, NUM_BLOCK); + if (player_is_falling) + player.a.y = GRAVITY; + else + player.a.y = 0; + next_tick(&player, 1e9 / FPS / SUB_TICK); + + // game over when fall out of the screen + if (player.p.y > WORLD_HEIGHT * BLOCK_SIZE) { + next_menu = GAME_OVER; + break; + } + // bind within the world + if (player.p.x < 0) { + player.p.x = 0; + } + if (WORLD_WIDTH * BLOCK_SIZE < player.p.x + + player.body.rectangle.w) { + player.p.x = WORLD_WIDTH * BLOCK_SIZE - + player.body.rectangle.w; + } + + + for (int i = 0; i < NUM_BLOCK; i++) + next_tick(&block[i], 1e9 / FPS / SUB_TICK); + + int colliding_blocks[9]; + int distance[9]; + int j = 0; + for (int i = 0; i < NUM_BLOCK; i++) + if (test_collision(&player, &block[i])) { + colliding_blocks[j] = i; + distance[j] = (player.p.x - block[i].p.x) * + (player.p.x - block[i].p.x) + + (player.p.y - block[i].p.y) * + (player.p.y - block[i].p.y); + j++; + } + sort_blocks(colliding_blocks, distance, j); + for (int i = 0; i < j; i++) + handle_collision_mf(&player, &block[colliding_blocks[i]]); + } + + // fix fps + // TODO: This method create some strange stripe when + // rendered in 60fps on a 60fps monitor. + dt = 0; + while (dt < 1.0 * 1e9 / FPS){ + clock_gettime(CLOCK_MONOTONIC, &ts); + t1 = ts.tv_nsec; + dt = t1 > t0 ? t1 - t0 : t1 - t0 + 1e9; + } +#ifdef COUNT_FPS + // count fps. + fps_count++; + if (t1 < t0){ + printf("fps: %u\n", fps_count); + fps_count = 0; + } +#endif + + x_clear_area(); + for (int i = 0; i < NUM_BLOCK; i++) { + x_draw_rectangle(0x00FF00, + block[i].p.x, block[i].p.y, // position + block[i].body.rectangle.w, + block[i].body.rectangle.h); + } + x_draw_rectangle(0x009FFF, + player.p.x, player.p.y, // position + player.body.rectangle.w, player.body.rectangle.h); + char status_string[128]; + snprintf(status_string, 128, "falling: %d", player_is_falling); + x_draw_string(0x00FFFF, + 0, 20, + status_string, + strlen(status_string)); + } +} + +void +game_over(void) +{ + char *menu_char = "GAME OVER"; + + x_clear_area(); + x_draw_string(0x00FFFF, + WORLD_WIDTH * BLOCK_SIZE/2 - 10 * strlen(menu_char)/2, + WORLD_HEIGHT * BLOCK_SIZE/2, + menu_char, strlen(menu_char)); + x_flush(); + + sleep(1); + next_menu = START_MENU; +} + +void +receive_events(enum key_state key_state[]) +{ + 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': + key_state[KEY_Q] = KEY_DOWN; + 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 XKEYRELEASE: + switch (c) { + case 'q': + key_state[KEY_Q] = KEY_UP; + break; + 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; + } + } +} + +void +handle_inputs(enum key_state key_state[]) +{ + if (key_state[KEY_Q] == KEY_DOWN){ + next_menu = GAME_OVER; + return; + } + if (key_state[KEY_D] == KEY_DOWN) { + if (player.v.x > 0) { + player.a.x = 500; + } else { + player.a.x = 1000; + } + } else if (key_state[KEY_A] == KEY_DOWN) { + if (player.v.x > 0) { + player.a.x = -1000; + } else { + player.a.x = -500; + } + } else { + if (player_is_falling) + player.a.x = -player.v.x; + else + player.a.x = -3 * player.v.x; + } + + if (player.v.x < -200) player.v.x = -200; + if (player.v.x > 200) player.v.x = 200; + /* + if (key_state[KEY_S] == KEY_DOWN) + player.v.y += 300; + if (key_state[KEY_W] == KEY_DOWN) + player.v.y += -300; + */ + if (!player_is_falling && key_state[KEY_SPACE] == KEY_DOWN) + player.v.y = -450; +} + +void +swap(int list[], int i, int j) +{ + int tmp = list[i]; + list[i] = list[j]; + list[j] = tmp; +} + +void +sort_blocks(int colliding_blocks[], int distance[], int count) +{ + for (int i = 0; i < count - 1; i++) { + for (int j = i + 1; j < count; j++) { + if (distance[i] > distance[j]) { + swap(colliding_blocks, i, j); + swap(distance, i, j); + } + } + } +} + + +int +main(void) +{ + x_setup_window(0, 0, + WORLD_WIDTH * BLOCK_SIZE, WORLD_HEIGHT * BLOCK_SIZE, + 0x000000, "UNKO"); + 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; + } + } + + x_clean_up(); + return 0; +} diff --git a/ex7/ex7.h b/ex7/main.h diff --git a/ex7/physics.c b/ex7/physics.c @@ -1,6 +1,6 @@ #include <stdio.h> -#include "ex7.h" +#include "main.h" static int test_collision_rr(struct Object *, struct Object *); static void rect_next_tick(struct Object *, long); diff --git a/ex7/x.c b/ex7/x.c @@ -2,7 +2,7 @@ #include <X11/Xlib.h> -#include "ex7.h" +#include "main.h" Display *display; Atom wm_delete_window;