Rework pathfinding to use Vector2, form formations

This commit is contained in:
2023-11-23 12:01:42 +01:00
parent 513168825c
commit 0dc8046d8f
6 changed files with 129 additions and 85 deletions

View File

@@ -8,6 +8,15 @@
void pickEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t **outEntities);
void pickEntities(BzSpatialGrid *entityGrid, Rectangle area, ecs_entity_t **outEntities);
static void placeUnits(i32 numUnits, f32 unitSpacing, Vector2 start, Vector2 end, BzTileMap *map, Vector2 **outPlaces);
static bool wasInputDragged(InputState *input) {
return IsMouseButtonReleased(input->LMB) && input->mouseDownElapsed > input->CLICK_LIMIT;
}
static bool wasInputClicked(InputState *input) {
return IsMouseButtonReleased(input->LMB);
}
void updatePlayerInput(ecs_iter_t *it) {
f32 dt = GetFrameTime();
ImGuiIO *io = igGetIO();
@@ -37,11 +46,11 @@ void updatePlayerInput(ecs_iter_t *it) {
}
Vector2 worldPos = GetScreenToWorld2D(GetMousePosition(), game->camera);
int tileX = (int) worldPos.x / map->tileWidth;
int tileY = (int) worldPos.y / map->tileHeight;
BzTile tileX = 0, tileY = 0;
bzTileMapPosToTile(map, worldPos, &tileX, &tileY);
switch (input->state) {
case INPUT_NONE:
if (IsMouseButtonReleased(input->LMB) && input->mouseDownElapsed > input->CLICK_LIMIT) {
if (wasInputDragged(input)) {
// Dragging
Vector2 start = input->mouseDownWorld;
@@ -64,7 +73,7 @@ void updatePlayerInput(ecs_iter_t *it) {
break;
}
} else if (IsMouseButtonReleased(input->LMB)) {
} else if (wasInputClicked(input)) {
// Click
// 1. Entity
@@ -103,7 +112,37 @@ void updatePlayerInput(ecs_iter_t *it) {
input->state = INPUT_NONE;
break;
}
if (IsMouseButtonPressed(input->LMB)) {
if (bzArraySize(input->entities) > 1 && wasInputDragged(input)) {
// TODO: For click it should just move them
i32 numUnits = bzArraySize(input->entities);
f32 unitSpacing = 3.5f;
Vector2 *unitPositions = bzArrayCreate(Position, numUnits);
placeUnits(numUnits, unitSpacing, input->mouseDownWorld, worldPos,
map, &unitPositions);
BZ_ASSERT(bzArraySize(unitPositions) == numUnits);
bzArrayFor(unitPositions, i) {
Position target = bzArrayGet(unitPositions, i);
ecs_entity_t entity = bzArrayGet(input->entities, i);
const Position *start = ecs_get(ECS, entity, Position);
Path path = {NULL, 0};
findPath(&(PathfindingDesc) {
.start=*start,
.target=target,
.map=map,
.outPath=&path,
.pool=game->pools.pathData
});
if (!path.paths) continue;
ecs_set_ptr(ECS, entity, Path, &path);
input->state = INPUT_NONE;
}
bzArrayDestroy(unitPositions);
} else if (wasInputClicked(input)) {
bzArrayFor(input->entities, i) {
ecs_entity_t entity = bzArrayGet(input->entities, i);
ecs_remove(ECS, entity, Path);
@@ -111,12 +150,9 @@ void updatePlayerInput(ecs_iter_t *it) {
const Position *start = ecs_get(ECS, entity, Position);
Path path = {NULL, 0};
findPath(&(PathfindingDesc) {
.start=(TilePosition) {
start->x / game->map.tileWidth,
start->y / game->map.tileHeight,
},
.target=(TilePosition) {tileX, tileY},
.map=&game->map,
.start=*start,
.target=worldPos,
.map=map,
.outPath=&path,
.pool=game->pools.pathData
});
@@ -200,3 +236,43 @@ void pickEntities(BzSpatialGrid *entityGrid, Rectangle area, ecs_entity_t **outE
bzArrayPush(*outEntities, entity);
}
}
static bool isUnitObstructed(f32 x, f32 y, BzTileMap *map) {
return bzTileMapHasCollision(map, x / map->tileWidth, y / map->tileHeight);
}
static bool canPlaceUnit(Vector2 pos, f32 space, BzTileMap *map) {
for (i32 y = -1; y <= 1; y++) {
for (i32 x = -1; x <= 1; x++) {
if (isUnitObstructed(pos.x + x * space, pos.y + y * space, map))
return false;
}
}
return true;
}
void placeUnits(i32 numUnits, f32 unitSpacing, Vector2 start, Vector2 end, BzTileMap *map, Vector2 **outPlaces) {
f32 angle = Vector2Angle(start, end);
f32 lineLength = Vector2Distance(start, end);
Vector2 pos = Vector2Zero();
pos.x = unitSpacing;
for (i32 i = 0; i < numUnits; i++) {
if (pos.x + unitSpacing * 2.0f > lineLength) {
pos.x = unitSpacing;
pos.y += unitSpacing * 2.0f;
}
Vector2 unitPos = Vector2Add(start, Vector2Rotate(pos, angle));
if (!canPlaceUnit(unitPos, 4.0f, map)) {
i--;
} else {
bzArrayPush(*outPlaces, unitPos);
}
pos.x += unitSpacing * 2.0f;
}
}