Knowledge is a human construct, made to communicate how we conceive the things around us. That I earnestly believe in.
Ray casting is a fundamental technique in game development, allowing for the creation of 2D and 3D environments with believable lighting and shadows. In Pygame, ray casting can be implemented using basic trigonometry. By leveraging the power of trigonometric functions such as sine, cosine, and tangent, you can create immersive and interactive environments that simulate real-world physics.
The tutorial's iteration of collision logic borrows tuples from mini_map, which are wall coordinates, to simulate collision. If player coordinates will be equal to one of the tuple coordinates, player coordinates will not be increased until it changes course.
Since the code for coordinate updating (actually just addition) is already in the collision method, you can replace the former with the latter in the player movement method.
Keep your eyes on the road, stranger.
Ray casting simulates the way light behaves in the real world. It involves casting imaginary rays from the viewer's perspective into the scene and determining which objects the rays intersect with.
To understand ray casting, one must first cover basic trigonometry as the concept heavily relies on it, particularly the use of angles, sine, cosine, and tangent. All aforementioned concepts will be not explained in-depth in this and all upcoming sections of my blog.
This iteration proposes calculating the player's exact position, which will be used for precise collision detection and rendering, and map position, which will be used for tile-based logic (i.e., wall collision).
In this iteration of ray casting, the player's field-of-view is divided into discrete units, with each unit representing a ray cast from the player's position. The player's forward-facing angle is calculated by subtracting half their field-of-view from the player's current angle, plus a small offset value of 0.0001. This offset is likely used to avoid division by zero or other numerical issues.
Continuing with the same method, the program detects the player's direction in terms of right and left with the cosine value. A positive cosine value says that the player is facing the right side of their current direction, while a negative cosine value says the player is facing left instead. If neither are True, then the player is facing their middle.
Vertical depth represents the distance from the player's eye to the wall along the y-axis (up/down direction). Vertical depth is affected by the player's pitch (looking up or down) and the wall's height. To determine if the closest point of a wall-touching rat is a vertical depth point, check if the following conditions are met:
y-coordinate is an integer, indicating that the ray has intersected with a horizontal grid line.
x-coordinate is a fraction, indicating that the ray has intersected with a vertical grid line at a non-integer x-coordinate.
Distance along y-axis is smaller than distance along x-axis, which ensures that intersection point is closer to player in vertical direction than in horizontal.
On the other hand, horizontal depth represents the distance from the player's eye to the wall along the x-axis (left/right direction). Horizontal depth is affected by the player's yaw (turning left/right) and the wall's width.
To determine if the closest point of a wall-touching rat is a horizontal depth point, swap the x- and y-coordinate conditions for determining a closer vertical depth point and flip the distance among axes condition (x-axis distance > y-axis distance).
Together with the vertical data section, ray_cast() calculates the coordinates of ray intersection points by comparing the depths of the intersections. To summarize in order:
Both sections calculate intersection points of the ray with vertical and horizontal grid lines, respectively.
Depths of intersections are calculated and compared to determine which intersection point is closer to the origin.
Intersection point with smaller depth is chosen as final intersection point.
Coordinates of final intersection (x and y) point are then used to render the 2D environment.
To view and debug your field-of-vision, you can use the draw.line() script below to draw a sector depicting it.
Like shining a flashlight in a dark mansion.