Ray casting now working
This commit is contained in:
		
							parent
							
								
									3402fb50d9
								
							
						
					
					
						commit
						ccfe9fd786
					
				@ -49,7 +49,7 @@ static void drawRays(Camera* camera, sf::RenderWindow* window)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		float distance = level_rayCastDistance(camera->pos, rayDirection);
 | 
							float distance = level_rayCastDistance(camera->pos, rayDirection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		drawLine(window, camera->pos, rayDirection, distance, sf::Color::Blue);
 | 
							drawLine(window, camera->pos, rayDirection, distance, sf::Color(150, 150, 100));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((i + isOddResolution) % 2) rayDirectionOffset += rayDirectionStep;
 | 
							if ((i + isOddResolution) % 2) rayDirectionOffset += rayDirectionStep;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										103
									
								
								level.cpp
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								level.cpp
									
									
									
									
									
								
							@ -10,17 +10,17 @@ static void drawGrid();
 | 
				
			|||||||
static void drawGridLine(unsigned int step, bool isHorizontal);
 | 
					static void drawGridLine(unsigned int step, bool isHorizontal);
 | 
				
			||||||
static sf::Vertex getGridLineVertex(unsigned int n, unsigned int maxDimension, bool isStart, bool isHorizontal);
 | 
					static sf::Vertex getGridLineVertex(unsigned int n, unsigned int maxDimension, bool isStart, bool isHorizontal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void castRay(sf::Vector2f point, float direction);
 | 
					static float castRay(sf::Vector2f point, float direction);
 | 
				
			||||||
static void getGridIndex(sf::Vector2f point, int* x, int* y);
 | 
					static void getGridIndex(sf::Vector2f point, int* x, int* y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static sf::RenderWindow* window = nullptr;
 | 
					static sf::RenderWindow* window = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned int level[WIDTH * HEIGHT] = {
 | 
					static unsigned int level[WIDTH * HEIGHT] = {
 | 
				
			||||||
	1, 1, 1, 1, 1,
 | 
						1, 1, 1, 1, 1,
 | 
				
			||||||
	1, 0, 0, 0, 0,
 | 
						0, 0, 0, 0, 0,
 | 
				
			||||||
	1, 0, 1, 0, 1,
 | 
						0, 0, 1, 0, 1,
 | 
				
			||||||
	1, 0, 0, 0, 0,
 | 
						0, 0, 0, 0, 0,
 | 
				
			||||||
	1, 0, 1, 0, 1,
 | 
						0, 0, 1, 0, 1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int level_init(sf::RenderWindow* renderWindow)
 | 
					int level_init(sf::RenderWindow* renderWindow)
 | 
				
			||||||
@ -45,8 +45,7 @@ void level_end()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
float level_rayCastDistance(sf::Vector2f point, float direction)
 | 
					float level_rayCastDistance(sf::Vector2f point, float direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	castRay(point, direction);
 | 
						return castRay(point, direction);
 | 
				
			||||||
	return 1000.f;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void drawGrid()
 | 
					static void drawGrid()
 | 
				
			||||||
@ -107,73 +106,97 @@ static sf::Vertex getGridLineVertex(unsigned int offset, unsigned int maxDimensi
 | 
				
			|||||||
	return isStart? start : end;
 | 
						return isStart? start : end;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void castRay(sf::Vector2f point, float direction)
 | 
					static float castRay(sf::Vector2f point, float direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const sf::Vector2u windowSize = window->getSize();
 | 
						const sf::Vector2u windowSize = window->getSize();
 | 
				
			||||||
	const unsigned int tileWidth = windowSize.x/WIDTH;
 | 
						const unsigned int tileWidth = windowSize.x/WIDTH;
 | 
				
			||||||
	const unsigned int tileHeight = windowSize.y/HEIGHT;
 | 
						const unsigned int tileHeight = windowSize.y/HEIGHT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// dx and dy are the delta x and delta y of closest grid intersection
 | 
					 | 
				
			||||||
	int indexX, indexY;
 | 
						int indexX, indexY;
 | 
				
			||||||
	float dx, dy;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	getGridIndex(point, &indexX, &indexY);
 | 
						getGridIndex(point, &indexX, &indexY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	direction = maths_modulo(direction, 2.0f*PI);
 | 
						// The horizontal* and vertical* variables correspond to variables, that
 | 
				
			||||||
 | 
						// are used to calculate the horizontal and vertical grid intersection points
 | 
				
			||||||
 | 
						// respectively. The horizontal and vertical grid intersections are done 
 | 
				
			||||||
 | 
						// separately.
 | 
				
			||||||
 | 
						// 
 | 
				
			||||||
 | 
						// The *Dy and *Dx variables are the deltas to the nearest grid boundary.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// The *StepX and *StepY variables are the regular x and y steps from the 
 | 
				
			||||||
 | 
						// initial boundary intersection along the ray.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// The *ProjectedX and *ProjectedY variables are projected coordinates of the 
 | 
				
			||||||
 | 
						// grid intersections along the ray.
 | 
				
			||||||
 | 
						// 
 | 
				
			||||||
 | 
						// The *DistCoeff variables store the coefficient of sin(direction) used to 
 | 
				
			||||||
 | 
						// calculate distance travelled along the ray, without having to do extra
 | 
				
			||||||
 | 
						// calls to sin(), as the direction doesn't change.
 | 
				
			||||||
 | 
						direction = maths_modulo(direction, 2.0f*PI); // modulo to keep the angle between 0 and 2 PI radians
 | 
				
			||||||
	bool goingDown = direction < PI;
 | 
						bool goingDown = direction < PI;
 | 
				
			||||||
	int signDown = goingDown? 1 : -1;
 | 
						int signDown = goingDown? 1 : -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dy = (float)((indexY + goingDown) * tileHeight) - point.y;
 | 
						float horizontalDy = (float)((indexY + goingDown) * tileHeight) - point.y;
 | 
				
			||||||
	dx = dy/tan(direction);
 | 
						float horizontalDx = horizontalDy/tan(direction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	float horizontalStepX = (float)(signDown * (tileWidth/tan(direction)));
 | 
						float horizontalStepX = (float)(signDown * (tileWidth/tan(direction)));
 | 
				
			||||||
	float horizontalStepY = (float)(signDown * (int)tileHeight);
 | 
						float horizontalStepY = (float)(signDown * (int)tileHeight);
 | 
				
			||||||
	float horizontalProjectedX = point.x + dx;
 | 
						float horizontalProjectedX = point.x + horizontalDx;
 | 
				
			||||||
	float horizontalProjectedY = (indexY + goingDown) * tileHeight;
 | 
						float horizontalProjectedY = (indexY + goingDown) * tileHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	direction = maths_modulo(direction + 0.5f*PI, 2.0f*PI);
 | 
						float horizontalDistCoeff = sin(direction);
 | 
				
			||||||
 | 
						float horizontalRayDist = std::abs(horizontalDy/horizontalDistCoeff);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						direction = maths_modulo(direction + 0.5f*PI, 2.0f*PI); // rotate angle by 90 degrees for ease of calaculation
 | 
				
			||||||
	bool goingRight = direction < PI;
 | 
						bool goingRight = direction < PI;
 | 
				
			||||||
	int signRight = goingRight? 1 : -1;
 | 
						int signRight = goingRight? 1 : -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dx = (float)((indexX + goingRight) * tileWidth) - point.x;
 | 
						float verticalDx = (float)((indexX + goingRight) * tileWidth) - point.x;
 | 
				
			||||||
	dy = -dx/tan(direction);
 | 
						float verticalDy = -verticalDx/tan(direction); // y axis needs to be flipped 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	float verticalStepY = -(float)(signRight * (tileHeight/tan(direction)));
 | 
						float verticalStepY = -(float)(signRight * (tileHeight/tan(direction))); // y axis also flipped here
 | 
				
			||||||
	float verticalStepX = (float)(signRight * (int)tileHeight);
 | 
						float verticalStepX = (float)(signRight * (int)tileHeight);
 | 
				
			||||||
	float verticalProjectedY = point.y + dy;
 | 
						float verticalProjectedY = point.y + verticalDy;
 | 
				
			||||||
	float verticalProjectedX = (indexX + goingRight) * tileWidth;
 | 
						float verticalProjectedX = (indexX + goingRight) * tileWidth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool inLevel; 
 | 
						float verticalDistCoeff = sin(direction);
 | 
				
			||||||
	do {
 | 
						float verticalRayDist = std::abs(verticalDx/verticalDistCoeff);
 | 
				
			||||||
		const float circleRadius = 3.f;
 | 
					 | 
				
			||||||
		sf::CircleShape circle(circleRadius);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		circle.setFillColor(sf::Color::Red);
 | 
						while (true) {
 | 
				
			||||||
 | 
							int indexX0, indexY0; // store grid indices for horizontal intersections
 | 
				
			||||||
 | 
							int indexX1, indexY1; // store grid indices for vertical intersections
 | 
				
			||||||
 | 
							getGridIndex(sf::Vector2f(horizontalProjectedX, horizontalProjectedY), &indexX0, &indexY0);
 | 
				
			||||||
 | 
							getGridIndex(sf::Vector2f(verticalProjectedX,   verticalProjectedY),   &indexX1, &indexY1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		circle.setPosition(sf::Vector2f(horizontalProjectedX, horizontalProjectedY));
 | 
							// If the ray going up or to left, the intersection points will give an index 
 | 
				
			||||||
		circle.setOrigin(circleRadius, circleRadius);
 | 
							// of the cells below or to the right of the cell boundaries. For those cases, 
 | 
				
			||||||
		window->draw(circle);
 | 
							// the appropriate indices will be reduced by one.
 | 
				
			||||||
 | 
							indexY0 -= !goingDown;
 | 
				
			||||||
 | 
							indexX1 -= !goingRight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		circle.setPosition(sf::Vector2f(verticalProjectedX, verticalProjectedY));
 | 
							bool inLevel0 = indexX0 != -1 && indexY0 != -1;
 | 
				
			||||||
		circle.setOrigin(circleRadius, circleRadius);
 | 
							bool inLevel1 = indexX1 != -1 && indexY1 != -1;
 | 
				
			||||||
		window->draw(circle);
 | 
					
 | 
				
			||||||
 | 
							if (!(inLevel0 || inLevel1)) break; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (horizontalRayDist < verticalRayDist) {
 | 
				
			||||||
 | 
								if (level[indexY0 * WIDTH + indexX0]) return horizontalRayDist;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			horizontalProjectedX += horizontalStepX;
 | 
								horizontalProjectedX += horizontalStepX;
 | 
				
			||||||
			horizontalProjectedY += horizontalStepY;
 | 
								horizontalProjectedY += horizontalStepY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								horizontalRayDist += std::abs(horizontalStepY/horizontalDistCoeff);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								if (level[indexY1 * WIDTH + indexX1]) return verticalRayDist;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			verticalProjectedX += verticalStepX;
 | 
								verticalProjectedX += verticalStepX;
 | 
				
			||||||
			verticalProjectedY += verticalStepY;
 | 
								verticalProjectedY += verticalStepY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int indexX0, indexY0;
 | 
								verticalRayDist += std::abs(verticalStepX/verticalDistCoeff);
 | 
				
			||||||
		int indexX1, indexY1;
 | 
							}
 | 
				
			||||||
		getGridIndex(sf::Vector2f(horizontalProjectedX, horizontalProjectedY), &indexX0, &indexY0);
 | 
						};
 | 
				
			||||||
		getGridIndex(sf::Vector2f(verticalProjectedX,   verticalProjectedY),   &indexX1, &indexY1);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool inLevel0 = ((indexX0 >= 0 && indexX0 < WIDTH) && (indexY0 >= 0 && indexY0 < HEIGHT));
 | 
						return 1000.f;
 | 
				
			||||||
		bool inLevel1 = ((indexX1 >= 0 && indexX1 < WIDTH) && (indexY1 >= 0 && indexY1 < HEIGHT));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		inLevel = inLevel0 || inLevel1;
 | 
					 | 
				
			||||||
	} while (inLevel);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void getGridIndex(sf::Vector2f point, int* x, int* y)
 | 
					static void getGridIndex(sf::Vector2f point, int* x, int* y)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								view.cpp
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								view.cpp
									
									
									
									
									
								
							@ -12,7 +12,7 @@ static sf::Uint32 style = sf::Style::Titlebar;
 | 
				
			|||||||
static sf::RenderWindow window(sf::VideoMode(500, 500), "Raycasting", style);
 | 
					static sf::RenderWindow window(sf::VideoMode(500, 500), "Raycasting", style);
 | 
				
			||||||
static sf::Clock timer;
 | 
					static sf::Clock timer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static Camera camera = { sf::Vector2f(300.f, 250.f), 0.f, 50, 2.0f*PI };
 | 
					static Camera camera = { sf::Vector2f(300.f, 250.f), 0.f, 100, 2.0f*PI };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int view_init()
 | 
					int view_init()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user