aboutsummaryrefslogtreecommitdiff
path: root/C++
diff options
context:
space:
mode:
Diffstat (limited to 'C++')
-rw-r--r--C++/3D-Console-Game.cpp198
1 files changed, 198 insertions, 0 deletions
diff --git a/C++/3D-Console-Game.cpp b/C++/3D-Console-Game.cpp
new file mode 100644
index 0000000..d98cb32
--- /dev/null
+++ b/C++/3D-Console-Game.cpp
@@ -0,0 +1,198 @@
+#include <iostream>
+#include <math.h>
+
+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");
+}