1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include "renderer.h"
#include "screen.h"
#include "ray.h"
#include <math.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_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);
}
}
|