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
129
130
131
132
|
#include "renderer.h"
#include "screen.h"
#include "ray.h"
#include <math.h>
#define PI 3.14159265358979323846
#define PIH 1.57079632679489661923
#define PI2 6.28318530718
void init_camera(Camera* camera) {
camera->x = 3;
camera->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
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;
}
camera->x += move.x * MOVE_SPEED * screen->delta;
camera->y += move.y * MOVE_SPEED * screen->delta;
}
v2 get_cam_right(const Camera* camera) {
v2 cam_right = {
-sin(camera->angle),
cos(camera->angle)
};
return cam_right;
}
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;
}
}
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
void render(Screen* screen, const Camera* camera) {
const v2 pos = {
camera->x,
camera->y
};
const v2 cam_right = get_cam_right(camera);
for (int sx = 0; sx < screen->width; sx++) {
const float xcam = (2 * (sx / (float) (screen->width))) - 1;
const float change = fov * atan(xcam);
const float theta = camera->angle + change;
v2 hit_pos;
uint32_t hit = cast_ray(pos, theta, &hit_pos);
hit_pos.x -= pos.x;
hit_pos.y -= 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, sx, 0, y0, 0x202020FF);
verline(screen, sx, y0, y1, color);
verline(screen, sx, y1, screen->height - 1, 0x505050FF);
}
}
|