107 lines
2.1 KiB
C
107 lines
2.1 KiB
C
|
#include "ray.h"
|
||
|
#include "map.h"
|
||
|
|
||
|
#include <math.h>
|
||
|
|
||
|
float v2_cross(v2 a, v2 b) {
|
||
|
return fabs(a.x * b.y - a.y * b.x);
|
||
|
}
|
||
|
|
||
|
float v2_len(v2 a) {
|
||
|
return sqrt(a.x * a.x + a.y * a.y);
|
||
|
}
|
||
|
|
||
|
float v2_square_dist(v2 a, v2 b) {
|
||
|
return pow(a.x - b.x, 2) + pow(a.y - b.y, 2);
|
||
|
}
|
||
|
|
||
|
#define PI 3.14159265358979323846
|
||
|
#define PIH 1.57079632679489661923
|
||
|
#define PI2 6.28318530718
|
||
|
|
||
|
uint32_t cast_ray(v2 pos, float theta, v2* hit_pos) {
|
||
|
|
||
|
const v2i move = {
|
||
|
#define sign(a) ((a) < 0 ? -1 : 1)
|
||
|
sign(cos(theta)),
|
||
|
sign(sin(theta)),
|
||
|
};
|
||
|
|
||
|
const v2i offset = {
|
||
|
move.x == -1 ? 1 : 0,
|
||
|
move.y == -1 ? 1 : 0
|
||
|
};
|
||
|
|
||
|
const float tanc = tan(theta);
|
||
|
const float cotc = tan(PIH - (theta));
|
||
|
|
||
|
v2i posi = {
|
||
|
(int)pos.x + offset.x,
|
||
|
(int)pos.y + offset.y
|
||
|
};
|
||
|
|
||
|
bool fx = false;
|
||
|
uint32_t vx = 0;
|
||
|
float x;
|
||
|
|
||
|
while (!fx) {
|
||
|
posi.y += move.y;
|
||
|
x = cotc * (posi.y - pos.y) + pos.x;
|
||
|
|
||
|
if (fabs(x) - pos.x >= MAP_SIZE) break;
|
||
|
|
||
|
vx = value((int)x, posi.y - offset.y);
|
||
|
|
||
|
if (vx != 0) {
|
||
|
fx = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool fy = false;
|
||
|
uint32_t vy = 0;
|
||
|
float y;
|
||
|
|
||
|
while (!fy) {
|
||
|
posi.x += move.x;
|
||
|
y = tanc * (posi.x - pos.x) + pos.y;
|
||
|
|
||
|
if (fabs(y) - pos.y >= MAP_SIZE) break;
|
||
|
|
||
|
vy = value(posi.x - offset.x, (int)y);
|
||
|
|
||
|
if (vy != 0) {
|
||
|
fy = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uint32_t hit;
|
||
|
if (!fx && !fy) {
|
||
|
hit = 0;
|
||
|
hit_pos->x = pos.x + 1000 * move.x;
|
||
|
hit_pos->y = pos.y + 1000 * move.y;
|
||
|
return false;
|
||
|
} else if (fx && !fy) {
|
||
|
hit = vx;
|
||
|
hit_pos->x = x;
|
||
|
hit_pos->y = posi.y;
|
||
|
} else if (fy && !fx) {
|
||
|
hit = vy;
|
||
|
hit_pos->x = posi.x;
|
||
|
hit_pos->y = y;
|
||
|
} else {
|
||
|
const v2 posx = {x, posi.y};
|
||
|
const v2 posy = {posi.x, y};
|
||
|
if (v2_square_dist(posx, pos) < v2_square_dist(posy, pos)) {
|
||
|
hit = vx;
|
||
|
hit_pos->x = x;
|
||
|
hit_pos->y = posi.y;
|
||
|
} else {
|
||
|
hit = vy;
|
||
|
hit_pos->x = posi.x;
|
||
|
hit_pos->y= y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hit;
|
||
|
}
|