DDA with Intersection Point

This is a modified version of the Digital Differential Analyzer algorithm. It can keep track of the distance of the ray in order to return the precise intersection point, which is useful for cases like ray casting-based renderers.

This implementation is written in C and makes use of raylib's Vector2 struct. It's pretty conventional, so there should be no issues adapting it.

Constants

#define GRID_DIM_SIZE 32
#define CELL_SIZE 20.0
#define MAX_DISTANCE 100.0

Implementation

// Some basic values to define first:
bool grid[GRID_DIM_SIZE][GRID_DIM_SIZE] = {0};
Vector2 startWorldSpace = {320, 320};
Vector2 endWorldSpace = {400, 270};

// Our results:
bool tileFound = false;
Vector2 intersection = {};

// Scale ray down from world space to grid space:
Vector2 start = Vector2Scale(charPosition, 1.0 / CELL_SIZE);
Vector2 end = Vector2Scale(mousePosition, 1.0 / CELL_SIZE);

Vector2 direction = Vector2Normalize(Vector2Subtract(end, start));

// The slope/gradient of the ray - how far does the hypotenuse move for one step on both axes?
Vector2 stepSize = { sqrt(1 + (direction.y / direction.x) * (direction.y / direction.x)), sqrt(1 + (direction.x / direction.y) * (direction.x / direction.y)) };

Vector2 rayLength = { 0, 0 };

int gridCheckX = start.x, gridCheckY = start.y;
int stepX, stepY;

// We define a step direction, so that we know in which direction to go, and add the sloped gap between the starting tile and its closest boundary for the relevant direction in order to have a starting point for our raycast.

// Define step direction and first hit distance for X axis:
if (direction.x < 0)
{
    stepX = -1;
    rayLength.x = (start.x - gridCheckX) * stepSize.x;
}
else
{
    stepX = 1;
    rayLength.x = ((gridCheckX + 1) - start.x) * stepSize.x;
}

// Define step direction and first hit distance for Y axis:
if (direction.y < 0)
{
    stepY = -1;
    rayLength.y = (start.y - gridCheckY) * stepSize.y;
}
else
{
    stepY = 1;
    rayLength.y = ((gridCheckY + 1) - start.y) * stepSize.y;
}

float distance = 0.0f;

while (!tileFound && distance < MAX_DISTANCE)
{
    if (rayLength.x < rayLength.y)
    {
        gridCheckX += stepX;
        distance = rayLength.x;
        rayLength.x += stepSize.x;
    }
    else
    {
        gridCheckY += stepY;
        distance = rayLength.y;
        rayLength.y += stepSize.y;
    }

    if (gridCheckX >= 0 && gridCheckX < GRID_DIM_SIZE && gridCheckY >= 0 && gridCheckY < GRID_DIM_SIZE)
    {
        if (grid[gridCheckX][gridCheckY])
        {
            tileFound = true;
        }
    }
}

if (tileFound)
{
    intersection = Vector2Add(start, Vector2Scale(direction, distance));
}

Credits

These resources helped with my implementation, you can check them for more information.