Compare commits
No commits in common. "main" and "wolf" have entirely different histories.
8 changed files with 132 additions and 156 deletions
76
src/camera.c
76
src/camera.c
|
@ -1,76 +0,0 @@
|
|||
#include "camera.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
14
src/camera.h
14
src/camera.h
|
@ -1,14 +0,0 @@
|
|||
#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);
|
||||
|
|
@ -13,7 +13,7 @@ static void signal_handler() {
|
|||
|
||||
int main (void) {
|
||||
Screen screen;
|
||||
init_screen(&screen, 2160, 1440, "Raycaster", 60);
|
||||
init_screen(&screen, 2160, 1440, "Raycaster");
|
||||
|
||||
Camera camera;
|
||||
init_camera(&camera);
|
||||
|
|
12
src/map.h
12
src/map.h
|
@ -2,18 +2,6 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
// #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,
|
||||
|
|
|
@ -3,13 +3,90 @@
|
|||
#include "ray.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
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) {
|
||||
|
@ -26,7 +103,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 = camera->fov * atan(xcam);
|
||||
const float change = fov * atan(xcam);
|
||||
const float theta = camera->angle + change;
|
||||
|
||||
v2 hit_pos;
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "screen.h"
|
||||
#include "camera.h"
|
||||
#include "ray.h"
|
||||
|
||||
typedef struct {
|
||||
v2 pos;
|
||||
float angle;
|
||||
} Camera;
|
||||
|
||||
void init_camera(Camera* camera);
|
||||
void update_camera(Camera* camera, Screen* screeen);
|
||||
|
||||
void render(Screen* screen, const Camera* camera);
|
||||
|
|
70
src/screen.c
70
src/screen.c
|
@ -5,7 +5,10 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define XLIB_ILLEGAL_ACCESS
|
||||
#include <X11/X.h>
|
||||
|
@ -30,8 +33,6 @@ 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() {
|
||||
|
@ -172,6 +173,7 @@ void swapchain_next(Swapchain* swapchain) {
|
|||
next += 1;
|
||||
next %= 3;
|
||||
}
|
||||
|
||||
swapchain->image_current = next;
|
||||
pthread_mutex_unlock(&swapchain->lock);
|
||||
}
|
||||
|
@ -182,54 +184,28 @@ 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);
|
||||
screen->swapchain.image_front = screen->swapchain.image_recent;
|
||||
int index = screen->swapchain.image_recent;
|
||||
screen->swapchain.image_front = index;
|
||||
pthread_mutex_unlock(&screen->swapchain.lock);
|
||||
|
||||
XPutImage(
|
||||
dpy,
|
||||
state->window,
|
||||
state->graphics_ctx,
|
||||
state->images[screen->swapchain.image_front],
|
||||
state->images[index],
|
||||
0, 0, 0, 0,
|
||||
screen->swapchain.width,
|
||||
screen->swapchain.height
|
||||
|
@ -237,6 +213,8 @@ static void* swapchain_thread(void* arg) {
|
|||
XSync(dpy, 0);
|
||||
|
||||
pthread_mutex_unlock(&state->recreate_lock);
|
||||
|
||||
usleep(1000 * 1000 / 60);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -244,7 +222,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, uint16_t update_rate) {
|
||||
void init_screen(struct Screen* screen, uint16_t width, uint16_t height, const char* title) {
|
||||
|
||||
if (dpy == NULL) {
|
||||
init_x();
|
||||
|
@ -255,7 +233,6 @@ 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);
|
||||
|
@ -265,6 +242,23 @@ 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;
|
||||
|
@ -297,11 +291,11 @@ static void handle_event(struct Screen* screen) {
|
|||
}
|
||||
|
||||
bool poll_screen(struct Screen* screen) {
|
||||
|
||||
while (XPending(dpy))
|
||||
handle_event(screen);
|
||||
|
||||
static long last = 0;
|
||||
update_delta(&screen->delta, &last);
|
||||
update_delta(screen);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -326,15 +320,13 @@ void free_screen(struct Screen* screen) {
|
|||
}
|
||||
}
|
||||
|
||||
bool key_pressed(int code) {
|
||||
int keycode = code - dpy->min_keycode;
|
||||
bool key_pressed(int keycode) {
|
||||
if (key_checked[keycode]) return false;
|
||||
if (!key_state[keycode]) return false;
|
||||
key_checked[keycode] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key_down(int code) {
|
||||
int keycode = code - dpy->min_keycode;
|
||||
bool key_down(int keycode) {
|
||||
return key_state[keycode];
|
||||
}
|
||||
|
|
25
src/screen.h
25
src/screen.h
|
@ -2,6 +2,7 @@
|
|||
|
||||
#define _XOPEN_SOURCE 600
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
// #define _POSIX_C_SOURCE 200809L
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
|
@ -28,19 +29,19 @@ struct Screen {
|
|||
|
||||
#define Screen struct Screen
|
||||
|
||||
#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
|
||||
#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
|
||||
|
||||
void init_screen(Screen* screen, uint16_t width, uint16_t height, const char* title, uint16_t update_rate);
|
||||
void init_screen(Screen* screen, uint16_t width, uint16_t height, const char* title);
|
||||
bool poll_screen(Screen* screen);
|
||||
void free_screen(Screen* screen);
|
||||
|
||||
|
|
Loading…
Reference in a new issue