From 4402ec9159ac6f53b7e8882d9fca61f696477b1c Mon Sep 17 00:00:00 2001 From: Floriansylvain Date: Sun, 28 Dec 2025 05:35:35 +0100 Subject: [PATCH] feat: raycasting part 1 --- src/Game.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++--------- src/Game.hpp | 22 ++++++++++++++++ src/Walls.cpp | 19 +++++++++++++- src/Walls.hpp | 2 ++ 4 files changed, 101 insertions(+), 13 deletions(-) diff --git a/src/Game.cpp b/src/Game.cpp index e1c24bc..25d9afd 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -1,6 +1,12 @@ #include "Game.hpp" +#include +#include +#include +#include -Game::Game() : gridLines(WIDTH, HEIGHT, 20.f), player(15.f, sf::Color::Green) { +Game::Game() + : gridLines(WIDTH, HEIGHT, 20.f), player(15.f, sf::Color::Green), + rayVertices(sf::PrimitiveType::Lines) { window.create(sf::VideoMode({WIDTH, HEIGHT}), "SFML Game"); window.setVerticalSyncEnabled(VSYNC); @@ -10,17 +16,6 @@ Game::Game() : gridLines(WIDTH, HEIGHT, 20.f), player(15.f, sf::Color::Green) { worldView.setSize({(float)WIDTH, (float)HEIGHT}); worldView.setCenter({(float)WIDTH / 2.f, (float)HEIGHT / 2.f}); - - walls.add({1.f, 1.f}, {WIDTH - 1.f, 1.f}); - walls.add({1.f, 1.f}, {1.f, HEIGHT - 1.f}); - walls.add({WIDTH - 1.f, 1.f}, {WIDTH - 1.f, HEIGHT - 1.f}); - walls.add({1.f, HEIGHT - 1.f}, {WIDTH - 1.f, HEIGHT - 1.f}); - - walls.add({1000.f, 500.f}, {1500.f, 500.f}); - walls.add({500.f, 240.f}, {500.f, 760.f}); - walls.add({420.f, 240.f}, {420.f, 760.f}); - walls.add({420.f, 240.f}, {500.f, 240.f}); - walls.add({420.f, 760.f}, {500.f, 760.f}); } void Game::run() { @@ -63,9 +58,57 @@ 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 false; + + 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; +}; + void Game::update(double dt) { debug.update(dt); player.update(dt, window, worldView); + + // INIT/UPDATE RAYS ------- + auto mousePos = sf::Mouse::getPosition(window); + auto mousePosWorld = window.mapPixelToCoords(mousePos, worldView); + + rayVertices.clear(); + for (sf::Vector2 targetPoint : walls.getPoints()) { + auto ray = Ray(mousePosWorld, targetPoint); + auto closestDist = 1.0f; + + for (Wall wall : walls.get()) { + auto rayDist = intersects(ray, wall); + if (rayDist < closestDist) { + closestDist = rayDist; + }; + } + + sf::Vector2f hitPoint = ray.origin + (ray.direction * closestDist); + + rayVertices.append({ray.origin, sf::Color::Blue}); + rayVertices.append({hitPoint, sf::Color::Blue}); + } + + // TODO: implement 3-rays trick to have softer angles + // ----------------- }; void Game::render() { @@ -77,5 +120,9 @@ void Game::render() { player.render(window); walls.render(window); + // RENDER RAYS ------- + window.draw(rayVertices); + // ----------------- + window.display(); }; diff --git a/src/Game.hpp b/src/Game.hpp index a22be1e..5bef1d1 100644 --- a/src/Game.hpp +++ b/src/Game.hpp @@ -2,6 +2,10 @@ #define GAME_HPP #include +#include +#include +#include +#include #include "DebugUI.hpp" #include "GridLines.hpp" @@ -14,6 +18,20 @@ constexpr int HEIGHT = 1080; constexpr int DEBUG_REFRESH_RATE_IN_MS = 250; constexpr float ASPECT = 16.f / 9.f; +struct Ray { + sf::Vector2f origin; + sf::Vector2f direction; + float angle; + + Ray(sf::Vector2f origin, sf::Vector2f target) { + this->origin = origin; + this->direction = target - origin; + angle = direction.angleTo(origin).asDegrees(); + }; + + Ray(float angle, float length) {}; // TODO +}; + class Game { public: Game(); @@ -28,6 +46,10 @@ private: GridLines gridLines; Walls walls; + sf::VertexArray rayVertices; + + float intersects(Ray ray, Wall wall); + void onResize(); void processEvents(); void update(double dt); diff --git a/src/Walls.cpp b/src/Walls.cpp index 23cb9ad..b568af8 100644 --- a/src/Walls.cpp +++ b/src/Walls.cpp @@ -1,14 +1,31 @@ #include "Walls.hpp" +#include "Game.hpp" #include +#include -Walls::Walls() : walls(sf::PrimitiveType::Lines) {}; +Walls::Walls() : walls(sf::PrimitiveType::Lines) { + add({1.f, 1.f}, {WIDTH - 1.f, 1.f}); + add({1.f, 1.f}, {1.f, HEIGHT - 1.f}); + add({WIDTH - 1.f, 1.f}, {WIDTH - 1.f, HEIGHT - 1.f}); + add({1.f, HEIGHT - 1.f}, {WIDTH - 1.f, HEIGHT - 1.f}); + + add({1000.f, 500.f}, {1500.f, 500.f}); + add({500.f, 240.f}, {500.f, 760.f}); + add({420.f, 240.f}, {420.f, 760.f}); + add({420.f, 240.f}, {500.f, 240.f}); + add({420.f, 760.f}, {500.f, 760.f}); +}; void Walls::add(sf::Vector2f pointA, sf::Vector2f pointB) { walls.append({pointA, sf::Color::Red}); walls.append({pointB, sf::Color::Red}); vertices.emplace_back(Wall{pointA, pointB}); + points.emplace_back(pointA); + points.emplace_back(pointB); }; std::vector Walls::get() { return vertices; }; +std::vector Walls::getPoints() { return points; }; + void Walls::render(sf::RenderWindow &window) { window.draw(walls); }; diff --git a/src/Walls.hpp b/src/Walls.hpp index 19fb0ee..cd58832 100644 --- a/src/Walls.hpp +++ b/src/Walls.hpp @@ -18,12 +18,14 @@ public: void add(sf::Vector2f pointA, sf::Vector2f pointB); std::vector get(); + std::vector getPoints(); void render(sf::RenderWindow &window); private: sf::VertexArray walls; std::vector vertices; + std::vector points; }; #endif // WALLS_HPP