#include #include const int mapSize = 7; const float wallHeight = 1; char map[mapSize][mapSize] = { { '0', '9', '8', '7', 'M', 'P', 'O' }, // 0 { '-', ' ', ' ', ' ', ' ', ' ', '3' }, // 1 { '=', ' ', ' ', ' ', 'o', ' ', '2' }, // 2 { '|', ' ', ' ', ' ', ' ', ' ', '1' }, // 3 { '=', ' ', ' ', ' ', ' ', ' ', '2' }, // 4 { '-', ' ', ' ', '0', ' ', ' ', '3' }, // 5 { '0', '9', '8', '7', '6', '5', '0' }, // 6 // 0 1 2 3 4 5 6 }; struct Coord { float x; float y; }; float dist(Coord c1, Coord c2) { float x1 = c2.x - c1.x, y1 = c2.y - c1.y; return sqrt(x1 * x1 + y1*y1); } bool isValidCoord(float coord) { return 0 <= coord && coord <= mapSize; } bool isValidCoord(Coord c) { return isValidCoord(c.x) && isValidCoord(c.y); } const float focalLength = 3.4; class Player { Coord loc; float lookingAngle = 0.0; float height = 0.6; int fov = 90; public: Player() : Player(0, 0) {} Player(float x, float y) { this->loc = { x, y }; } float get_height() const { return height; } const Coord& get_loc() const { return loc; } int get_fov() const { return fov; } float get_lookingAngle() const { return lookingAngle; } void walkForward() { if (isValidCoord(loc.x + 0.25)) loc.x += 0.25; } void walkBackward() { if (isValidCoord(loc.x - 0.25)) loc.x -= 0.25; } void walkLeft() { if (isValidCoord(loc.y - 0.25)) loc.y -= 0.25; } void walkRight() { if (isValidCoord(loc.y + 0.25)) loc.y += 0.25; } void lookLeft() { if (lookingAngle == -180) lookingAngle = 180; else lookingAngle -= 2; } void lookRight() { if (lookingAngle == 180) lookingAngle = -180; else lookingAngle += 2; } Coord castRayFromEyes() const { return castRayFromEyes(0); } Coord castRayFromEyes(float angle) const { Coord rayLoc = loc; angle += lookingAngle; float xOffset = cos(angle * M_PI / 180.0), yOffset = sin(angle * M_PI / 180.0); while (rayLoc.x < mapSize && rayLoc.y < mapSize && rayLoc.x > -1 && rayLoc.y > -1 && map[(int)rayLoc.y][(int)rayLoc.x] == ' ') { rayLoc.x += 0.25 * xOffset; rayLoc.y += 0.25 * yOffset; } std::cout << rayLoc.x << " " << rayLoc.y << std::endl; return rayLoc; } }; const int scrH = 200, scrW = 800; // const int scrH = 20, scrW = 80; struct VerticalSlice { Coord collision; float collisionDistance; int aboveRay; int belowRay; VerticalSlice() = default; VerticalSlice(float topScr, float botScr, float plHeight, float angle, Coord plLoc, Coord objLoc) { collision = objLoc; float aboveHeight = wallHeight - plHeight; float belowHeight = plHeight; float properFL = focalLength; this->collisionDistance = dist(plLoc, objLoc); this->aboveRay = ((aboveHeight * properFL) / collisionDistance) * topScr; this->belowRay = ((belowHeight * properFL) / collisionDistance) * botScr; } }; char getDepthChar(float distance) { if (distance >= 6) return ' '; else if (distance >= 5) return '.'; else if (distance >= 4) return ';'; else if (distance >= 3) return '+'; else if (distance >= 2) return '*'; else if (distance >= 1) return '#'; else return 'O'; } void draw(Player& pl) { float topScr = scrH * (wallHeight - pl.get_height()), botScr = scrH - topScr; VerticalSlice slices[pl.get_fov()]; int halfFov = pl.get_fov() / 2; for (int i = -halfFov; i <= halfFov; i++) { slices[i + halfFov] = VerticalSlice(topScr, botScr, pl.get_height(), i, pl.get_loc(), pl.castRayFromEyes(i)); } // return; float angleStep = pl.get_fov() / (float)scrW; for (int row = 0; row < scrH; row++) { for (int dot = 0; dot < scrW; dot++) { VerticalSlice sl = slices[(int)(dot * angleStep)]; if (row < topScr && topScr - row <= sl.aboveRay) std::cout << getDepthChar(sl.collisionDistance); else if (row >= topScr && row - topScr < sl.belowRay) std::cout << getDepthChar(sl.collisionDistance); else std::cout << ' '; } std::cout << std::endl; } } int main() { Player pl(1, 3); char buffer; bool play = true; system("stty -echo"); system("stty cbreak"); while (play) { std::cout << u8"\033[2J\033[1;1H"; // clear draw(pl); buffer = getchar(); switch (buffer) { case 'w': pl.walkForward(); break; case 's': pl.walkBackward(); break; case 'a': pl.walkLeft(); break; case 'd': pl.walkRight(); break; case ',': pl.lookLeft(); break; case '.': pl.lookRight(); break; case 'x': play = false; break; } for (int i = 0; i < 1000;i++){} } system("stty echo"); system("stty -cbreak"); }