So yesterday I started working on a wolfenstein like 2d game, using raycasting to visualize the world. (by using permadi's tutorial)
But it's giving me ton of headaches, usually I can figure out or solve things myself, but this time, I'm gonna need help from more experienced people.
Small note, it's a bit messy, and just code to test it, so it's not gonna be used like this, just wanted to get the actually running before I start thinking about optimizing it, and writing it more cleanly.
So yes, the problem, the world is basicly just garbage, it's just impossible to tell what is really going on.
When I was trying some solutions I did get it to work when the camera was in a 90 degree angle, but then when trying to fix the fact that the rotation of the camera didn't work it basicly broke down, and it has been getting even worse with every solution I tried.
So this forum is basicly the last hope, before I just scratch this code and start again.
the degrees are in the unit circle, so right = 0 degrees, 90 degrees is up, 180 left, etc
And the coordinate system follows the usual convention for screens, so the Y axis is pointing down.
Initialization:
raycast::raycast(): m_playerFOV(ToRad(60)), m_PlayerViewAngle(ToRad(90)), m_PlayerHeight(BLOCK_DIM/2), m_PlayerPos(8*BLOCK_DIM,11*BLOCK_DIM), m_ProjPlaneDim(800,600)
{
//Find the center of the projection plane
m_ProjPlaneCenter.x = m_ProjPlaneDim.x/2;
m_ProjPlaneCenter.y = m_ProjPlaneDim.y/2;
//Find the distance from the player to the projection plane
m_ProjPlaneDistance = m_ProjPlaneCenter.x / tan(m_playerFOV/2);
//Find the player direction vector, only used for movement purposes
m_PlayerDirection.x = cos(m_PlayerViewAngle);
m_PlayerDirection.y = sin(m_PlayerViewAngle);
m_PlayerDirection = m_PlayerDirection + m_PlayerPos;
//Find the offset for each ray
m_RayAngles = ToRad(m_playerFOV / ToRad(m_ProjPlaneDim.x));
//Initialize the map
InitMap();
}
Tick Function:
void raycast::Tick()
{
//Add half of the player FOV to get the angel of the first ray
double rayToCastAngle = m_PlayerViewAngle+ (m_playerFOV /2);
//Cast rays equal to the width of the projection plane
for(int rayCounter = 0; rayCounter < int(m_ProjPlaneDim.x); ++rayCounter)
{
//Find the horizontal intersection
DOUBLE2 HorizontalIntersect = HorizontalInterSection(rayToCastAngle);
//Find the vertical Intersection
DOUBLE2 VerticalIntersect = VerticalInterSection(rayToCastAngle);
//Calculate the distances of the rays if the ray has hit a wall
double horizontalRayDist = 0;
if(HorizontalIntersect.x != std::numeric_limits<double>::max() && HorizontalIntersect.y != std::numeric_limits<double>::max())
{
horizontalRayDist = sqrt((m_PlayerPos.x - HorizontalIntersect.x)*(m_PlayerPos.x - HorizontalIntersect.x))+((m_PlayerPos.y - HorizontalIntersect.y)*(m_PlayerPos.y - HorizontalIntersect.y));
//Correct the distance (fishbowl effect)
double angleOffset = rayToCastAngle - m_PlayerViewAngle;
horizontalRayDist *= cos(angleOffset);
}
else
{
horizontalRayDist = std::numeric_limits<double>::max();
}
double verticalRayDist = 0;
if(VerticalIntersect.x != std::numeric_limits<double>::max() && VerticalIntersect.y != std::numeric_limits<double>::max())
{
verticalRayDist = sqrt((m_PlayerPos.x - VerticalIntersect.x)*(m_PlayerPos.x - VerticalIntersect.x))+((m_PlayerPos.y - VerticalIntersect.y)*(m_PlayerPos.y - VerticalIntersect.y));
//Correct the distance (fishbowl effect)
double angleOffset = rayToCastAngle - m_PlayerViewAngle;
verticalRayDist *= cos(angleOffset);
}
else
{
verticalRayDist = std::numeric_limits<double>::max();
}
//Find the smaller of the 2 distances
if(verticalRayDist < horizontalRayDist)
{
m_RayDistances[rayCounter] = double(BLOCK_DIM) / verticalRayDist * m_ProjPlaneDistance;
}
else
{
if(horizontalRayDist < verticalRayDist)
{
m_RayDistances[rayCounter] = double(BLOCK_DIM) / horizontalRayDist * m_ProjPlaneDistance;
}
}
//subtract angle of 1 ray from the angle
rayToCastAngle -= m_RayAngles;
if(rayToCastAngle > ToRad(360))
rayToCastAngle = 0;
if(rayToCastAngle < 0)
rayToCastAngle = ToRad(360);
}
}
Horizontal and vertical rays:
DOUBLE2 raycast::HorizontalInterSection(double rayAngle)
{
//If the ray is 0 or 180 degrees there will be no horizontal Intersection
if(rayAngle == 0 || rayAngle == ToRad(180))
return DOUBLE2(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
//Find the coordinate of the first intersection
DOUBLE2 intersection(0,0);
if(rayAngle < ToRad(180))
{
//ray is facing up
intersection.y = floor(m_PlayerPos.x / BLOCK_DIM) * BLOCK_DIM - 1;
}
else
{
//ray is facing down
intersection.y = floor(m_PlayerPos.x / BLOCK_DIM) * BLOCK_DIM + BLOCK_DIM;
}
intersection.x = m_PlayerPos.x + (m_PlayerPos.x - intersection.y) / tan(rayAngle);
//Check if the ray is outside of the grid
if(intersection.x < 0 || (intersection.x > double(NUM_ROWS*BLOCK_DIM)) || intersection.y < 0 || (intersection.y > double(NUM_ROWS*BLOCK_DIM)))
{
return DOUBLE2(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
}
//Check if there is a wall on the coordinate
if(m_WorldMapArr[int(intersection.x/BLOCK_DIM)][int(intersection.y/BLOCK_DIM)] > 0)
{
return intersection;
}
else
{
//Find the Offsets
DOUBLE2 offSet(double((BLOCK_DIM)/tan(rayAngle)),BLOCK_DIM);
//if the ray is facing up
if(rayAngle < ToRad(180))
offSet.y = BLOCK_DIM*-1;
//loop until intersection is found or the ray goes outside of the grid
while(true)
{
intersection.x += offSet.x;
intersection.y += offSet.y;
//Check if the ray is outside of the grid
if(intersection.x < 0 || (intersection.x > double(NUM_ROWS*BLOCK_DIM)) || intersection.y < 0 || (intersection.y > double(NUM_ROWS*BLOCK_DIM)))
{
return DOUBLE2(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
}
//Check if there is a wall on the coordinate
if(m_WorldMapArr[int(intersection.x/BLOCK_DIM)][int(intersection.y/BLOCK_DIM)] > 0)
{
return intersection;
}
}
}
}
DOUBLE2 raycast::VerticalInterSection(double rayAngle)
{
//if the ray is 90 or 270 degrees we can't find a vertical intersection
if(rayAngle == ToRad(90) || rayAngle == ToRad(270))
{
return DOUBLE2(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
}
//Find the first Intersection
DOUBLE2 intersection(0,0);
if(rayAngle > ToRad(90) && rayAngle < ToRad(270))
{
//ray is facing left
intersection.x = floor(m_PlayerPos.x / double(BLOCK_DIM)) * BLOCK_DIM -1;
}
else
{
//ray is facing right
intersection.x = floor(m_PlayerPos.x / double(BLOCK_DIM)) * BLOCK_DIM + BLOCK_DIM;
}
intersection.y = m_PlayerPos.y + (m_PlayerPos.x - intersection.x) * tan(rayAngle);
//Check if the ray is withing the grid
if(intersection.x < 0 || (intersection.x > double(NUM_ROWS*BLOCK_DIM)) || intersection.y < 0 || (intersection.y > double(NUM_ROWS*BLOCK_DIM)))
{
return DOUBLE2(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
}
//check if the ray has hit a wall
if(m_WorldMapArr[int(intersection.x/BLOCK_DIM)][int(intersection.y/BLOCK_DIM)] > 0)
{
return intersection;
}
else
{
//find the offsets
DOUBLE2 offset(BLOCK_DIM, (m_PlayerPos.y + (m_PlayerPos.x - intersection.x) * tan(rayAngle)));
//Check if the ray is facing right
if(rayAngle > ToRad(90) && rayAngle < ToRad(270))
offset.x = BLOCK_DIM * -1;
//loop untill a wall has found or the ray is outside the grid
while(true)
{
intersection.x += offset.x;
intersection.y += offset.y;
//Check if the ray is outside of the grid
if(intersection.x < 0 || (intersection.x > double(NUM_ROWS*BLOCK_DIM)) || intersection.y < 0 || (intersection.y > double(NUM_ROWS*BLOCK_DIM)))
{
return DOUBLE2(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
}
//Check if there is a wall on the coordinate
if(m_WorldMapArr[int(intersection.x/BLOCK_DIM)][int(intersection.y/BLOCK_DIM)] > 0)
{
return intersection;
}
}
}
}


















