diff --git a/World.cpp b/World.cpp index 1ca062c..f632b86 100644 --- a/World.cpp +++ b/World.cpp @@ -6,9 +6,8 @@ #include -World::World(int w, int h, sf::Color groundColor, sf::Color ceilingColor, std::vector worldMap) : - player(0,0,0), w(w), h(h), map(std::move(worldMap)), - groundColor(groundColor), ceilingColor(ceilingColor) +World::World(int w, int h, sf::Color groundColor, sf::Color ceilingColor, std::vector worldMap) : w(w), h(h), + groundColor(groundColor), ceilingColor(ceilingColor), map(std::move(worldMap)), player(0,0,0) { map.resize(w*h,BlockType::WALL); } @@ -23,14 +22,9 @@ int World::getH() const return h; } -BlockType World::getBlock(int x, int y) const -{ - return map[x + w*y]; -} - BlockType World::getBlock(float x, float y) const { - return map[static_cast(x) + w*static_cast(y)]; + return(map.at(static_cast(x)+w* static_cast(y))); } void World::setBlock(BlockType block, int x, int y, int width, int height) @@ -89,6 +83,16 @@ std::ostream& operator<<(std::ostream& ostream, World const& world) return(ostream); } +void World::fillColumn(sf::RenderWindow& window, int column, float scale, sf::Color wallColor) const +{ + float columnHeight = window.getSize().y*scale; + sf::RectangleShape pixelColumn(sf::Vector2f(1,columnHeight)); + pixelColumn.setPosition(column,(window.getSize().y-columnHeight)/2.0); + pixelColumn.setFillColor(wallColor); + + window.draw(pixelColumn); +} + float World::castRay(float originX, float originY, float orientation) const { /* @@ -165,8 +169,7 @@ float World::castRay(float originX, float originY, float orientation) const float hCheckX = originX + hOffsetX; float hCheckY = hOffsetY; /* Bounds + sanity check. */ - while (hCheckX >= 0 && hCheckX <= static_cast(w) && - hCheckY >= 0 && hCheckY <= static_cast(h) && i < h) { + while (hCheckX >= 0 && hCheckX <= w && hCheckY >= 0 && hCheckY <= h && i < h) { if (getBlock(floorf(hCheckX), floorf(hCheckY) + hRound) == BlockType::WALL) { break; } @@ -181,8 +184,7 @@ float World::castRay(float originX, float originY, float orientation) const float vCheckY = originY + vOffsetY; /* Bounds + sanity check. */ - while (vCheckX >= 0 && vCheckX < static_cast(w) && - vCheckY >= 0 && vCheckY < static_cast(h) && i < w) { + while (vCheckX >= 0 && vCheckX < w && vCheckY >= 0 && vCheckY < h && i < w) { if (getBlock(floorf(vCheckX) + vRound, floorf(vCheckY)) == BlockType::WALL) { break; } @@ -200,36 +202,24 @@ float World::castRay(float originX, float originY, float orientation) const (originY - hCheckY)*(originY - hCheckY)); float vDist = sqrtf((originX - vCheckX)*(originX - vCheckX) + (originY - vCheckY)*(originY - vCheckY)); + float finalDist = hDist > vDist ? vDist : hDist; - return hDist > vDist ? vDist : hDist; -} - -void World::fillColumn(sf::RenderWindow& window, unsigned int column, - float scale, sf::Color wallColor) const -{ - float columnHeight = static_cast(window.getSize().y)*scale; - sf::RectangleShape pixelColumn(sf::Vector2f(1,columnHeight)); - pixelColumn.setPosition(static_cast(column), - (static_cast(window.getSize().y)-columnHeight)/2.0f); - pixelColumn.setFillColor(wallColor); - - window.draw(pixelColumn); + /* 2 Is wall height in meters. */ + return player.focalLength*2/finalDist; } void World::render(sf::RenderWindow& window) const { - float windowX = static_cast(window.getSize().x); - float windowY = static_cast(window.getSize().y); /* * Draw ground and sky planes through half of the screen, as the walls * will get drawn over them. * This doesn't work if we support textures/levels. */ - sf::RectangleShape ground = sf::RectangleShape(sf::Vector2f(windowX,windowY/2.0f)); + sf::RectangleShape ground = sf::RectangleShape(sf::Vector2f(window.getSize().x,window.getSize().y/2.0)); ground.setFillColor(groundColor); - ground.setPosition(0,windowY/2.0f); + ground.setPosition(0,window.getSize().y/2.0); - sf::RectangleShape ceiling = sf::RectangleShape(sf::Vector2f(windowX,windowY/2.0f)); + sf::RectangleShape ceiling = sf::RectangleShape(sf::Vector2f(window.getSize().x,window.getSize().y/2.0)); ceiling.setFillColor(ceilingColor); window.draw(ground); @@ -239,17 +229,16 @@ void World::render(sf::RenderWindow& window) const * Throw rays and draw walls over the ceiling and ground. * Only throws in the plane, which doesn't work for levels/3D. */ - for(unsigned int i = 0 ; i < window.getSize().x ; i++) + for(int i = 0;i(i)-windowX/2.0f); + float deltaAngle = (player.fov/window.getSize().x) * (i-window.getSize().x/2.0); float rayAngle = player.orientation + deltaAngle; if (rayAngle < 0) { rayAngle += 360; } else if (rayAngle > 360) { rayAngle -= 360; } - float obstacleScale = player.focalLength*2/(castRay(player.x, player.y, rayAngle)*player.sensorSize); - /* 2 Is wall height in meters. */ + float obstacleScale = castRay(player.x, player.y, rayAngle)/player.sensorSize; fillColumn(window, i, obstacleScale); } } @@ -258,7 +247,7 @@ void World::step(const float& stepTime) { player.move(player.currentMoveSpeedX*stepTime, player.currentMoveSpeedY*stepTime); /* Undo last move if the player would end up in a wall. */ - if (getBlock(player.x, player.y) != BlockType::AIR) { + if (getBlock((int)player.x, (int)player.y) != BlockType::AIR) { player.move(-player.currentMoveSpeedX*stepTime, -player.currentMoveSpeedY*stepTime); } diff --git a/World.h b/World.h index 6ecf4ab..c098e68 100644 --- a/World.h +++ b/World.h @@ -30,9 +30,8 @@ public: int getW() const; int getH() const; - inline BlockType getBlock(int x, int y) const; - inline BlockType getBlock(float x, float y) const; - void setBlock(BlockType block, int x, int y, int width = 1, int height = 1); + inline BlockType getBlock(float x, float y) const; + void setBlock(BlockType block, int x, int y, int width = 1, int height = 1); void render(sf::RenderWindow&) const; @@ -51,14 +50,14 @@ private: sf::Color groundColor; sf::Color ceilingColor; - void fillColumn(sf::RenderWindow&, unsigned int column, float scale, + void fillColumn(sf::RenderWindow&, int column, float scale, sf::Color wallColor = sf::Color(84,56,34)) const; /** - * Cast a ray from a given position and its distance to the origin. + * Cast a ray from a given position and return the on-screen scale. * @param originX Ray X origin, strictly positive * @param originY Ray Y origin, strictly positive * @param orientation Angle to cast to, in degrees between 0 and 360 - * @return Distance of the hit to the origin. + * @return Scale on the screen of the hit wall. */ float castRay(float originX, float originY, float orientation) const; }; diff --git a/main.cpp b/main.cpp index 5b9c8d3..73c4dfc 100644 --- a/main.cpp +++ b/main.cpp @@ -14,7 +14,8 @@ int main() std::cout << world << std::endl; sf::RenderWindow window(sf::VideoMode(800,600),"Da raycasting"); - sf::RenderWindow window(sf::VideoMode(1000,1000),"Da raycasting"); + world.render(window); + window.display(); sf::Event event{}; sf::Clock frameTime; @@ -22,19 +23,9 @@ int main() { while (window.pollEvent(event)) { - if (event.type == sf::Event::Closed) { - window.close(); - continue; - } - if (event.type == sf::Event::Resized) { - // Keep the view area fit to the window. - sf::FloatRect newView(0, 0, - static_cast(event.size.width), - static_cast(event.size.height)); - window.setView(sf::View(newView)); - continue; - } - if (event.type == sf::Event::KeyPressed) { + if (event.type == sf::Event::Closed) + window.close(); + else if (event.type == sf::Event::KeyPressed) { switch (event.key.code) { case sf::Keyboard::Key::Escape: window.close();