Add actions
This commit is contained in:
@@ -24,9 +24,14 @@ add_executable(PixelDefense
|
||||
game/pathfinding.c
|
||||
game/pathfinding.h
|
||||
game/systems.h
|
||||
game/systems_ai.c
|
||||
game/systems_entity.c
|
||||
game/systems_input.c
|
||||
game/systems_ui.c
|
||||
game/unit_actions.c
|
||||
game/unit_actions.h
|
||||
game/unit_ai.c
|
||||
game/unit_ai.h
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ ECS_COMPONENT_DECLARE(TextureRegion);
|
||||
|
||||
ECS_COMPONENT_DECLARE(Animation);
|
||||
|
||||
ECS_COMPONENT_DECLARE(UnitAction);
|
||||
ECS_TAG_DECLARE(Selectable);
|
||||
ECS_TAG_DECLARE(Selected);
|
||||
|
||||
@@ -35,8 +36,6 @@ ECS_TAG_DECLARE(Attackable);
|
||||
|
||||
ECS_COMPONENT_DECLARE(Storage);
|
||||
|
||||
ECS_COMPONENT_DECLARE(HarvestTask);
|
||||
|
||||
void initComponentIDs(ecs_world_t *ecs) {
|
||||
ECS_TAG_DEFINE(ecs, TextureTerrain);
|
||||
ECS_TAG_DEFINE(ecs, TextureBuildings);
|
||||
@@ -61,6 +60,7 @@ void initComponentIDs(ecs_world_t *ecs) {
|
||||
|
||||
ECS_COMPONENT_DEFINE(ecs, Animation);
|
||||
|
||||
ECS_COMPONENT_DEFINE(ecs, UnitAction);
|
||||
ECS_TAG_DEFINE(ecs, Selectable);
|
||||
ECS_TAG_DEFINE(ecs, Selected);
|
||||
|
||||
@@ -72,6 +72,4 @@ void initComponentIDs(ecs_world_t *ecs) {
|
||||
ECS_TAG_DEFINE(ecs, Attackable);
|
||||
|
||||
ECS_COMPONENT_DEFINE(ecs, Storage);
|
||||
|
||||
ECS_COMPONENT_DEFINE(ecs, HarvestTask);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <flecs.h>
|
||||
|
||||
#include "game_tileset.h"
|
||||
#include "unit_actions.h"
|
||||
|
||||
extern ECS_TAG_DECLARE(TextureTerrain);
|
||||
extern ECS_TAG_DECLARE(TextureBuildings);
|
||||
@@ -124,6 +125,12 @@ typedef struct EntityArms {
|
||||
* Gameplay components
|
||||
*********************************************************/
|
||||
|
||||
extern ECS_COMPONENT_DECLARE(UnitAction);
|
||||
|
||||
typedef struct ActionOverseer {
|
||||
|
||||
} ActionOverseer;
|
||||
|
||||
extern ECS_TAG_DECLARE(Selectable);
|
||||
extern ECS_TAG_DECLARE(Selected);
|
||||
|
||||
@@ -151,20 +158,6 @@ typedef struct Storage {
|
||||
} Storage;
|
||||
extern ECS_COMPONENT_DECLARE(Storage);
|
||||
|
||||
typedef struct HarvestTask {
|
||||
ecs_entity_t entity;
|
||||
} HarvestTask;
|
||||
extern ECS_COMPONENT_DECLARE(HarvestTask);
|
||||
|
||||
typedef struct WorkerTask {
|
||||
enum {
|
||||
HARVEST,
|
||||
BUILD,
|
||||
} type;
|
||||
ecs_entity_t target;
|
||||
//struct WorkerTask *next;
|
||||
} WorkerTask;
|
||||
|
||||
void initComponentIDs(ecs_world_t *ecs);
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ typedef struct Game {
|
||||
BzStackAlloc stackAlloc;
|
||||
struct {
|
||||
BzObjectPool *pathData;
|
||||
BzObjectPool *actions;
|
||||
} pools;
|
||||
struct {
|
||||
bool path;
|
||||
|
||||
11
game/main.c
11
game/main.c
@@ -111,6 +111,10 @@ bool init(void *userData) {
|
||||
.objectSize = sizeof(PathData),
|
||||
.objectsPerPage = 512
|
||||
});
|
||||
game->pools.actions = bzObjectPoolCreate(&(BzObjectPoolDesc) {
|
||||
.objectSize = sizeof(UnitAction),
|
||||
.objectsPerPage = 1024,
|
||||
});
|
||||
|
||||
|
||||
int screenWidth = 1280;
|
||||
@@ -171,7 +175,8 @@ bool init(void *userData) {
|
||||
ECS_SYSTEM(ECS, entityMoveToTarget, EcsOnUpdate, Position, Rotation, Velocity, TargetPosition, Steering);
|
||||
ECS_SYSTEM(ECS, entityFollowPath, EcsOnUpdate, Path);
|
||||
|
||||
ECS_SYSTEM(ECS, entityHarvestTaskSystem, EcsOnUpdate, Position, Rotation, HarvestTask);
|
||||
//ECS_SYSTEM(ECS, entityHarvestTaskSystem, EcsOnUpdate, Position, Rotation, HarvestTask);
|
||||
ECS_SYSTEM(ECS, updateUnitActions, EcsOnUpdate, UnitAction);
|
||||
|
||||
//ECS_SYSTEM(ECS, entityUpdateAnimationState, EcsOnUpdate, Velocity, AnimationType);
|
||||
ECS_SYSTEM(ECS, entityUpdateAnimation, EcsOnUpdate, Animation, TextureRegion);
|
||||
@@ -213,6 +218,7 @@ void deinit(void *userData) {
|
||||
|
||||
bzStackAllocDestroy(&gameCopy.stackAlloc);
|
||||
bzObjectPoolDestroy(gameCopy.pools.pathData);
|
||||
bzObjectPoolDestroy(gameCopy.pools.actions);
|
||||
bzSpatialGridDestroy(gameCopy.entityGrid);
|
||||
}
|
||||
|
||||
@@ -271,7 +277,8 @@ void imguiRender(float dt, void *userData) {
|
||||
createWorker((Position) {1100, 400}, (Size) {10, 10}, game->entityGrid,
|
||||
&game->map.tilesets[2], 1322);
|
||||
}
|
||||
igText("Num paths from pool available: %llu", bzObjectPoolGetNumFree(game->pools.pathData));
|
||||
igText("PathData pool available: %llu", bzObjectPoolGetNumFree(game->pools.pathData));
|
||||
igText("Action pool available: %llu", bzObjectPoolGetNumFree(game->pools.actions));
|
||||
const char *inputState = "NONE";
|
||||
switch (input->state) {
|
||||
case INPUT_NONE:
|
||||
|
||||
@@ -148,6 +148,7 @@ ecs_entity_t createWorker(Position position, Size size, BzSpatialGrid *grid, BzT
|
||||
.curFrame = 0,
|
||||
.elapsed = 0.0f,
|
||||
});
|
||||
ecs_set(ECS, e, UnitAction, {NULL, NULL});
|
||||
ecs_add_id(ECS, e, Selectable);
|
||||
ecs_add_id(ECS, e, Unit);
|
||||
ecs_add_id(ECS, e, Worker);
|
||||
|
||||
@@ -7,9 +7,18 @@
|
||||
|
||||
typedef struct Game Game;
|
||||
|
||||
void entityClearTasks(const ecs_entity_t entity);
|
||||
bool entitySetPath(const ecs_entity_t entity, const Vector2 target, Game *game);
|
||||
|
||||
/**********************************
|
||||
* AI systems
|
||||
**********************************/
|
||||
|
||||
/*
|
||||
* 0: Game (singleton)
|
||||
* 1: UnitAction
|
||||
*/
|
||||
void updateUnitActions(ecs_iter_t *it);
|
||||
|
||||
|
||||
/**********************************
|
||||
* Entity Systems
|
||||
|
||||
13
game/systems_ai.c
Normal file
13
game/systems_ai.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "systems.h"
|
||||
|
||||
#include "game_state.h"
|
||||
|
||||
void updateUnitActions(ecs_iter_t *it) {
|
||||
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||
UnitAction *action = ecs_field(it, UnitAction, 1);
|
||||
|
||||
for (i32 i = 0; i < it->count; i++) {
|
||||
ecs_entity_t entity = it->entities[i];
|
||||
handleAction(entity, &action[i], game);
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,6 @@
|
||||
#include <math.h>
|
||||
#include <raymath.h>
|
||||
|
||||
void entityClearTasks(const ecs_entity_t entity) {
|
||||
ecs_remove(ECS, entity, HarvestTask);
|
||||
}
|
||||
bool entitySetPath(const ecs_entity_t entity, const Vector2 target, Game *game) {
|
||||
const Vector2 *pPath = ecs_get(ECS, entity, Position);
|
||||
BZ_ASSERT(pPath);
|
||||
@@ -217,6 +214,7 @@ static ecs_entity_t findNearestStorage(ResourceType type) {
|
||||
return closest;
|
||||
}
|
||||
|
||||
/*
|
||||
void entityHarvestTaskSystem(ecs_iter_t *it) {
|
||||
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||
|
||||
@@ -270,6 +268,7 @@ void entityHarvestTaskSystem(ecs_iter_t *it) {
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void entityUpdateAnimationState(ecs_iter_t *it) {
|
||||
Velocity *velocity = ecs_field(it, Velocity, 1);
|
||||
|
||||
@@ -83,7 +83,13 @@ void inputUnitAction(Game *game, InputState *input) {
|
||||
while (ecs_query_next(&it)) {
|
||||
for (i32 i = 0; i < it.count; i++) {
|
||||
const ecs_entity_t entity = it.entities[i];
|
||||
ecs_set(ECS, entity, HarvestTask, {taskEntity});
|
||||
const Position target = *ecs_get(ECS, taskEntity, Position);
|
||||
addAction(entity, game, &(const Action) {
|
||||
.type = ACTION_MOVE_TO,
|
||||
.as.moveTo.target = target,
|
||||
.as.moveTo.proximityThreshold = 10.0f,
|
||||
});
|
||||
//ecs_set(ECS, entity, HarvestTask, {taskEntity});
|
||||
goto while_break;
|
||||
}
|
||||
}
|
||||
|
||||
93
game/unit_actions.c
Normal file
93
game/unit_actions.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "unit_actions.h"
|
||||
#include "game_state.h"
|
||||
#include "components.h"
|
||||
#include "systems.h"
|
||||
|
||||
#include <raymath.h>
|
||||
|
||||
void actionMoveTo(ecs_entity_t entity, Action *action, Game *game) {
|
||||
const Vector2 target = action->as.moveTo.target;
|
||||
if (!ecs_has(ECS, entity, Path)) {
|
||||
entitySetPath(entity, target, game);
|
||||
return;
|
||||
}
|
||||
Vector2 pos = *ecs_get(ECS, entity, Position);
|
||||
|
||||
f32 dst = Vector2Distance(pos, target);
|
||||
if (dst < action->as.moveTo.proximityThreshold) {
|
||||
action->finished = true;
|
||||
}
|
||||
}
|
||||
void actionCollectResource(ecs_entity_t entity, Action *action, Game *game) {
|
||||
|
||||
}
|
||||
void actionDepositResource(ecs_entity_t entity, Action *action, Game *game) {
|
||||
|
||||
}
|
||||
|
||||
void handleAction(ecs_entity_t entity, UnitAction *unitAction, Game *game) {
|
||||
Action *action = unitAction->first;
|
||||
if (action == NULL) return;
|
||||
switch (action->type) {
|
||||
case ACTION_NONE:
|
||||
break;
|
||||
case ACTION_MOVE_TO:
|
||||
actionMoveTo(entity, action, game);
|
||||
break;
|
||||
case ACTION_COLLECT_RESOURCE:
|
||||
actionCollectResource(entity, action, game);
|
||||
break;
|
||||
case ACTION_DEPOSIT_RESOURCE:
|
||||
actionDepositResource(entity, action, game);
|
||||
break;
|
||||
default:
|
||||
BZ_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
action->elapsed += GetFrameTime();
|
||||
if (action->finished) {
|
||||
unitAction->first = action->next;
|
||||
if (unitAction->last == action) {
|
||||
unitAction->last = NULL;
|
||||
BZ_ASSERT(unitAction->first == unitAction->last);
|
||||
}
|
||||
BzObjectPool *pool = game->pools.actions;
|
||||
bzObjectPoolRelease(pool, action);
|
||||
}
|
||||
}
|
||||
void clearActions(ecs_entity_t entity, Game *game) {
|
||||
if (!ecs_has(ECS, entity, UnitAction)) return;
|
||||
UnitAction *unitAction = ecs_get_mut(ECS, entity, UnitAction);
|
||||
|
||||
BzObjectPool *pool = game->pools.actions;
|
||||
|
||||
Action *pAction = unitAction->first;
|
||||
while (pAction) {
|
||||
bzObjectPoolRelease(pool, pAction);
|
||||
pAction = pAction->next;
|
||||
}
|
||||
|
||||
unitAction->first = NULL;
|
||||
unitAction->last = NULL;
|
||||
}
|
||||
void addAction(ecs_entity_t entity, Game *game, const Action *action) {
|
||||
BZ_ASSERT(action);
|
||||
BZ_ASSERT(ecs_has(ECS, entity, UnitAction));
|
||||
|
||||
UnitAction *unitAction = ecs_get_mut(ECS, entity, UnitAction);
|
||||
BzObjectPool *pool = game->pools.actions;
|
||||
|
||||
Action *newAction = bzObjectPool(pool);
|
||||
BZ_ASSERT(newAction);
|
||||
*newAction = *action;
|
||||
|
||||
newAction->next = NULL;
|
||||
if (unitAction->last) {
|
||||
Action *last = unitAction->last;
|
||||
last->next = newAction;
|
||||
unitAction->last = newAction;
|
||||
} else {
|
||||
unitAction->first = newAction;
|
||||
unitAction->last = newAction;
|
||||
}
|
||||
}
|
||||
51
game/unit_actions.h
Normal file
51
game/unit_actions.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef PIXELDEFENSE_UNIT_ACTIONS_H
|
||||
#define PIXELDEFENSE_UNIT_ACTIONS_H
|
||||
|
||||
#include <breeze.h>
|
||||
#include <flecs.h>
|
||||
|
||||
typedef struct Game Game;
|
||||
|
||||
typedef enum ActionType {
|
||||
ACTION_NONE,
|
||||
ACTION_MOVE_TO,
|
||||
ACTION_COLLECT_RESOURCE,
|
||||
ACTION_DEPOSIT_RESOURCE,
|
||||
ACTION_COUNT,
|
||||
} ActionType;
|
||||
|
||||
typedef struct ActionMoveTo {
|
||||
Vector2 target;
|
||||
f32 proximityThreshold;
|
||||
} ActionMoveTo;
|
||||
typedef struct ActionCollectResource {
|
||||
|
||||
} ActionCollectResource;
|
||||
typedef struct ActionDepositResource {
|
||||
|
||||
} ActionDepositResource;
|
||||
|
||||
typedef struct Action {
|
||||
ActionType type;
|
||||
union {
|
||||
ActionMoveTo moveTo;
|
||||
ActionCollectResource collectResource;
|
||||
ActionDepositResource depositResource;
|
||||
} as;
|
||||
|
||||
f32 elapsed;
|
||||
bool finished;
|
||||
|
||||
struct Action *next;
|
||||
} Action;
|
||||
|
||||
typedef struct UnitAction {
|
||||
Action *first;
|
||||
Action *last;
|
||||
} UnitAction;
|
||||
|
||||
void handleAction(ecs_entity_t entity, UnitAction *unitAction, Game *game);
|
||||
void clearActions(ecs_entity_t entity, Game *game);
|
||||
void addAction(ecs_entity_t entity, Game *game, const Action *action);
|
||||
|
||||
#endif //PIXELDEFENSE_UNIT_ACTIONS_H
|
||||
1
game/unit_ai.c
Normal file
1
game/unit_ai.c
Normal file
@@ -0,0 +1 @@
|
||||
#include "unit_ai.h"
|
||||
5
game/unit_ai.h
Normal file
5
game/unit_ai.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#ifndef PIXELDEFENSE_UNIT_AI_H
|
||||
#define PIXELDEFENSE_UNIT_AI_H
|
||||
|
||||
|
||||
#endif //PIXELDEFENSE_UNIT_AI_H
|
||||
Reference in New Issue
Block a user