From 4a95664342833931836b9b60c588e5bb8413b184 Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Wed, 24 Jan 2024 23:09:59 +0000 Subject: [PATCH 1/3] main: Clean up, handle resize Handle window resizes by resizing the view frame as well. Clean up the event handling to allow interleaving other code between different checks. Remove early first frame, handle it like the others. --- main.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/main.cpp b/main.cpp index 73c4dfc..5b9c8d3 100644 --- a/main.cpp +++ b/main.cpp @@ -14,8 +14,7 @@ int main() std::cout << world << std::endl; sf::RenderWindow window(sf::VideoMode(800,600),"Da raycasting"); - world.render(window); - window.display(); + sf::RenderWindow window(sf::VideoMode(1000,1000),"Da raycasting"); sf::Event event{}; sf::Clock frameTime; @@ -23,9 +22,19 @@ int main() { while (window.pollEvent(event)) { - if (event.type == sf::Event::Closed) - window.close(); - else if (event.type == sf::Event::KeyPressed) { + 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) { switch (event.key.code) { case sf::Keyboard::Key::Escape: window.close(); From ddb01d05096772dbb2a0bb471f053148a8ad7df9 Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Wed, 24 Jan 2024 23:16:44 +0000 Subject: [PATCH 2/3] World: Clean warnings, optimize GetBlock World has a lot of type conversion warnings. Take care of most of them, for a slight performance hit ( :( ). Re-order constructor parameters to match declaration. Move FillColumn to a more appropriate place. GetBlock gets called a lot : use direct memory access of the vector rather than going through bounds checks with .at(). Introduce an integer overload to remove warnings. --- World.cpp | 54 +++++++++++++++++++++++++++++++++--------------------- World.h | 7 ++++--- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/World.cpp b/World.cpp index f632b86..40120ed 100644 --- a/World.cpp +++ b/World.cpp @@ -6,8 +6,9 @@ #include -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) +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) { map.resize(w*h,BlockType::WALL); } @@ -22,9 +23,14 @@ 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.at(static_cast(x)+w* static_cast(y))); + return map[static_cast(x) + w*static_cast(y)]; } void World::setBlock(BlockType block, int x, int y, int width, int height) @@ -83,16 +89,6 @@ 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 { /* @@ -169,7 +165,8 @@ float World::castRay(float originX, float originY, float orientation) const float hCheckX = originX + hOffsetX; float hCheckY = hOffsetY; /* Bounds + sanity check. */ - while (hCheckX >= 0 && hCheckX <= w && hCheckY >= 0 && hCheckY <= h && i < h) { + while (hCheckX >= 0 && hCheckX <= static_cast(w) && + hCheckY >= 0 && hCheckY <= static_cast(h) && i < h) { if (getBlock(floorf(hCheckX), floorf(hCheckY) + hRound) == BlockType::WALL) { break; } @@ -184,7 +181,8 @@ float World::castRay(float originX, float originY, float orientation) const float vCheckY = originY + vOffsetY; /* Bounds + sanity check. */ - while (vCheckX >= 0 && vCheckX < w && vCheckY >= 0 && vCheckY < h && i < w) { + while (vCheckX >= 0 && vCheckX < static_cast(w) && + vCheckY >= 0 && vCheckY < static_cast(h) && i < w) { if (getBlock(floorf(vCheckX) + vRound, floorf(vCheckY)) == BlockType::WALL) { break; } @@ -208,18 +206,32 @@ float World::castRay(float originX, float originY, float orientation) const return player.focalLength*2/finalDist; } +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); +} + 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(window.getSize().x,window.getSize().y/2.0)); + sf::RectangleShape ground = sf::RectangleShape(sf::Vector2f(windowX,windowY/2.0f)); ground.setFillColor(groundColor); - ground.setPosition(0,window.getSize().y/2.0); + ground.setPosition(0,windowY/2.0f); - sf::RectangleShape ceiling = sf::RectangleShape(sf::Vector2f(window.getSize().x,window.getSize().y/2.0)); + sf::RectangleShape ceiling = sf::RectangleShape(sf::Vector2f(windowX,windowY/2.0f)); ceiling.setFillColor(ceilingColor); window.draw(ground); @@ -229,9 +241,9 @@ 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(int i = 0;i(i)-windowX/2.0f); float rayAngle = player.orientation + deltaAngle; if (rayAngle < 0) { rayAngle += 360; @@ -247,7 +259,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((int)player.x, (int)player.y) != BlockType::AIR) { + if (getBlock(player.x, player.y) != BlockType::AIR) { player.move(-player.currentMoveSpeedX*stepTime, -player.currentMoveSpeedY*stepTime); } diff --git a/World.h b/World.h index c098e68..7f716e3 100644 --- a/World.h +++ b/World.h @@ -30,8 +30,9 @@ public: int getW() const; int getH() 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(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); void render(sf::RenderWindow&) const; @@ -50,7 +51,7 @@ private: sf::Color groundColor; sf::Color ceilingColor; - void fillColumn(sf::RenderWindow&, int column, float scale, + void fillColumn(sf::RenderWindow&, unsigned int column, float scale, sf::Color wallColor = sf::Color(84,56,34)) const; /** * Cast a ray from a given position and return the on-screen scale. From a0b65364325bd33fc54bfb1ae3c7cfd77318ed19 Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Thu, 25 Jan 2024 22:30:38 +0000 Subject: [PATCH 3/3] World: make CastRay generic Previously CastRay did the scale computation and used the player view statistics. This makes it quite specialized, and the rest of the computations are made outside. Move the computations in the render function and make castRay generic. --- World.cpp | 7 +++---- World.h | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/World.cpp b/World.cpp index 40120ed..1ca062c 100644 --- a/World.cpp +++ b/World.cpp @@ -200,10 +200,8 @@ 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; - /* 2 Is wall height in meters. */ - return player.focalLength*2/finalDist; + return hDist > vDist ? vDist : hDist; } void World::fillColumn(sf::RenderWindow& window, unsigned int column, @@ -250,7 +248,8 @@ void World::render(sf::RenderWindow& window) const } else if (rayAngle > 360) { rayAngle -= 360; } - float obstacleScale = castRay(player.x, player.y, rayAngle)/player.sensorSize; + float obstacleScale = player.focalLength*2/(castRay(player.x, player.y, rayAngle)*player.sensorSize); + /* 2 Is wall height in meters. */ fillColumn(window, i, obstacleScale); } } diff --git a/World.h b/World.h index 7f716e3..6ecf4ab 100644 --- a/World.h +++ b/World.h @@ -54,11 +54,11 @@ private: void fillColumn(sf::RenderWindow&, unsigned int column, float scale, sf::Color wallColor = sf::Color(84,56,34)) const; /** - * Cast a ray from a given position and return the on-screen scale. + * Cast a ray from a given position and its distance to the origin. * @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 Scale on the screen of the hit wall. + * @return Distance of the hit to the origin. */ float castRay(float originX, float originY, float orientation) const; };