1
0
Fork 0

Compare commits

..

2 commits

Author SHA1 Message Date
9678e8c286 World: Introduce a struct for raycast results
In order to implement more complexe behaviors, more information than the distance
is needed from a raycast.
Add a new struct to store and return this information, currently hit position
and hit type, and update castRay to return that instead.
2024-02-05 00:33:01 +00:00
3492cfa63d World: Add projection correction factor
Rays are all sent from the center of the camera plane, which makes rays
with a greater angle longer than if they were properly sent perpendicularly
from the camera plane.

Correct this by projecting the ray to the look direction (which is
perpendicular to the camera plane).
2024-02-04 21:04:07 +00:00
2 changed files with 30 additions and 5 deletions

View file

@ -99,7 +99,7 @@ std::ostream& operator<<(std::ostream& ostream, World const& world)
return(ostream); return(ostream);
} }
float World::castRay(float originX, float originY, float orientation) const RaycastResult World::castRay(float originX, float originY, float orientation) const
{ {
/* /*
* Reference used for ray intersection computations : * Reference used for ray intersection computations :
@ -214,7 +214,21 @@ float World::castRay(float originX, float originY, float orientation) const
float vDist = sqrtf((originX - vCheckX)*(originX - vCheckX) + float vDist = sqrtf((originX - vCheckX)*(originX - vCheckX) +
(originY - vCheckY)*(originY - vCheckY)); (originY - vCheckY)*(originY - vCheckY));
return hDist > vDist ? vDist : hDist;
RaycastResult result{};
if (hDist > vDist) {
result.distance = vDist;
result.hitX = vCheckX;
result.hitY = vCheckY;
} else {
result.distance = hDist;
result.hitX = hCheckX;
result.hitY = hCheckY;
}
result.hitBlock = getBlock(floorf(result.hitX) + vRound,
floorf(result.hitY));
return result;
} }
void World::fillColumn(sf::RenderWindow& window, unsigned int column, void World::fillColumn(sf::RenderWindow& window, unsigned int column,
@ -267,7 +281,10 @@ void World::render(sf::RenderWindow& window)
} else if (rayAngle > 360) { } else if (rayAngle > 360) {
rayAngle -= 360; rayAngle -= 360;
} }
float obstacleScale = worldToCamera / castRay(player.x, player.y, rayAngle); float obstacleScale = worldToCamera / (
castRay(player.x, player.y, rayAngle).distance *
cosf(deltaAngle*deg_to_rad)
);
/* 2 Is wall height in meters. */ /* 2 Is wall height in meters. */
fillColumn(window, i, obstacleScale); fillColumn(window, i, obstacleScale);
} }

12
World.h
View file

@ -9,6 +9,7 @@
#include <ostream> #include <ostream>
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include <iostream> #include <iostream>
#include <optional>
#include "Color.h" #include "Color.h"
#include "Player.h" #include "Player.h"
@ -20,6 +21,13 @@ enum class BlockType {
WINDOW, WINDOW,
}; };
struct RaycastResult {
float distance;
float hitX;
float hitY;
BlockType hitBlock;
};
class World { class World {
public: public:
Player player; Player player;
@ -61,9 +69,9 @@ private:
* @param originX Ray X origin, strictly positive * @param originX Ray X origin, strictly positive
* @param originY Ray Y origin, strictly positive * @param originY Ray Y origin, strictly positive
* @param orientation Angle to cast to, in degrees between 0 and 360 * @param orientation Angle to cast to, in degrees between 0 and 360
* @return Distance of the hit to the origin. * @return Result struct containing information on the hit.
*/ */
float castRay(float originX, float originY, float orientation) const; RaycastResult castRay(float originX, float originY, float orientation) const;
}; };