mirror of
https://github.com/Floriansylvain/whateversfml.git
synced 2026-08-19 11:43:22 +02:00
refac: clean working raycasting
This commit is contained in:
+4
-82
@@ -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
@@ -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();
|
||||||
|
|||||||
@@ -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); };
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user