refac: clean working raycasting

This commit is contained in:
Floriansylvain
2025-12-28 17:44:13 +01:00
parent 763a236882
commit 37f22cad70
4 changed files with 116 additions and 95 deletions
+4 -82
View File
@@ -1,13 +1,10 @@
#include "Game.hpp" #include "Game.hpp"
#include "Lighting.hpp"
#include <SFML/Graphics/Color.hpp> #include <SFML/Graphics/Color.hpp>
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <SFML/Window/Mouse.hpp> #include <SFML/Window/Mouse.hpp>
#include <algorithm>
#include <cmath>
Game::Game() Game::Game() : gridLines(WIDTH, HEIGHT, 20.f), player(15.f, sf::Color::Green) {
: gridLines(WIDTH, HEIGHT, 20.f), player(15.f, sf::Color::Green),
rayVertices(sf::PrimitiveType::TriangleFan) {
window.create(sf::VideoMode({WIDTH, HEIGHT}), "SFML Game"); window.create(sf::VideoMode({WIDTH, HEIGHT}), "SFML Game");
window.setVerticalSyncEnabled(VSYNC); window.setVerticalSyncEnabled(VSYNC);
@@ -17,8 +14,6 @@ Game::Game()
worldView.setSize({(float)WIDTH, (float)HEIGHT}); worldView.setSize({(float)WIDTH, (float)HEIGHT});
worldView.setCenter({(float)WIDTH / 2.f, (float)HEIGHT / 2.f}); worldView.setCenter({(float)WIDTH / 2.f, (float)HEIGHT / 2.f});
lightColor = sf::Color(255, 255, 150, 50);
} }
void Game::run() { void Game::run() {
@@ -61,80 +56,10 @@ void Game::processEvents() {
}; };
}; };
float Game::intersects(Ray ray, Wall wall) {
auto wallVector = wall.end - wall.start;
auto determinator =
(ray.direction.x * wallVector.y) - (ray.direction.y * wallVector.x);
if (determinator == 0)
return INFINITY;
auto rayDist = ((wall.start.x - ray.origin.x) * wallVector.y -
(wall.start.y - ray.origin.y) * wallVector.x);
rayDist /= determinator;
auto wallDist = (wall.start.x - ray.origin.x) * ray.direction.y -
(wall.start.y - ray.origin.y) * ray.direction.x;
wallDist /= determinator;
if (rayDist > 0 && wallDist >= 0 && wallDist <= 1) {
return rayDist;
}
return INFINITY;
};
sf::Vector2f Game::updateRay(sf::Vector2f &origin, sf::Vector2f &targetPoint,
float offset) {
auto closestDist = 1.0f;
auto maxDist = 3000.0f;
float angle =
std::atan2(targetPoint.y - origin.y, targetPoint.x - origin.x) + offset;
sf::Vector2f direction = {std::cos(angle) * maxDist,
std::sin(angle) * maxDist};
Ray ray = {origin, direction};
for (Wall wall : walls.get()) {
auto rayDist = intersects(ray, wall);
if (rayDist < closestDist) {
closestDist = rayDist;
};
}
return ray.origin + (ray.direction * closestDist);
}
void Game::update(double dt) { void Game::update(double dt) {
debug.update(dt); debug.update(dt);
player.update(dt, window, worldView); player.update(dt, window, worldView);
lighting.update(dt, player.position, walls);
// INIT/UPDATE RAYS ------------------------------------------
sf::Vector2 playerPosition = player.position;
rayVertices.clear();
hitPoints.clear();
for (sf::Vector2 targetPoint : walls.getPoints()) {
hitPoints.emplace_back(updateRay(playerPosition, targetPoint, 0.f));
hitPoints.emplace_back(updateRay(playerPosition, targetPoint, 0.001f));
hitPoints.emplace_back(updateRay(playerPosition, targetPoint, -0.001f));
}
std::sort(hitPoints.begin(), hitPoints.end(),
[playerPosition](sf::Vector2f a, sf::Vector2f b) -> bool {
auto angleA =
atan2(playerPosition.y - a.y, playerPosition.x - a.x);
auto angleB =
atan2(playerPosition.y - b.y, playerPosition.x - b.x);
return angleA < angleB;
});
rayVertices.append({playerPosition, lightColor});
for (auto hitPoint : hitPoints) {
rayVertices.append({hitPoint, lightColor});
}
rayVertices.append({hitPoints[0], lightColor});
// -----------------------------------------------------------
}; };
void Game::render() { void Game::render() {
@@ -145,10 +70,7 @@ void Game::render() {
debug.render(window); debug.render(window);
player.render(window); player.render(window);
walls.render(window); walls.render(window);
lighting.render(window);
// RENDER RAYS -------
window.draw(rayVertices);
// -----------------
window.display(); window.display();
}; };
+2 -13
View File
@@ -9,6 +9,7 @@
#include "DebugUI.hpp" #include "DebugUI.hpp"
#include "GridLines.hpp" #include "GridLines.hpp"
#include "Lighting.hpp"
#include "Player.hpp" #include "Player.hpp"
#include "Walls.hpp" #include "Walls.hpp"
@@ -18,11 +19,6 @@ constexpr int HEIGHT = 1080;
constexpr int DEBUG_REFRESH_RATE_IN_MS = 250; constexpr int DEBUG_REFRESH_RATE_IN_MS = 250;
constexpr float ASPECT = 16.f / 9.f; constexpr float ASPECT = 16.f / 9.f;
struct Ray {
sf::Vector2f origin;
sf::Vector2f direction;
};
class Game { class Game {
public: public:
Game(); Game();
@@ -36,14 +32,7 @@ private:
DebugUI debug; DebugUI debug;
GridLines gridLines; GridLines gridLines;
Walls walls; Walls walls;
Lighting lighting;
sf::VertexArray rayVertices;
std::vector<sf::Vector2f> hitPoints;
sf::Color lightColor;
float intersects(Ray ray, Wall wall);
sf::Vector2f updateRay(sf::Vector2f &origin, sf::Vector2f &targetPoint,
float offset);
void onResize(); void onResize();
void processEvents(); void processEvents();
+81
View File
@@ -0,0 +1,81 @@
#include "Lighting.hpp"
#include <algorithm>
#include <cmath>
Lighting::Lighting() : rayVertices(sf::PrimitiveType::TriangleFan) {
lightColor = sf::Color(255, 255, 150, 50);
};
float Lighting::intersects(Ray ray, Wall wall) {
auto wallVector = wall.end - wall.start;
auto determinator =
(ray.direction.x * wallVector.y) - (ray.direction.y * wallVector.x);
if (determinator == 0)
return INFINITY;
auto rayDist = ((wall.start.x - ray.origin.x) * wallVector.y -
(wall.start.y - ray.origin.y) * wallVector.x);
rayDist /= determinator;
auto wallDist = (wall.start.x - ray.origin.x) * ray.direction.y -
(wall.start.y - ray.origin.y) * ray.direction.x;
wallDist /= determinator;
if (rayDist > 0 && wallDist >= 0 && wallDist <= 1) {
return rayDist;
}
return INFINITY;
};
sf::Vector2f Lighting::updateRay(Walls &walls, sf::Vector2f &origin,
sf::Vector2f &targetPoint, float offset) {
auto closestDist = 1.0f;
auto maxDist = 3000.0f;
float angle =
std::atan2(targetPoint.y - origin.y, targetPoint.x - origin.x) + offset;
sf::Vector2f direction = {std::cos(angle) * maxDist,
std::sin(angle) * maxDist};
Ray ray = {origin, direction};
for (Wall wall : walls.get()) {
auto rayDist = intersects(ray, wall);
if (rayDist < closestDist) {
closestDist = rayDist;
};
}
return ray.origin + (ray.direction * closestDist);
}
void Lighting::update(double dt, sf::Vector2f &playerPosition, Walls &walls) {
rayVertices.clear();
hitPoints.clear();
for (sf::Vector2 targetPoint : walls.getPoints()) {
hitPoints.emplace_back(updateRay(walls, playerPosition, targetPoint, 0.f));
hitPoints.emplace_back(
updateRay(walls, playerPosition, targetPoint, 0.001f));
hitPoints.emplace_back(
updateRay(walls, playerPosition, targetPoint, -0.001f));
}
std::sort(hitPoints.begin(), hitPoints.end(),
[playerPosition](sf::Vector2f a, sf::Vector2f b) -> bool {
auto angleA =
atan2(playerPosition.y - a.y, playerPosition.x - a.x);
auto angleB =
atan2(playerPosition.y - b.y, playerPosition.x - b.x);
return angleA < angleB;
});
rayVertices.append({playerPosition, lightColor});
for (auto hitPoint : hitPoints) {
rayVertices.append({hitPoint, lightColor});
}
rayVertices.append({hitPoints[0], lightColor});
}
void Lighting::render(sf::RenderWindow &window) { window.draw(rayVertices); };
+29
View File
@@ -0,0 +1,29 @@
#ifndef LIGHTING_HPP
#define LIGHTING_HPP
#include "Walls.hpp"
#include <SFML/Graphics/VertexArray.hpp>
#include <SFML/System/Vector2.hpp>
struct Ray {
sf::Vector2f origin;
sf::Vector2f direction;
};
class Lighting {
public:
Lighting();
float intersects(Ray ray, Wall wall);
sf::Vector2f updateRay(Walls &walls, sf::Vector2f &origin,
sf::Vector2f &targetPoint, float offset);
void update(double dt, sf::Vector2f &playerPosition, Walls &walls);
void render(sf::RenderWindow &window);
private:
sf::VertexArray rayVertices;
std::vector<sf::Vector2f> hitPoints;
sf::Color lightColor;
};
#endif // LIGHTING_HPP