#include "renderer.h" #include "screen.h" #include "ray.h" #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_pressed(screen, SDL_SCANCODE_LEFT)) rotate -= ROTATE_SPEED; if (key_pressed(screen, SDL_SCANCODE_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_pressed(screen, SDL_SCANCODE_W)) { move.x += forward.x; move.y += forward.y; } if (key_pressed(screen, SDL_SCANCODE_S)) { move.x -= forward.x; move.y -= forward.y; } if (key_pressed(screen, SDL_SCANCODE_A)) { move.x += left.x; move.y += left.y; } if (key_pressed(screen, SDL_SCANCODE_D)) { move.x -= left.x; move.y -= left.y; } if (key_pressed(screen, SDL_SCANCODE_EQUALS)) { fov += FOV_CHANGE_SPEED * screen->delta; } if (key_pressed(screen, SDL_SCANCODE_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(Screen* screen, int x, int y0, int y1, uint32_t color) { for (int y = y0; y <= y1; y++) { screen->pixels[(y * screen->width) + x] = color; } } void render(Screen* screen, const Camera* camera) { const v2 cam_right = { -sin(camera->angle), cos(camera->angle) }; for (int x = 0; x < screen->width; x++) { const float xcam = (2 * (x / (float) (screen->width))) - 1; const float change = fov * atan(xcam); const float theta = camera->angle + change; v2 hit_pos; uint32_t hit = cast_ray(camera->pos, theta, &hit_pos); hit_pos.x -= camera->pos.x; hit_pos.y -= camera->pos.y; float len = v2_cross(hit_pos, cam_right) / v2_len(cam_right); uint32_t color; switch (hit) { case 1: color = 0xFF0000FF; break; case 2: color = 0x00FF00FF; break; case 3: color = 0x0000FFFF; break; case 4: color = 0xFF00FFFF; break; case 5: color = 0x00FFFFFF; break; default: color = 0x000000FF; break; } const int h = (int) (screen->height / len), y0 = max((screen->height / 2) - (h / 2), 0), y1 = min((screen->height / 2) + (h / 2), screen->height - 1); verline(screen, x, 0, y0, 0x202020FF); verline(screen, x, y0, y1, color); verline(screen, x, y1, screen->height - 1, 0x505050FF); } }