Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added comments for shader file and a bit for pathfinding algorithm #74

Merged
merged 1 commit into from
Apr 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 51 additions & 11 deletions src/assets/shaders/lights.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,41 @@ uniform int obstaclesCount;

bool segmentsIntersection(vec2 first, vec2 second, vec2 third, vec2 fourth)
{
vec3 r = vec3(second - first, 0.0);
vec3 s = vec3(fourth - third, 0.0);
vec3 first_third = vec3(third - first, 0.0);
/*
Checks if two segments intersect
vec2 first: x, y of the first end of the first segment
vec2 second: x, y of the second end of the first segment
vec2 third: x, y of the first end of the second segment
vec2 fourth: x, y of the second end of the second segment

float t_numerator = cross(first_third, s).z;
float u_numerator = cross(first_third, r).z;
float denominator = cross(r, s).z;
return bool: true if segments intersect, false if not

if (abs(denominator) <= 1e-8)
return false;
to get familiar with what's going on here, you can read the following article on wikipedia:
https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line_segment
*/

vec3 r = vec3(second - first, 0.0); // the same as (x2 - x1, y2 - y1) in the article
vec3 s = vec3(fourth - third, 0.0); // the same as (x4 - x3, y4 - y3) in the article
vec3 first_third = vec3(third - first, 0.0); // the same as (x3 - x1, y3 - y1) in the article

// these three vectors are three-dimensional, because I decided to find determinant using cross-product
// of two two-dimensional vectors

float t_numerator = cross(first_third, s).z; // numerator of t from the article
float u_numerator = cross(first_third, r).z; // numerator of u from the article
float denominator = cross(r, s).z; // denominator from the article (t and u have the same denominator)

if (abs(denominator) <= 1e-8) // if determinant is zero (or approximately equal to), then
return false; // the segments are parallel therefore do not intersect

// then we should test if t and u are in the interval [0, 1], if they are then segments intersecting
// but division is time-consuming operation, doing some math, we can avoid division
// that is what's going on in the lines below

// if both numerator and denominator are positive
if (0.0 <= t_numerator && t_numerator <= denominator && 0.0 <= u_numerator && u_numerator <= denominator)
return true;
// if both numerator and denominator are negative
else if (denominator <= t_numerator && t_numerator <= 0.0 && denominator <= u_numerator && u_numerator <= 0.0)
return true;
else
Expand All @@ -35,6 +57,17 @@ bool segmentsIntersection(vec2 first, vec2 second, vec2 third, vec2 fourth)

bool segmentRectangleIntersection(vec4 segment, vec4 rectangle)
{
/*
Checks if given segment intersects given rectangle
vec4 segment: x, y of the first end of the segment and x, y of the second end of the segment
vec4 rectangle x, y of the top left vertex of the rectangle and x, y of the bottom right vertex

return bool: true if a segment intersects rectangle else false

if a line intersects a rectangle, then it intersects at least one of it's diagonal,
hence instead of checking four sides, we can check for intersection only diagonals
the game draws obstacles after calculating the lights, hence in the end we obtain a nice picture
*/
vec4 firstDiagonal = rectangle;
vec4 secondDiagonal = vec4(rectangle.z, rectangle.y, rectangle.x, rectangle.w);

Expand All @@ -49,11 +82,18 @@ bool segmentRectangleIntersection(vec4 segment, vec4 rectangle)

float computeLight(vec3 light, vec2 pixelPosition)
{
/*
Calculates how much light is in given point
vec3 light: x, y, radius of a light
vec2 pixelPosition: x, y of a pixel that we are checking

return float: number in interval [0, 1] that tells us how much light in the pixel
*/
float _distance = length(light.xy - pixelPosition);

vec4 segment = vec4(light.xy, pixelPosition);


// Check every rectangle (obstacle) on a game plane
for (int i = 0; i < obstaclesCount; ++i)
if (segmentRectangleIntersection(segment, obstacles[i].xyzw))
return 0.0;
Expand All @@ -70,8 +110,8 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
for (int i = 0; i < lightCount; ++i)
{
float lightAmount = computeLight(lightSources[i].xyz, fragCoord);
vec4 color = mix(blackColor, LIGHT_COLOR, lightAmount);
preFragColor = mix(preFragColor, color, lightAmount);
vec4 color = mix(blackColor, LIGHT_COLOR, lightAmount); // mix obtained light amount with light color
preFragColor = mix(preFragColor, color, lightAmount); // mix obtained color with color of texture
}

fragColor = preFragColor;
Expand Down
5 changes: 3 additions & 2 deletions src/classes/world.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,16 @@ def tile_to_screen(self, tile_x: int, tile_y: int) -> tuple[int, int]:
@lru_cache()
def pathfinding(self, start: tuple[int, int], destination: tuple[int, int]) -> list[tuple[int, int]] | None:
"""
A* algorithm realization
Uses manhattan distance as heuristics

:param start: tuple of absolute coordinates of start position
:param destination: tuple of absolute coordinates of destination position
:return: list of absolute coordinates or None if path not found
"""

start_tile = self.screen_to_tile(*start)
destination_tile = self.screen_to_tile(*destination)
print(self.grid[destination_tile])
print(destination_tile)

lengths = np.full((int(self.map.width), int(self.map.height)), -1)
lengths[start_tile] = 0
Expand Down