Improve input processing
This commit is contained in:
@@ -17,6 +17,8 @@ add_executable(PixelDefense
|
|||||||
game/components.c
|
game/components.c
|
||||||
game/components.h
|
game/components.h
|
||||||
game/entrypoint.c
|
game/entrypoint.c
|
||||||
|
game/game_state.h
|
||||||
|
game/input.h
|
||||||
game/main.c
|
game/main.c
|
||||||
game/map_init.c
|
game/map_init.c
|
||||||
game/map_init.h
|
game/map_init.h
|
||||||
|
|||||||
@@ -16,3 +16,6 @@ target_link_libraries(heap_test LINK_PRIVATE Breeze)
|
|||||||
|
|
||||||
add_executable(array_test array_test.c)
|
add_executable(array_test array_test.c)
|
||||||
target_link_libraries(array_test LINK_PRIVATE Breeze)
|
target_link_libraries(array_test LINK_PRIVATE Breeze)
|
||||||
|
|
||||||
|
add_executable(pan_test pan_test.c)
|
||||||
|
target_link_libraries(pan_test LINK_PRIVATE Breeze)
|
||||||
|
|||||||
@@ -4,48 +4,6 @@
|
|||||||
#include <breeze.h>
|
#include <breeze.h>
|
||||||
#include <flecs.h>
|
#include <flecs.h>
|
||||||
|
|
||||||
typedef enum InputType {
|
|
||||||
INPUT_NONE,
|
|
||||||
INPUT_BUILDING,
|
|
||||||
INPUT_SELECTED_UNITS,
|
|
||||||
INPUT_SELECTED_OBJECT,
|
|
||||||
INPUT_SELECTED_BUILDING,
|
|
||||||
} InputType;
|
|
||||||
|
|
||||||
typedef struct InputState {
|
|
||||||
InputType state;
|
|
||||||
// Input mapping
|
|
||||||
MouseButton LMB;
|
|
||||||
MouseButton RMB;
|
|
||||||
MouseButton MMB;
|
|
||||||
KeyboardKey ESC;
|
|
||||||
f32 CLICK_LIMIT;
|
|
||||||
// Common
|
|
||||||
Vector2 mouseDown;
|
|
||||||
Vector2 mouseDownWorld;
|
|
||||||
f32 mouseDownElapsed;
|
|
||||||
// INPUT_BUILDING
|
|
||||||
int building;
|
|
||||||
bool buildingCanPlace;
|
|
||||||
TilePosition buildingPos;
|
|
||||||
TileSize buildingSize;
|
|
||||||
// Units
|
|
||||||
Rectangle pickArea;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
/* Selected units
|
|
||||||
* 1: Position
|
|
||||||
* 2: Size
|
|
||||||
* 3: UnitSelected
|
|
||||||
*/
|
|
||||||
ecs_query_t *selected;
|
|
||||||
//ecs_query_t *selectedBuilding;
|
|
||||||
} queries;
|
|
||||||
Position *unitPositions;
|
|
||||||
// SELECTED_OBJECT
|
|
||||||
// SELECTED_BUILDING
|
|
||||||
} InputState;
|
|
||||||
|
|
||||||
typedef struct Game {
|
typedef struct Game {
|
||||||
Camera2D camera;
|
Camera2D camera;
|
||||||
BzTileset terrainTileset;
|
BzTileset terrainTileset;
|
||||||
@@ -77,7 +35,6 @@ typedef struct Game {
|
|||||||
|
|
||||||
extern ecs_world_t *ECS;
|
extern ecs_world_t *ECS;
|
||||||
|
|
||||||
extern ECS_COMPONENT_DECLARE(Game);
|
extern ECS_COMPONENT_DECLARE(Game); // defined in main.c
|
||||||
extern ECS_COMPONENT_DECLARE(InputState);
|
|
||||||
|
|
||||||
#endif //PIXELDEFENSE_GAME_STATE_H
|
#endif //PIXELDEFENSE_GAME_STATE_H
|
||||||
|
|||||||
12
game/main.c
12
game/main.c
@@ -4,6 +4,7 @@
|
|||||||
#include "utils/building_types.h"
|
#include "utils/building_types.h"
|
||||||
#include "components.h"
|
#include "components.h"
|
||||||
#include "game_state.h"
|
#include "game_state.h"
|
||||||
|
#include "input.h"
|
||||||
#include "map_init.h"
|
#include "map_init.h"
|
||||||
#include "map_layers.h"
|
#include "map_layers.h"
|
||||||
#include "buildings.h"
|
#include "buildings.h"
|
||||||
@@ -65,11 +66,7 @@ bool init(void *userData) {
|
|||||||
ecs_singleton_set(ECS, InputState, {});
|
ecs_singleton_set(ECS, InputState, {});
|
||||||
InputState *input = ecs_singleton_get_mut(ECS, InputState);
|
InputState *input = ecs_singleton_get_mut(ECS, InputState);
|
||||||
|
|
||||||
input->LMB = MOUSE_LEFT_BUTTON;
|
input->mapping = inputDefaultMapping();
|
||||||
input->RMB = MOUSE_RIGHT_BUTTON;
|
|
||||||
input->MMB = MOUSE_MIDDLE_BUTTON;
|
|
||||||
input->ESC = KEY_ESCAPE;
|
|
||||||
input->CLICK_LIMIT = 0.2f;
|
|
||||||
|
|
||||||
// Create queries
|
// Create queries
|
||||||
input->queries.selected = ecs_query(ECS, {
|
input->queries.selected = ecs_query(ECS, {
|
||||||
@@ -210,11 +207,14 @@ void update(float dt, void *userData) {
|
|||||||
snprintf(titleBuf, sizeof(titleBuf), "FPS: %d | %.2f ms", GetFPS(), GetFrameTime() * 1000);
|
snprintf(titleBuf, sizeof(titleBuf), "FPS: %d | %.2f ms", GetFPS(), GetFrameTime() * 1000);
|
||||||
SetWindowTitle(titleBuf);
|
SetWindowTitle(titleBuf);
|
||||||
|
|
||||||
Game *game = ecs_singleton_get_mut(ECS, Game);
|
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||||
|
InputState *input = ecs_singleton_get_mut(ECS, InputState);
|
||||||
|
|
||||||
BZ_ASSERT(game->stackAlloc.allocated == 0);
|
BZ_ASSERT(game->stackAlloc.allocated == 0);
|
||||||
bzStackAllocReset(&game->stackAlloc);
|
bzStackAllocReset(&game->stackAlloc);
|
||||||
|
|
||||||
|
updateInputState(input, game->camera, dt);
|
||||||
|
|
||||||
updatePlayerInput();
|
updatePlayerInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "game_state.h"
|
#include "game_state.h"
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <raymath.h>
|
#include <raymath.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "systems.h"
|
#include "systems.h"
|
||||||
#include "game_state.h"
|
#include "game_state.h"
|
||||||
|
#include "input.h"
|
||||||
#include "buildings.h"
|
#include "buildings.h"
|
||||||
#include "pathfinding.h"
|
#include "pathfinding.h"
|
||||||
#include <rlImGui.h>
|
#include <rlImGui.h>
|
||||||
@@ -8,6 +9,9 @@
|
|||||||
|
|
||||||
Rectangle calculateEntityBounds(Position pos, Size size);
|
Rectangle calculateEntityBounds(Position pos, Size size);
|
||||||
bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Rectangle *outBounds);
|
bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Rectangle *outBounds);
|
||||||
|
|
||||||
|
ecs_entity_t queryEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag);
|
||||||
|
|
||||||
bool pickEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag);
|
bool pickEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag);
|
||||||
void pickUnits(BzSpatialGrid *entityGrid, Rectangle area);
|
void pickUnits(BzSpatialGrid *entityGrid, Rectangle area);
|
||||||
|
|
||||||
@@ -16,14 +20,43 @@ static void iterRemovePaths(ecs_entity_t entity, Position *pos, Size *size);
|
|||||||
|
|
||||||
void placeUnits(i32 numUnits, f32 unitSpacing, Vector2 start, Vector2 end, BzTileMap *map, Vector2 **outPlaces);
|
void placeUnits(i32 numUnits, f32 unitSpacing, Vector2 start, Vector2 end, BzTileMap *map, Vector2 **outPlaces);
|
||||||
|
|
||||||
static bool isInputDragged(InputState *input) {
|
void inputPrimaryAction(Game *game, InputState *input) {
|
||||||
return IsMouseButtonDown(input->LMB && input->mouseDownElapsed > input->CLICK_LIMIT);
|
const MouseButton primaryBtn = input->mapping.primaryBtn;
|
||||||
|
if (isInputBtnDragged(input, primaryBtn)) {
|
||||||
|
Vector2 start = input->mouseDownWorld;
|
||||||
|
Vector2 end = input->mouseWorld;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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 (isInputBtnJustDragged(input, primaryBtn) && selectedCount > 0) {
|
||||||
|
input->state = INPUT_SELECTED_UNITS;
|
||||||
|
} else if (isInputBtnJustUp(input, primaryBtn)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
selectedCount = ecs_query_entity_count(input->queries.selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedCount == 0)
|
||||||
|
input->state = INPUT_NONE;
|
||||||
}
|
}
|
||||||
static bool wasInputDragged(InputState *input) {
|
void inputUnitAction(Game *game, InputState *input) {
|
||||||
return IsMouseButtonReleased(input->LMB) && input->mouseDownElapsed > input->CLICK_LIMIT;
|
|
||||||
}
|
|
||||||
static bool wasInputClicked(InputState *input) {
|
|
||||||
return IsMouseButtonReleased(input->LMB) && input->mouseDownElapsed <= input->CLICK_LIMIT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updatePlayerInput() {
|
void updatePlayerInput() {
|
||||||
@@ -43,65 +76,33 @@ void updatePlayerInput() {
|
|||||||
if (IsKeyDown(KEY_E)) game->camera.rotation++;
|
if (IsKeyDown(KEY_E)) game->camera.rotation++;
|
||||||
|
|
||||||
|
|
||||||
game->camera.zoom += ((float) GetMouseWheelMove() * 0.05f);
|
game->camera.zoom += GetMouseWheelMove() * 0.05f;
|
||||||
BzTileMap *map = &game->map;
|
BzTileMap *map = &game->map;
|
||||||
|
|
||||||
if (IsMouseButtonPressed(input->LMB)) {
|
BzTile tileX = 0, tileY = 0;
|
||||||
input->mouseDown = GetMousePosition();
|
bzTileMapPosToTile(map, input->mouseWorld, &tileX, &tileY);
|
||||||
input->mouseDownWorld = GetScreenToWorld2D(input->mouseDown, game->camera);
|
|
||||||
input->mouseDownElapsed = 0;
|
if (IsKeyPressed(input->mapping.backBtn)) {
|
||||||
} else if (IsMouseButtonDown(input->LMB)) {
|
ecs_remove_all(ECS, Selected);
|
||||||
input->mouseDownElapsed += dt;
|
input->state = INPUT_NONE;
|
||||||
|
input->building = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 worldPos = GetScreenToWorld2D(GetMousePosition(), game->camera);
|
const MouseButton primaryBtn = input->mapping.primaryBtn;
|
||||||
BzTile tileX = 0, tileY = 0;
|
const MouseButton secondaryBtn = input->mapping.secondaryBtn;
|
||||||
bzTileMapPosToTile(map, worldPos, &tileX, &tileY);
|
|
||||||
switch (input->state) {
|
switch (input->state) {
|
||||||
case INPUT_NONE: {
|
case INPUT_NONE: {
|
||||||
if (isInputDragged(input)) {
|
inputPrimaryAction(game, 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;
|
|
||||||
}
|
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
case INPUT_BUILDING: {
|
case INPUT_BUILDING: {
|
||||||
if (IsKeyPressed(input->ESC) ||
|
|
||||||
IsMouseButtonPressed(input->RMB) ||
|
|
||||||
input->building == 0) {
|
|
||||||
input->state = INPUT_NONE;
|
|
||||||
input->building = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
BZ_ASSERT(input->building);
|
BZ_ASSERT(input->building);
|
||||||
BzTile sizeX = 0, sizeY = 0;
|
BzTile sizeX = 0, sizeY = 0;
|
||||||
getBuildingSize(input->building, &sizeX, &sizeY);
|
getBuildingSize(input->building, &sizeX, &sizeY);
|
||||||
bool canPlace = canPlaceBuilding(&game->map, input->building, tileX, tileY);
|
bool canPlace = canPlaceBuilding(&game->map, input->building, tileX, tileY);
|
||||||
if (canPlace && IsMouseButtonDown(input->LMB)) {
|
if (canPlace && isInputBtnDown(input, primaryBtn)) {
|
||||||
placeBuilding(&game->map, input->building, tileX, tileY);
|
placeBuilding(&game->map, input->building, tileX, tileY);
|
||||||
}
|
}
|
||||||
input->buildingCanPlace = canPlace;
|
input->buildingCanPlace = canPlace;
|
||||||
@@ -110,19 +111,17 @@ void updatePlayerInput() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INPUT_SELECTED_UNITS: {
|
case INPUT_SELECTED_UNITS: {
|
||||||
if (IsKeyPressed(input->ESC) || IsMouseButtonPressed(input->RMB)) {
|
inputPrimaryAction(game, input);
|
||||||
ecs_remove_all(ECS, Selected);
|
if (input->state != INPUT_SELECTED_UNITS) break;
|
||||||
input->state = INPUT_NONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i32 selectedCount = ecs_query_entity_count(input->queries.selected);
|
i32 selectedCount = ecs_query_entity_count(input->queries.selected);
|
||||||
if (selectedCount > 1 && wasInputDragged(input)) {
|
if (selectedCount > 1 && isInputBtnJustDragged(input, secondaryBtn)) {
|
||||||
// TODO: For click it should just move them
|
// TODO: For click it should just move them
|
||||||
i32 numUnits = selectedCount;
|
i32 numUnits = selectedCount;
|
||||||
f32 unitSpacing = 3.5f;
|
f32 unitSpacing = 3.5f;
|
||||||
bzArrayClear(input->unitPositions);
|
bzArrayClear(input->unitPositions);
|
||||||
placeUnits(numUnits, unitSpacing, input->mouseDownWorld, worldPos,
|
placeUnits(numUnits, unitSpacing,
|
||||||
map, &input->unitPositions);
|
input->mouseDownWorld, input->mouseWorld,
|
||||||
|
map, &input->unitPositions);
|
||||||
|
|
||||||
BZ_ASSERT(bzArraySize(input->unitPositions) == numUnits);
|
BZ_ASSERT(bzArraySize(input->unitPositions) == numUnits);
|
||||||
i32 unitPosIdx = 0;
|
i32 unitPosIdx = 0;
|
||||||
@@ -138,8 +137,6 @@ void updatePlayerInput() {
|
|||||||
for (i32 i = 0; i < it.count; i++) {
|
for (i32 i = 0; i < it.count; i++) {
|
||||||
ecs_entity_t entity = it.entities[i];
|
ecs_entity_t entity = it.entities[i];
|
||||||
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
Position target = bzArrayGet(input->unitPositions, unitPosIdx);
|
Position target = bzArrayGet(input->unitPositions, unitPosIdx);
|
||||||
unitPosIdx++;
|
unitPosIdx++;
|
||||||
|
|
||||||
@@ -158,7 +155,7 @@ void updatePlayerInput() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ecs_defer_end(ECS);
|
ecs_defer_end(ECS);
|
||||||
} else if (wasInputClicked(input)) {
|
} else if (isInputBtnJustDown(input, secondaryBtn)) {
|
||||||
ecs_defer_begin(ECS);
|
ecs_defer_begin(ECS);
|
||||||
iterateSelectedUnits(input->queries.selected, iterRemovePaths);
|
iterateSelectedUnits(input->queries.selected, iterRemovePaths);
|
||||||
ecs_defer_end(ECS);
|
ecs_defer_end(ECS);
|
||||||
@@ -175,7 +172,7 @@ void updatePlayerInput() {
|
|||||||
Path path = {NULL, 0};
|
Path path = {NULL, 0};
|
||||||
pathfindAStar(&(PathfindingDesc) {
|
pathfindAStar(&(PathfindingDesc) {
|
||||||
.start=pos[i],
|
.start=pos[i],
|
||||||
.target=worldPos,
|
.target=input->mouseWorld,
|
||||||
.map=map,
|
.map=map,
|
||||||
.outPath=&path,
|
.outPath=&path,
|
||||||
.pool=game->pools.pathData,
|
.pool=game->pools.pathData,
|
||||||
@@ -190,14 +187,16 @@ void updatePlayerInput() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INPUT_SELECTED_OBJECT:
|
case INPUT_SELECTED_OBJECT: {
|
||||||
case INPUT_SELECTED_BUILDING:
|
inputPrimaryAction(game, input);
|
||||||
if (IsKeyPressed(input->ESC) || IsMouseButtonPressed(input->RMB)) {
|
if (input->state != INPUT_SELECTED_OBJECT) break;
|
||||||
ecs_remove_all(ECS, Selected);
|
|
||||||
input->state = INPUT_NONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case INPUT_SELECTED_BUILDING: {
|
||||||
|
inputPrimaryAction(game, input);
|
||||||
|
if (input->state != INPUT_SELECTED_BUILDING) break;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,12 +205,14 @@ void drawPlayerInputUI() {
|
|||||||
Game *game = ecs_singleton_get_mut(ECS, Game);
|
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||||
InputState *input = ecs_singleton_get_mut(ECS, InputState);
|
InputState *input = ecs_singleton_get_mut(ECS, InputState);
|
||||||
BzTileMap *map = &game->map;
|
BzTileMap *map = &game->map;
|
||||||
Vector2 worldPos = GetScreenToWorld2D(GetMousePosition(), game->camera);
|
|
||||||
|
const MouseButton primaryBtn = input->mapping.primaryBtn;
|
||||||
|
const MouseButton secondaryBtn = input->mapping.secondaryBtn;
|
||||||
|
|
||||||
i32 selectedUnitCount = ecs_count_id(ECS, Selected);
|
i32 selectedUnitCount = ecs_count_id(ECS, Selected);
|
||||||
switch (input->state) {
|
switch (input->state) {
|
||||||
case INPUT_NONE:
|
case INPUT_NONE:
|
||||||
if (isInputDragged(input)) {
|
if (isInputBtnDragged(input, primaryBtn)) {
|
||||||
Rectangle area = input->pickArea;
|
Rectangle area = input->pickArea;
|
||||||
DrawRectangleLines(area.x, area.y, area.width, area.height, RED);
|
DrawRectangleLines(area.x, area.y, area.width, area.height, RED);
|
||||||
}
|
}
|
||||||
@@ -230,11 +231,12 @@ void drawPlayerInputUI() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INPUT_SELECTED_UNITS: {
|
case INPUT_SELECTED_UNITS: {
|
||||||
if (selectedUnitCount > 1 && isInputDragged(input)) {
|
BZ_ASSERT(selectedUnitCount);
|
||||||
|
if (selectedUnitCount > 1 && isInputBtnDragged(input, primaryBtn)) {
|
||||||
i32 numUnits = selectedUnitCount;
|
i32 numUnits = selectedUnitCount;
|
||||||
f32 unitSpacing = 3.5f;
|
f32 unitSpacing = 3.5f;
|
||||||
bzArrayClear(input->unitPositions);
|
bzArrayClear(input->unitPositions);
|
||||||
placeUnits(numUnits, unitSpacing, input->mouseDownWorld, worldPos,
|
placeUnits(numUnits, unitSpacing, input->mouseDownWorld, input->mouseWorld,
|
||||||
map, &input->unitPositions);
|
map, &input->unitPositions);
|
||||||
|
|
||||||
BZ_ASSERT(bzArraySize(input->unitPositions) == numUnits);
|
BZ_ASSERT(bzArraySize(input->unitPositions) == numUnits);
|
||||||
@@ -243,6 +245,22 @@ void drawPlayerInputUI() {
|
|||||||
DrawCircle(pos.x, pos.y, 2.0f, ORANGE);
|
DrawCircle(pos.x, pos.y, 2.0f, ORANGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Rectangle area = {input->mouseWorld.x, input->mouseWorld.y, 1, 1};
|
||||||
|
DrawCircle(area.x, area.y, 4.0f, BLUE);
|
||||||
|
|
||||||
|
BzSpatialGridIter it = bzSpatialGridIter(game->entityGrid, area.x, area.y, area.width, area.height);
|
||||||
|
while (bzSpatialGridQueryNext(&it)) {
|
||||||
|
ecs_entity_t entity = 0;
|
||||||
|
|
||||||
|
BzSpatialGrid *grid = game->entityGrid;
|
||||||
|
Vector2 point = input->mouseWorld;
|
||||||
|
|
||||||
|
|
||||||
|
if ((entity = queryEntity(grid, point, Harvestable))) {
|
||||||
|
DrawText("Collect resources", point.x, point.y, 10.0f, RED);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -297,8 +315,7 @@ bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Recta
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pickEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag) {
|
ecs_entity_t queryEntity(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);
|
BzSpatialGridIter it = bzSpatialGridIter(entityGrid, point.x, point.y, 0.0f, 0.0f);
|
||||||
f32 closestDst = INFINITY;
|
f32 closestDst = INFINITY;
|
||||||
ecs_entity_t closest = 0;
|
ecs_entity_t closest = 0;
|
||||||
@@ -318,8 +335,14 @@ bool pickEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag) {
|
|||||||
closest = entity;
|
closest = entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (closest) {
|
return closest;
|
||||||
ecs_add(ECS, closest, Selected);
|
}
|
||||||
|
|
||||||
|
bool pickEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag) {
|
||||||
|
ecs_remove_all(ECS, Selected);
|
||||||
|
const ecs_entity_t entity = queryEntity(entityGrid, point, tag);
|
||||||
|
if (entity) {
|
||||||
|
ecs_add(ECS, entity, Selected);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user