Fenscaster is now using the first version of Lode's DDA raycasting algorithm but the coordinates/angles in the left map view don't matchthe right view, and the right view distorts the distance to far wall so they're viewed at 'infinity'.
This commit is contained in:
parent
75a927e192
commit
96b44a4eb2
2 changed files with 132 additions and 29 deletions
127
fenscaster.cpp
127
fenscaster.cpp
|
@ -78,7 +78,7 @@ void draw_map(Fenster &window, Matrix &map) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_line(Fenster &window, Point start, Point end) {
|
void draw_line(Fenster &window, Point start, Point end, uint32_t color) {
|
||||||
int x = int(start.x);
|
int x = int(start.x);
|
||||||
int y = int(start.y);
|
int y = int(start.y);
|
||||||
int x1 = int(end.x);
|
int x1 = int(end.x);
|
||||||
|
@ -102,7 +102,7 @@ void draw_line(Fenster &window, Point start, Point end) {
|
||||||
y = y + sy;
|
y = y + sy;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.px(x, y) = rgba_color(200, 20, 20, 255);
|
window.px(x, y) = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,29 +116,110 @@ void clear(Fenster &window) {
|
||||||
|
|
||||||
void draw_map_rays(Fenster &window, int col, int row, Point target) {
|
void draw_map_rays(Fenster &window, int col, int row, Point target) {
|
||||||
draw_map_rect(window, col, row, rgba_color(100, 20, 20, 255));
|
draw_map_rect(window, col, row, rgba_color(100, 20, 20, 255));
|
||||||
draw_line(window, {size_t(player_x), size_t(player_y)}, target);
|
draw_line(window, {size_t(player_x), size_t(player_y)}, target, rgba_color(200, 20, 20, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_3d_view(Fenster &window, int depth, float start_angle, int ray) {
|
|
||||||
uint8_t color = 255 / (1 + depth * depth * 0.0001);
|
|
||||||
|
|
||||||
float fixed_depth = depth * std::cos(player_angle - start_angle);
|
|
||||||
|
|
||||||
float wall_height = 21000 / fixed_depth;
|
|
||||||
|
|
||||||
if(wall_height > window.height()){
|
|
||||||
wall_height = window.height();
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_rect(window,
|
|
||||||
{size_t(window.height() + ray * SCALE),
|
|
||||||
size_t((window.height() / 2) - wall_height / 2)},
|
|
||||||
{size_t(SCALE), size_t(wall_height)},
|
|
||||||
gray_color(color));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ray_casting(Fenster &window, Matrix& map) {
|
void ray_casting(Fenster &window, Matrix& map) {
|
||||||
|
int w = THREED_VIEW_WIDTH;
|
||||||
|
int h = THREED_VIEW_HEIGHT;
|
||||||
|
|
||||||
|
// x and y start position
|
||||||
|
double posX = player_x / TILE_SIZE;
|
||||||
|
double posY = player_y / TILE_SIZE;
|
||||||
|
|
||||||
|
// initial direction vector
|
||||||
|
double dirX = std::cos(player_angle);
|
||||||
|
double dirY = 0;
|
||||||
|
|
||||||
|
// the 2d raycaster version of camera plane
|
||||||
|
double planeX = 0;
|
||||||
|
double planeY = 0.66;
|
||||||
|
|
||||||
|
// time of current frame
|
||||||
|
double time = 0;
|
||||||
|
// time of previous frame
|
||||||
|
double oldTime = 0;
|
||||||
|
|
||||||
|
for(int x = 0; x < w; x++) {
|
||||||
|
// calculate ray position and direction
|
||||||
|
double cameraX = 2 * x / double(w) - 1; // x-coord in camera space
|
||||||
|
double rayDirX = dirX + planeX * cameraX;
|
||||||
|
double rayDirY = dirY + planeY * cameraX;
|
||||||
|
|
||||||
|
// which box of the map we're in
|
||||||
|
int mapX = int(posX);
|
||||||
|
int mapY = int(posY);
|
||||||
|
|
||||||
|
// length of ray from current pos to next x or y-side
|
||||||
|
double sideDistX;
|
||||||
|
double sideDistY;
|
||||||
|
|
||||||
|
// length of ray from one x or y-side to next x or y-side
|
||||||
|
double deltaDistX = (rayDirX == 0) ? 1e30 : std::abs(1.0 / rayDirX);
|
||||||
|
double deltaDistY = (rayDirY == 0) ? 1e30 : std::abs(1.0 / rayDirY);
|
||||||
|
double perpWallDist;
|
||||||
|
|
||||||
|
int stepX = 0;
|
||||||
|
int stepY = 0;
|
||||||
|
int hit = 0;
|
||||||
|
int side = 0;
|
||||||
|
|
||||||
|
// calculate step and initial sideDist
|
||||||
|
if(rayDirX < 0) {
|
||||||
|
stepX = -1;
|
||||||
|
sideDistX = (posX - mapX) * deltaDistX;
|
||||||
|
} else {
|
||||||
|
stepX = 1;
|
||||||
|
sideDistX = (mapX + 1.0 - posX) * deltaDistX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rayDirY < 0) {
|
||||||
|
stepY = -1;
|
||||||
|
sideDistY = (posY - mapY) * deltaDistY;
|
||||||
|
} else {
|
||||||
|
stepY = 1;
|
||||||
|
sideDistY = (mapY + 1.0 - posY) * deltaDistY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform DDA
|
||||||
|
while(hit == 0) {
|
||||||
|
if(sideDistX < sideDistY) {
|
||||||
|
sideDistX += deltaDistX;
|
||||||
|
mapX += stepX;
|
||||||
|
side = 0;
|
||||||
|
} else {
|
||||||
|
sideDistY += deltaDistY;
|
||||||
|
mapY += stepY;
|
||||||
|
side = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(map[mapY][mapX] > 0) hit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(side == 0) {
|
||||||
|
perpWallDist = (sideDistX - deltaDistX);
|
||||||
|
} else {
|
||||||
|
perpWallDist = (sideDistY - deltaDistY);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lineHeight = int(h / perpWallDist);
|
||||||
|
|
||||||
|
int drawStart = -lineHeight / 2 + h / 2;
|
||||||
|
if(drawStart < 0) drawStart = 0;
|
||||||
|
|
||||||
|
int drawEnd = lineHeight / 2 + h / 2;
|
||||||
|
if(drawEnd >= h) drawEnd = h - 1;
|
||||||
|
|
||||||
|
uint32_t color = gray_color(std::min(lineHeight, 255));
|
||||||
|
|
||||||
|
draw_line(window,
|
||||||
|
{size_t(x + THREED_VIEW_WIDTH), size_t(drawStart)},
|
||||||
|
{size_t(x + THREED_VIEW_WIDTH), size_t(drawEnd)}, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void map_view_casting(Fenster &window, Matrix& map) {
|
||||||
float start_angle = player_angle - HALF_FOV;
|
float start_angle = player_angle - HALF_FOV;
|
||||||
|
|
||||||
for(int ray = 0; ray < CASTED_RAYS; ray++, start_angle += STEP_ANGLE)
|
for(int ray = 0; ray < CASTED_RAYS; ray++, start_angle += STEP_ANGLE)
|
||||||
|
@ -152,7 +233,6 @@ void ray_casting(Fenster &window, Matrix& map) {
|
||||||
|
|
||||||
if(map[row][col] == 1) {
|
if(map[row][col] == 1) {
|
||||||
draw_map_rays(window, col, row, {size_t(target_x), size_t(target_y)});
|
draw_map_rays(window, col, row, {size_t(target_x), size_t(target_y)});
|
||||||
draw_3d_view(window, depth, start_angle, ray);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,6 +254,7 @@ void draw_everything(Fenster &window) {
|
||||||
clear(window);
|
clear(window);
|
||||||
draw_map(window, MAP);
|
draw_map(window, MAP);
|
||||||
draw_ceiling_floor(window);
|
draw_ceiling_floor(window);
|
||||||
|
map_view_casting(window, MAP);
|
||||||
ray_casting(window, MAP);
|
ray_casting(window, MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
matrix.hpp
34
matrix.hpp
|
@ -10,8 +10,15 @@ namespace matrix {
|
||||||
using std::vector, std::queue, std::array;
|
using std::vector, std::queue, std::array;
|
||||||
using std::min, std::max, std::floor;
|
using std::min, std::max, std::floor;
|
||||||
|
|
||||||
typedef vector<int> Row;
|
template<typename T>
|
||||||
typedef vector<Row> Matrix;
|
using BaseRow = vector<T>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using Base = vector<BaseRow<T>>;
|
||||||
|
|
||||||
|
using Row = vector<int>;
|
||||||
|
using Matrix = vector<Row>;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Just a quick thing to reset a matrix to a value.
|
* Just a quick thing to reset a matrix to a value.
|
||||||
|
@ -40,6 +47,17 @@ namespace matrix {
|
||||||
return mat.size();
|
return mat.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline Base<T> make_base(size_t width, size_t height) {
|
||||||
|
Base<T> result(height, BaseRow<T>(width));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Matrix make(size_t width, size_t height) {
|
||||||
|
Matrix result(height, Row(width));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
inline size_t next_x(size_t x, size_t width) {
|
inline size_t next_x(size_t x, size_t width) {
|
||||||
return (x + 1) * ((x + 1) < width);
|
return (x + 1) * ((x + 1) < width);
|
||||||
}
|
}
|
||||||
|
@ -150,6 +168,10 @@ namespace matrix {
|
||||||
size_t bottom = 0;
|
size_t bottom = 0;
|
||||||
|
|
||||||
box_t(MAT &mat, size_t at_x, size_t at_y, size_t size) :
|
box_t(MAT &mat, size_t at_x, size_t at_y, size_t size) :
|
||||||
|
box_t(mat, at_x, at_y, size, size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
box_t(MAT &mat, size_t at_x, size_t at_y, size_t width, size_t height) :
|
||||||
from_x(at_x), from_y(at_y)
|
from_x(at_x), from_y(at_y)
|
||||||
{
|
{
|
||||||
size_t h = matrix::height(mat);
|
size_t h = matrix::height(mat);
|
||||||
|
@ -157,15 +179,15 @@ namespace matrix {
|
||||||
|
|
||||||
// keeps it from going below zero
|
// keeps it from going below zero
|
||||||
// need extra -1 to compensate for the first next()
|
// need extra -1 to compensate for the first next()
|
||||||
left = max(from_x, size) - size;
|
left = max(from_x, width) - width;
|
||||||
x = left - 1; // must be -1 for next()
|
x = left - 1; // must be -1 for next()
|
||||||
// keeps it from going above width
|
// keeps it from going above width
|
||||||
right = min(from_x + size + 1, w);
|
right = min(from_x + width + 1, w);
|
||||||
|
|
||||||
// same for these two
|
// same for these two
|
||||||
top = max(from_y, size) - size;
|
top = max(from_y, height) - height;
|
||||||
y = top - (left == 0);
|
y = top - (left == 0);
|
||||||
bottom = min(from_y + size + 1, h);
|
bottom = min(from_y + height + 1, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool next() {
|
bool next() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue