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'.

master
Zed A. Shaw 24 hours ago
parent 75a927e192
commit 96b44a4eb2
  1. 115
      fenscaster.cpp
  2. 34
      matrix.hpp

@ -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) { void ray_casting(Fenster &window, Matrix& map) {
uint8_t color = 255 / (1 + depth * depth * 0.0001); 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;
}
float fixed_depth = depth * std::cos(player_angle - start_angle); if(rayDirY < 0) {
stepY = -1;
sideDistY = (posY - mapY) * deltaDistY;
} else {
stepY = 1;
sideDistY = (mapY + 1.0 - posY) * deltaDistY;
}
float wall_height = 21000 / fixed_depth; // perform DDA
while(hit == 0) {
if(sideDistX < sideDistY) {
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
} else {
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
if(wall_height > window.height()){ if(map[mapY][mapX] > 0) hit = 1;
wall_height = window.height(); }
}
draw_rect(window, if(side == 0) {
{size_t(window.height() + ray * SCALE), perpWallDist = (sideDistX - deltaDistX);
size_t((window.height() / 2) - wall_height / 2)}, } else {
{size_t(SCALE), size_t(wall_height)}, perpWallDist = (sideDistY - deltaDistY);
gray_color(color)); }
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 ray_casting(Fenster &window, Matrix& map) { 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);
} }

@ -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…
Cancel
Save