Rework pathfinding to use Vector2, form formations
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user