diff --git a/src/camera.c b/src/camera.c new file mode 100644 index 0000000..fa2d0e8 --- /dev/null +++ b/src/camera.c @@ -0,0 +1,76 @@ +#include "camera.h" + +#include + +void init_camera(Camera* camera) { + camera->pos.x = 3; + camera->pos.y = 3; + camera->angle = PI / 4; + camera->fov = PI / 4; +} + +#define MOVE_SPEED 1 +#define ROTATE_SPEED PI / 2 +#define FOV_CHANGE_SPEED .5 +#define PLAYER_SIZE .1 + +void update_camera(Camera* camera, Screen* screen) { + double rotate = 0; + + if (key_down(KEY_LEFT)) + rotate -= ROTATE_SPEED; + + if (key_down(KEY_RIGHT)) + rotate += ROTATE_SPEED; + + rotate *= screen->delta; + rotate += camera->angle; + while (rotate >= PI2) rotate -= PI2; + while (rotate < 0) rotate += PI2; + camera->angle = rotate; + + v2 forward = { cos(camera->angle), sin(camera->angle) }; + v2 left = { forward.y, -forward.x }; + v2 move = { 0, 0 }; + + if (key_down(KEY_W)) { + move.x += forward.x; + move.y += forward.y; + } + + if (key_down(KEY_S)) { + move.x -= forward.x; + move.y -= forward.y; + } + + if (key_down(KEY_A)) { + move.x += left.x; + move.y += left.y; + } + + if (key_down(KEY_D)) { + move.x -= left.x; + move.y -= left.y; + } + + if (key_down(KEY_EQUALS)) { + camera->fov += FOV_CHANGE_SPEED * screen->delta; + } + + if (key_down(KEY_MINUS)) { + camera->fov -= FOV_CHANGE_SPEED * screen->delta; + } + + v2 hit_pos; + bool movex, movey; + + cast_ray(camera->pos, sign(move.x) == 1 ? 0 : PI, &hit_pos); + movex = v2_dist(hit_pos, camera->pos) > PLAYER_SIZE; + + cast_ray(camera->pos, sign(move.y) == 1 ? PIH : -PIH, &hit_pos); + movey = v2_dist(hit_pos, camera->pos) > PLAYER_SIZE; + + if (movex) camera->pos.x += move.x * MOVE_SPEED * screen->delta; + if (movey) camera->pos.y += move.y * MOVE_SPEED * screen->delta; +} + diff --git a/src/camera.h b/src/camera.h new file mode 100644 index 0000000..cea1100 --- /dev/null +++ b/src/camera.h @@ -0,0 +1,14 @@ +#pragma once + +#include "screen.h" +#include "ray.h" + +typedef struct { + v2 pos; + float angle; + float fov; +} Camera; + +void init_camera(Camera* camera); +void update_camera(Camera* camera, Screen* screeen); + diff --git a/src/main.c b/src/main.c index d51e6c3..e4872f3 100644 --- a/src/main.c +++ b/src/main.c @@ -13,7 +13,7 @@ static void signal_handler() { int main (void) { Screen screen; - init_screen(&screen, 2160, 1440, "Raycaster"); + init_screen(&screen, 2160, 1440, "Raycaster", 60); Camera camera; init_camera(&camera); diff --git a/src/map.h b/src/map.h index 3e265b2..ecb60ef 100644 --- a/src/map.h +++ b/src/map.h @@ -2,6 +2,18 @@ #include +// #define MAP_SIZE 8 +// static uint8_t MAPDATA[MAP_SIZE * MAP_SIZE] = { +// 1, 1, 1, 1, 1, 1, 1, 1, +// 1, 0, 0, 0, 0, 0, 0, 1, +// 1, 0, 0, 0, 0, 3, 0, 1, +// 1, 0, 0, 0, 0, 0, 0, 1, +// 1, 0, 2, 0, 4, 4, 0, 1, +// 1, 0, 0, 0, 4, 0, 0, 1, +// 1, 0, 3, 0, 0, 0, 0, 1, +// 1, 1, 1, 1, 1, 1, 1, 1, +// }; + #define MAP_SIZE 8 static uint8_t MAPDATA[MAP_SIZE * MAP_SIZE] = { 1, 1, 1, 1, 1, 1, 1, 1, diff --git a/src/renderer.c b/src/renderer.c index 3841583..54d3bd0 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -3,90 +3,13 @@ #include "ray.h" #include -#include #include #include - -void init_camera(Camera* camera) { - camera->pos.x = 3; - camera->pos.y = 3; - camera->angle = PI / 4; -} - -static double fov = PI / 4; - -#define MOVE_SPEED 1 -#define ROTATE_SPEED PI / 2 -#define FOV_CHANGE_SPEED 1 -#define PLAYER_SIZE .1 - - -void update_camera(Camera* camera, Screen* screen) { - double rotate = 0; - - if (key_down(KEY_LEFT)) - rotate -= ROTATE_SPEED; - - if (key_down(KEY_RIGHT)) - rotate += ROTATE_SPEED; - - rotate *= screen->delta; - rotate += camera->angle; - while (rotate >= PI2) rotate -= PI2; - while (rotate < 0) rotate += PI2; - camera->angle = rotate; - - v2 forward = { cos(camera->angle), sin(camera->angle) }; - v2 left = { forward.y, -forward.x }; - v2 move = { 0, 0 }; - - if (key_down(KEY_W)) { - move.x += forward.x; - move.y += forward.y; - } - - if (key_down(KEY_S)) { - move.x -= forward.x; - move.y -= forward.y; - } - - if (key_down(KEY_A)) { - move.x += left.x; - move.y += left.y; - } - - if (key_down(KEY_D)) { - move.x -= left.x; - move.y -= left.y; - } - - if (key_down(KEY_EQUALS)) { - fov += FOV_CHANGE_SPEED * screen->delta; - } - - if (key_down(KEY_MINUS)) { - fov -= FOV_CHANGE_SPEED * screen->delta; - } - - v2 hit_pos; - bool movex, movey; - - cast_ray(camera->pos, sign(move.x) == 1 ? 0 : PI, &hit_pos); - movex = v2_dist(hit_pos, camera->pos) > PLAYER_SIZE; - - cast_ray(camera->pos, sign(move.y) == 1 ? PIH : -PIH, &hit_pos); - movey = v2_dist(hit_pos, camera->pos) > PLAYER_SIZE; - - if (movex) camera->pos.x += move.x * MOVE_SPEED * screen->delta; - if (movey) camera->pos.y += move.y * MOVE_SPEED * screen->delta; -} - static void verline(Swapchain* swapchain, int x, int y0, int y1, uint32_t color) { for (int y = y0; y <= y1; y++) { swapchain->images[swapchain->image_current][(y * swapchain->width) + x] = color; } - } void render(Screen* screen, const Camera* camera) { @@ -103,7 +26,7 @@ void render(Screen* screen, const Camera* camera) { for (int x = 0; x < screen->swapchain.width; x++) { const float xcam = (2 * (x / (float) (swapchain->width))) - 1; - const float change = fov * atan(xcam); + const float change = camera->fov * atan(xcam); const float theta = camera->angle + change; v2 hit_pos; diff --git a/src/renderer.h b/src/renderer.h index 4bbc711..25ea62d 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -1,14 +1,6 @@ #pragma once #include "screen.h" -#include "ray.h" - -typedef struct { - v2 pos; - float angle; -} Camera; - -void init_camera(Camera* camera); -void update_camera(Camera* camera, Screen* screeen); +#include "camera.h" void render(Screen* screen, const Camera* camera); diff --git a/src/screen.c b/src/screen.c index 5e84038..86d829d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -5,10 +5,7 @@ #include #include #include -#include #include -#include -#include #define XLIB_ILLEGAL_ACCESS #include @@ -33,6 +30,8 @@ typedef struct { XImage** images; pthread_t update_thread; pthread_mutex_t recreate_lock; + pthread_mutex_t lock; + uint16_t update_rate; } WindowState; static void init_x() { @@ -173,7 +172,6 @@ void swapchain_next(Swapchain* swapchain) { next += 1; next %= 3; } - swapchain->image_current = next; pthread_mutex_unlock(&swapchain->lock); } @@ -184,28 +182,54 @@ void swapchain_submit(Swapchain* swapchain) { pthread_mutex_unlock(&swapchain->lock); } +static long get_time() { + struct timespec spec; + clock_gettime(CLOCK_MONOTONIC, &spec); + return round(spec.tv_nsec / 1.0e6) + spec.tv_sec * 1000; +} + +static void update_delta(float* delta, long* last) { + long now = get_time(); + if (*last == 0) { + *delta = 0; + } else { + *delta = (now - *last) / 1000.0; + } + *last = now; +} + static void* swapchain_thread(void* arg) { struct Screen* screen = (struct Screen*) arg; WindowState* state = (WindowState*) screen->internal; + long last = get_time(); + float delta; + while (1) { if (screen->swapchain.images == NULL) { return NULL; } + + long now = last; + update_delta(&delta, &now); + if (delta < 1.0 / state->update_rate) { + continue; + } else { + last = now; + } pthread_mutex_lock(&state->recreate_lock); pthread_mutex_lock(&screen->swapchain.lock); - int index = screen->swapchain.image_recent; - screen->swapchain.image_front = index; + screen->swapchain.image_front = screen->swapchain.image_recent; pthread_mutex_unlock(&screen->swapchain.lock); XPutImage( dpy, state->window, state->graphics_ctx, - state->images[index], + state->images[screen->swapchain.image_front], 0, 0, 0, 0, screen->swapchain.width, screen->swapchain.height @@ -213,8 +237,6 @@ static void* swapchain_thread(void* arg) { XSync(dpy, 0); pthread_mutex_unlock(&state->recreate_lock); - - usleep(1000 * 1000 / 60); } return NULL; @@ -222,7 +244,7 @@ static void* swapchain_thread(void* arg) { #define FRAMES 3 -void init_screen(struct Screen* screen, uint16_t width, uint16_t height, const char* title) { +void init_screen(struct Screen* screen, uint16_t width, uint16_t height, const char* title, uint16_t update_rate) { if (dpy == NULL) { init_x(); @@ -233,6 +255,7 @@ void init_screen(struct Screen* screen, uint16_t width, uint16_t height, const c WindowState* state = malloc(sizeof(WindowState)); state->window = window; + state->update_rate = update_rate; screen->swapchain = create_swapchain(width, height, FRAMES, bit_depth, state); pthread_create(&state->update_thread, NULL, &swapchain_thread, screen); @@ -242,23 +265,6 @@ void init_screen(struct Screen* screen, uint16_t width, uint16_t height, const c count++; } -static long get_time() { - struct timespec spec; - clock_gettime(CLOCK_MONOTONIC, &spec); - return round(spec.tv_nsec / 1.0e6) + spec.tv_sec * 1000; -} - -static long last = 0; - -static void update_delta(struct Screen* screen) { - long now = get_time(); - if (last == 0) { - screen->delta = 0; - } else { - screen->delta = (now - last) / 1000.0; - } - last = now; -} static void handle_event(struct Screen* screen) { XEvent event; @@ -291,11 +297,11 @@ static void handle_event(struct Screen* screen) { } bool poll_screen(struct Screen* screen) { - while (XPending(dpy)) handle_event(screen); - update_delta(screen); + static long last = 0; + update_delta(&screen->delta, &last); return true; } @@ -320,13 +326,15 @@ void free_screen(struct Screen* screen) { } } -bool key_pressed(int keycode) { +bool key_pressed(int code) { + int keycode = code - dpy->min_keycode; if (key_checked[keycode]) return false; if (!key_state[keycode]) return false; key_checked[keycode] = true; return true; } -bool key_down(int keycode) { +bool key_down(int code) { + int keycode = code - dpy->min_keycode; return key_state[keycode]; } diff --git a/src/screen.h b/src/screen.h index 423af7e..23094bb 100644 --- a/src/screen.h +++ b/src/screen.h @@ -2,7 +2,6 @@ #define _XOPEN_SOURCE 600 #define _POSIX_C_SOURCE 200112L -// #define _POSIX_C_SOURCE 200809L #include #include #include @@ -29,19 +28,19 @@ struct Screen { #define Screen struct Screen -#define KEY_W 17 -#define KEY_A 30 -#define KEY_S 31 -#define KEY_D 32 -#define KEY_UP 103 -#define KEY_DOWN 108 -#define KEY_LEFT 105 -#define KEY_RIGHT 106 -#define KEY_MINUS 12 -#define KEY_EQUALS 13 -#define KEY_ESC 1 +#define KEY_W 25 +#define KEY_A 38 +#define KEY_S 39 +#define KEY_D 40 +#define KEY_UP 111 +#define KEY_DOWN 116 +#define KEY_LEFT 113 +#define KEY_RIGHT 114 +#define KEY_MINUS 20 +#define KEY_EQUALS 21 +#define KEY_ESC 9 -void init_screen(Screen* screen, uint16_t width, uint16_t height, const char* title); +void init_screen(Screen* screen, uint16_t width, uint16_t height, const char* title, uint16_t update_rate); bool poll_screen(Screen* screen); void free_screen(Screen* screen);