Rework input

This commit is contained in:
2023-12-07 14:19:10 +01:00
parent d3485303c9
commit 8543cc7b43
6 changed files with 220 additions and 122 deletions

View File

@@ -8,8 +8,8 @@
Rectangle calculateEntityBounds(Position pos, Size size);
bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Rectangle *outBounds);
void pickEntity(BzSpatialGrid *entityGrid, Vector2 point);
void pickEntities(BzSpatialGrid *entityGrid, Rectangle area);
bool pickEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag);
void pickUnits(BzSpatialGrid *entityGrid, Rectangle area);
static void iterateSelectedUnits(ecs_query_t *query, void (*fn)(ecs_entity_t entity, Position *pos, Size *size));
static void iterRemovePaths(ecs_entity_t entity, Position *pos, Size *size);
@@ -23,7 +23,7 @@ static bool wasInputDragged(InputState *input) {
return IsMouseButtonReleased(input->LMB) && input->mouseDownElapsed > input->CLICK_LIMIT;
}
static bool wasInputClicked(InputState *input) {
return IsMouseButtonReleased(input->LMB);
return IsMouseButtonReleased(input->LMB) && input->mouseDownElapsed <= input->CLICK_LIMIT;
}
void updatePlayerInput() {
@@ -34,10 +34,10 @@ void updatePlayerInput() {
Game *game = ecs_singleton_get_mut(ECS, Game);
InputState *input = ecs_singleton_get_mut(ECS, InputState);
if (IsKeyDown(KEY_W)) game->camera.target.y -= 20;
if (IsKeyDown(KEY_S)) game->camera.target.y += 20;
if (IsKeyDown(KEY_A)) game->camera.target.x -= 20;
if (IsKeyDown(KEY_D)) game->camera.target.x += 20;
if (IsKeyDown(KEY_W)) game->camera.target.y -= 5;
if (IsKeyDown(KEY_S)) game->camera.target.y += 5;
if (IsKeyDown(KEY_A)) game->camera.target.x -= 5;
if (IsKeyDown(KEY_D)) game->camera.target.x += 5;
if (IsKeyDown(KEY_Q)) game->camera.rotation--;
if (IsKeyDown(KEY_E)) game->camera.rotation++;
@@ -57,30 +57,39 @@ void updatePlayerInput() {
Vector2 worldPos = GetScreenToWorld2D(GetMousePosition(), game->camera);
BzTile tileX = 0, tileY = 0;
bzTileMapPosToTile(map, worldPos, &tileX, &tileY);
i32 selectedUnitCount = ecs_query_entity_count(input->unitSelectedQuery);
switch (input->state) {
case INPUT_NONE:
if (wasInputDragged(input)) {
if (selectedUnitCount > 0) {
input->state = INPUT_SELECTED_UNITS;
break;
case INPUT_NONE: {
if (isInputDragged(input)) {
Vector2 start = input->mouseDownWorld;
Vector2 end = worldPos;
if (start.x > end.x) {
f32 tmp = start.x;
start.x = end.x;
end.x = tmp;
}
} else if (wasInputClicked(input)) {
// Click
// 1. Entity
if (selectedUnitCount > 0) {
input->state = INPUT_SELECTED_UNITS;
break;
if (start.y > end.y) {
f32 tmp = start.y;
start.y = end.y;
end.y = tmp;
}
// 2. Object
// 3. Building
input->pickArea = (Rectangle) {start.x, start.y, end.x - start.x, end.y - start.y};
pickUnits(game->entityGrid, input->pickArea);
}
i32 selectedCount = ecs_query_entity_count(input->queries.selected);
if (wasInputClicked(input)) {
if (pickEntity(game->entityGrid, input->mouseDownWorld, Unit)) {
input->state = INPUT_SELECTED_UNITS;
} else if (pickEntity(game->entityGrid, input->mouseDownWorld, Harvestable)) {
input->state = INPUT_SELECTED_OBJECT;
} else if (pickEntity(game->entityGrid, input->mouseDownWorld, Buildable)) {
input->state = INPUT_SELECTED_BUILDING;
}
} else if (wasInputDragged(input) && selectedCount > 0) {
input->state = INPUT_SELECTED_UNITS;
}
break;
case INPUT_BUILDING:
}
case INPUT_BUILDING: {
if (IsKeyPressed(input->ESC) ||
IsMouseButtonPressed(input->RMB) ||
input->building == 0) {
@@ -99,15 +108,17 @@ void updatePlayerInput() {
input->buildingPos = (TilePosition) {tileX, tileY};
input->buildingSize = (TileSize) {sizeX, sizeY};
break;
case INPUT_SELECTED_UNITS:
}
case INPUT_SELECTED_UNITS: {
if (IsKeyPressed(input->ESC) || IsMouseButtonPressed(input->RMB)) {
ecs_remove_all(ECS, UnitSelected);
ecs_remove_all(ECS, Selected);
input->state = INPUT_NONE;
break;
}
if (selectedUnitCount > 1 && wasInputDragged(input)) {
i32 selectedCount = ecs_query_entity_count(input->queries.selected);
if (selectedCount > 1 && wasInputDragged(input)) {
// TODO: For click it should just move them
i32 numUnits = selectedUnitCount;
i32 numUnits = selectedCount;
f32 unitSpacing = 3.5f;
bzArrayClear(input->unitPositions);
placeUnits(numUnits, unitSpacing, input->mouseDownWorld, worldPos,
@@ -117,10 +128,10 @@ void updatePlayerInput() {
i32 unitPosIdx = 0;
ecs_defer_begin(ECS);
iterateSelectedUnits(input->unitSelectedQuery, iterRemovePaths);
iterateSelectedUnits(input->queries.selected, iterRemovePaths);
ecs_defer_end(ECS);
ecs_iter_t it = ecs_query_iter(ECS, input->unitSelectedQuery);
ecs_iter_t it = ecs_query_iter(ECS, input->queries.selected);
ecs_defer_begin(ECS);
while (ecs_iter_next(&it)) {
Position *pos = ecs_field(&it, Position, 1);
@@ -149,10 +160,10 @@ void updatePlayerInput() {
ecs_defer_end(ECS);
} else if (wasInputClicked(input)) {
ecs_defer_begin(ECS);
iterateSelectedUnits(input->unitSelectedQuery, iterRemovePaths);
iterateSelectedUnits(input->queries.selected, iterRemovePaths);
ecs_defer_end(ECS);
ecs_iter_t it = ecs_query_iter(ECS, input->unitSelectedQuery);
ecs_iter_t it = ecs_query_iter(ECS, input->queries.selected);
ecs_defer_begin(ECS);
while (ecs_iter_next(&it)) {
@@ -163,12 +174,12 @@ void updatePlayerInput() {
Path path = {NULL, 0};
pathfindAStar(&(PathfindingDesc) {
.start=pos[i],
.target=worldPos,
.map=map,
.outPath=&path,
.pool=game->pools.pathData,
.alloc=&game->stackAlloc
.start=pos[i],
.target=worldPos,
.map=map,
.outPath=&path,
.pool=game->pools.pathData,
.alloc=&game->stackAlloc
});
if (!path.paths) continue;
ecs_set_ptr(ECS, entity, Path, &path);
@@ -178,10 +189,16 @@ void updatePlayerInput() {
ecs_defer_end(ECS);
}
break;
}
case INPUT_SELECTED_OBJECT:
break;
case INPUT_SELECTED_BUILDING:
if (IsKeyPressed(input->ESC) || IsMouseButtonPressed(input->RMB)) {
ecs_remove_all(ECS, Selected);
input->state = INPUT_NONE;
break;
}
break;
}
}
@@ -191,26 +208,12 @@ void drawPlayerInputUI() {
BzTileMap *map = &game->map;
Vector2 worldPos = GetScreenToWorld2D(GetMousePosition(), game->camera);
i32 selectedUnitCount = ecs_count_id(ECS, UnitSelected);
i32 selectedUnitCount = ecs_count_id(ECS, Selected);
switch (input->state) {
case INPUT_NONE:
if (isInputDragged(input)) {
Vector2 start = input->mouseDownWorld;
Vector2 end = worldPos;
if (start.x > end.x) {
f32 tmp = start.x;
start.x = end.x;
end.x = tmp;
}
if (start.y > end.y) {
f32 tmp = start.y;
start.y = end.y;
end.y = tmp;
}
Rectangle area = {start.x, start.y, end.x - start.x, end.y - start.y};
Rectangle area = input->pickArea;
DrawRectangleLines(area.x, area.y, area.width, area.height, RED);
pickEntities(game->entityGrid, area);
}
break;
case INPUT_BUILDING: {
@@ -243,12 +246,8 @@ void drawPlayerInputUI() {
break;
}
case INPUT_SELECTED_OBJECT:
break;
case INPUT_SELECTED_BUILDING:
break;
}
ecs_iter_t it = ecs_query_iter(ECS, input->unitSelectedQuery);
ecs_iter_t it = ecs_query_iter(ECS, input->queries.selected);
rlSetLineWidth(2.0f);
while (ecs_query_next(&it)) {
Position *pos = ecs_field(&it, Position, 1);
@@ -298,13 +297,15 @@ bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Recta
return true;
}
void pickEntity(BzSpatialGrid *entityGrid, Vector2 point) {
ecs_remove_all(ECS, UnitSelected);
bool pickEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag) {
ecs_remove_all(ECS, Selected);
BzSpatialGridIter it = bzSpatialGridIter(entityGrid, point.x, point.y, 0.0f, 0.0f);
f32 closestDst = INFINITY;
ecs_entity_t closest = 0;
while (bzSpatialGridQueryNext(&it)) {
ecs_entity_t entity = *(ecs_entity_t *) it.data;
if (!ecs_has_id(ECS, entity, Selectable)) continue;
if (!ecs_has_id(ECS, entity, tag)) continue;
Vector2 pos;
Rectangle bounds;
if (!getEntityBounds(entity, &pos, NULL, &bounds)) continue;
@@ -318,20 +319,23 @@ void pickEntity(BzSpatialGrid *entityGrid, Vector2 point) {
}
}
if (closest) {
ecs_add(ECS, closest, UnitSelected);
ecs_add(ECS, closest, Selected);
return true;
}
return false;
}
void pickEntities(BzSpatialGrid *entityGrid, Rectangle area) {
ecs_remove_all(ECS, UnitSelected);
void pickUnits(BzSpatialGrid *entityGrid, Rectangle area) {
ecs_remove_all(ECS, Selected);
BzSpatialGridIter it = bzSpatialGridIter(entityGrid, area.x, area.y, area.width, area.height);
while (bzSpatialGridQueryNext(&it)) {
ecs_entity_t entity = *(ecs_entity_t *) it.data;
if (!ecs_has_id(ECS, entity, Unit)) continue;
Rectangle bounds;
if (!getEntityBounds(entity, NULL, NULL, &bounds)) continue;
if (!CheckCollisionRecs(area, bounds)) continue;
ecs_add(ECS, entity, UnitSelected);
ecs_add(ECS, entity, Selected);
}
}