Implement DDA raycasting, fix bug in path smoothing

This commit is contained in:
2023-11-25 10:56:26 +01:00
parent 2c3ee8afd6
commit 6240eeea1c
4 changed files with 86 additions and 21 deletions

View File

@@ -5,6 +5,7 @@
#include "../math/vec2i.h"
#include <cute_tiled.h>
#include <raymath.h>
#include <string.h>
BzTileMap BZ_TILEMAP_INVALID = {.isValid = false};
@@ -381,6 +382,80 @@ BzTileObjectGroup *bzTileMapGetObjects(BzTileMap *map, i32 slotID) {
BZ_ASSERT(slotID >= 0 && slotID < map->objectGroupCount);
return &map->objectGroups[slotID];
}
static f32 abs(f32 x) {
return x > 0 ? x : -x;
}
f32 bzTileMapRayCast(BzTileMap *map, Vector2 from, Vector2 to, f32 maxDst, Vector2 *outIntersection) {
// Digital Differential Analyzer (DDA)
Vector2 scale = {1.0f / map->tileWidth, 1.0f / map->tileHeight};
from = Vector2Multiply(from, scale);
to = Vector2Multiply(to, scale);
Vector2 dir = Vector2Subtract(to, from);
dir = Vector2Normalize(dir);
//Vector2 stepSize = {
// sqrtf(1 + (dir.y / dir.x) * (dir.y / dir.x)),
// sqrtf(1 + (dir.x / dir.y) * (dir.x / dir.y))
//};
Vector2 stepSize = {abs(1.0f / dir.x), abs(1.0f / dir.y)};
i32 cellX = (i32) from.x;
i32 cellY = (i32) from.y;
if (bzTileMapHasCollision(map, cellX, cellY)) {
return 0.0f;
}
Vector2 rayLength = Vector2Zero();
i32 stepX, stepY;
if (dir.x < 0) {
stepX = -1;
rayLength.x = (from.x - (f32) (cellX)) * stepSize.x;
} else {
stepX = 1;
rayLength.x = ((f32) cellX + 1.0f - from.x) * stepSize.x;
}
if (dir.y < 0) {
stepY = -1;
rayLength.y = (from.y - (f32) cellY) * stepSize.y;
} else {
stepY = 1;
rayLength.y = ((f32) cellY + 1 - from.y) * stepSize.y;
}
f32 distance = 0.0f;
while (distance < maxDst) {
if (rayLength.x < rayLength.y) {
cellX += stepX;
distance = rayLength.x * map->tileWidth;
rayLength.x += stepSize.x;
} else {
cellY += stepY;
distance = rayLength.y * map->tileHeight;
rayLength.y += stepSize.y;
}
if (cellX >= 0 && cellX < map->width && cellY >= 0 && cellY < map->height &&
map->collisionMap[cellY * map->width + cellX]) {
break;
}
}
if (outIntersection) {
Vector2 intersection = from;
intersection = Vector2Add(intersection, Vector2Scale(dir, distance));
intersection.x *= map->tileWidth;
intersection.y *= map->tileHeight;
*outIntersection = intersection;
}
return distance;
}
bool bzTileMapCanRayCastLine(BzTileMap *map, Vector2 from, Vector2 to) {
f32 dst = Vector2Distance(from, to);
f32 rayDst = bzTileMapRayCast(map, from, to, dst, NULL);
return rayDst >= dst;
}
void bzTileMapDraw(BzTileMap *map) {
for (i32 i = 0; i < map->layerCount; i++) {