yupplemayham/YuppleMayham/utility/raycaster.h
Ethan Adams 7e7dfd97b7 Removed UNIX (..) from headers
Cleaned up the weapon class
moved mousestate.h out of gameplay into utility
2024-06-22 00:08:59 -04:00

135 lines
No EOL
4.4 KiB
C++

#ifndef _H_RAYCASTER_H
#define _H_RAYCASTER_H
#include <glm/glm.hpp>
#include <vector>
#include <memory>
#include "utility/debugdraw.h"
class Raycaster {
public:
Raycaster(
float FOV,
float viewDist,
const std::vector<std::vector<int>>& collisionMap,
float tileSize)
:
FOV(FOV),
viewDist(viewDist),
collisionMap(collisionMap),
tileSize(tileSize)
{}
bool bresenhamRaycast(const glm::vec3& origin, const float rotation, const glm::vec3& target)
{
float rayAngle = rotation - (FOV / 2);
float angleIncrement = 2.0f;
bool hitTarget = false;
glm::ivec2 lastEnd = glm::ivec2(0);
for (int rayCount = 0; rayCount <= FOV / 2; rayCount++)
{
float endX = (origin.x + (glm::cos(glm::radians(rayAngle)) * viewDist));
float endY = (origin.y + (glm::sin(glm::radians(rayAngle)) * viewDist));
glm::ivec2 targetTile= glm::ivec2(static_cast<int>(target.x / tileSize), static_cast<int>(target.y / tileSize));
glm::ivec2 startTile = glm::ivec2(static_cast<int>((origin.x + tileSize * 0.1f) / tileSize), static_cast<int>((origin.y + tileSize * 0.1f) / tileSize));
glm::ivec2 endTile = glm::ivec2(static_cast<int>(endX / tileSize), static_cast<int>(endY / tileSize));
int dx = glm::abs(endTile.x - startTile.x);
int dy = glm::abs(endTile.y - startTile.y);
int sx = startTile.x < endTile.x ? 1 : -1;
int sy = startTile.y < endTile.y ? 1 : -1;
int err = (dx > dy ? dx : -dy) / 2;
glm::ivec2 step = startTile;
while (step != endTile)
{
if (step.x < 0 || step.x >= collisionMap[0].size() ||
step.y < 0 || step.y >= collisionMap.size())
{
if (glm::abs(rayAngle - rotation) <= 2)
distFromWall = distFromWall < glm::distance(glm::vec2(startTile), glm::vec2(step)) ?
distFromWall : glm::distance(glm::vec2(startTile), glm::vec2(step));
break;
}
if (collisionMap[step.y][step.x] != 0)
{
if (glm::abs(rayAngle - rotation) <= 2)
distFromWall = distFromWall < glm::distance(glm::vec2(startTile), glm::vec2(step)) ?
distFromWall : glm::distance(glm::vec2(startTile), glm::vec2(step));
break;
}
if (step == targetTile)
hitTarget = true;
int e2 = err;
if (e2 > -dx)
{
err -= dy;
step.x += sx;
}
if (e2 < dy)
{
err += dx;
step.y += sy;
}
}
//LineDrawer::getInstance().addLine(origin, glm::vec3(step.x * tileSize, step.y * tileSize, 0.f), glm::vec4(1.0 - (1.0f / rayCount), 1.0f / rayCount, 0.0f, 0.7f));
if (step == endTile)
distFromWall = std::numeric_limits<float>::infinity();
rayAngle += angleIncrement;
}
return hitTarget;
}
// We need to collision map and tile size so we can hide behind tiles
// returns true if the raycast lands on the targets tile
bool performRaycast(const glm::vec3& origin, const float rotation, const glm::vec3& target) {
float rayStepSize = 0.05f;
float rayAngle = rotation - (FOV / 2);
float angleInc = 2.0f;
glm::ivec2 targetTile = glm::ivec2(static_cast<int>(target.x / tileSize), static_cast<int>(target.y / tileSize));
bool hitTarget = false;
for (int rayCount = 0; rayCount <= FOV / 2; rayCount++)
{
glm::vec2 ray = glm::vec2(origin);
while (glm::distance(ray, glm::vec2(origin)) < viewDist)
{
ray.x += cos(glm::radians(rayAngle)) * rayStepSize;
ray.y += sin(glm::radians(rayAngle)) * rayStepSize;
glm::ivec2 rayTile = glm::ivec2(static_cast<int>(ray.x / tileSize), static_cast<int>(ray.y / tileSize));
if (rayTile.x < 0 || rayTile.x >= collisionMap[0].size() ||
rayTile.y < 0 || rayTile.y >= collisionMap.size())
{
if (rayCount == FOV / 2)
distFromWall = glm::distance(glm::vec2(origin), ray);
break;
}
if (collisionMap[rayTile.y][rayTile.x] != 0)
{
if (rayCount == FOV / 2)
distFromWall = glm::distance(glm::vec2(origin), ray);
break;
}
if (rayTile == targetTile)
hitTarget = true;
}
DebugDrawer::getInstance().addLine(origin, glm::vec3(ray.x, ray.y, 0.f), glm::vec4(1.0f, 0.0f, 0.0f, 0.2f));
if (glm::distance(ray, glm::vec2(origin)) >= viewDist)
distFromWall = std::numeric_limits<float>::infinity();
rayAngle += angleInc;
}
return hitTarget;
}
float getDistanceFromWall() const { return distFromWall; }
float getTileSize() const { return tileSize; }
private:
float FOV;
float viewDist;
float distFromWall = std::numeric_limits<float>::infinity();
std::vector<std::vector<int>> collisionMap;
float tileSize;
};
#endif // _H_RAYCASTER_H