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 3 months ago
parent 75a927e192
commit 96b44a4eb2
  1. 113
      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