Fix and integrate BT

This commit is contained in:
2024-01-10 14:42:21 +01:00
parent a9d20cb7f9
commit 3ba5c8932b
16 changed files with 551 additions and 109 deletions

View File

@@ -211,6 +211,17 @@ bool bzBTNodeMatchesState(const BzBTNode *node, const BzBTNodeState *state) {
return state && state->node == node;
}
BzBTNode *bzBTCompStateGetRunningChild(const BzBTNodeState *state) {
BZ_ASSERT(state->node);
BzBTNodeType type = state->node->type;
bool isComposite = type == BZ_BT_COMP_SELECTOR ||
type == BZ_BT_COMP_PARALLEL_SELECTOR ||
type == BZ_BT_COMP_SEQUENCE ||
type == BZ_BT_COMP_PARALLEL_SEQUENCE;
BZ_ASSERT(isComposite);
return state->as.composite.running;
}
i32 bzBTRepeatStateGetIter(const BzBTNodeState *state) {
BZ_ASSERT(state->node && state->node->type == BZ_BT_DECOR_REPEAT);
return state->as.repeat.iter;
@@ -226,14 +237,14 @@ BzBTState bzBTCreateState(const BzBTStateDesc *desc) {
BZ_ASSERT(desc->root);
return (BzBTState) {
.root = desc->root,
.first = NULL,
.last = NULL,
._first = NULL,
._last = NULL,
.nodeStatePool = desc->pool,
.userData = desc->userData
};
}
void bzBTDestroyState(BzBTState *state) {
BzBTNodeState *pNodeState = state->first;
BzBTNodeState *pNodeState = state->_first;
while (pNodeState) {
BzBTNodeState *next = pNodeState->next;
bzObjectPoolRelease(state->nodeStatePool, pNodeState);
@@ -244,16 +255,16 @@ void bzBTDestroyState(BzBTState *state) {
void bzBTStateAppend(BzBTState *state, BzBTNodeState *nodeState) {
nodeState->next = NULL;
nodeState->prev = state->last;
if (state->last)
state->last->next = nodeState;
nodeState->prev = state->_last;
if (state->_last)
state->_last->next = nodeState;
else
state->first = nodeState;
state->last = nodeState;
state->_first = nodeState;
state->_last = nodeState;
}
void bzBTStatePop(BzBTState *state, BzBTNodeState *nodeState) {
if (state->first == nodeState) state->first = nodeState->next;
if (state->last == nodeState) state->last = nodeState->prev;
if (state->_first == nodeState) state->_first = nodeState->next;
if (state->_last == nodeState) state->_last = nodeState->prev;
BzBTNodeState *next = nodeState->next;
BzBTNodeState *prev = nodeState->prev;
if (nodeState->prev)
@@ -276,6 +287,7 @@ BzBTNodeState *bzBTStatePool(BzBTState *state, const BzBTNode *node) {
return nodeState;
}
void bzBTStateRelease(BzBTState *state, BzBTNodeState *nodeState) {
bzBTStatePop(state, nodeState);
bzObjectPoolRelease(state->nodeStatePool, nodeState);
}
@@ -368,7 +380,7 @@ static inline BzBTStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt,
}
if (status == BZ_BT_ERROR) {
bzBTStatePop(newState, nodeState);
bzBTStateRelease(newState, nodeState);
return BZ_BT_ERROR;
}
@@ -376,7 +388,7 @@ static inline BzBTStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt,
status == BZ_BT_FAIL;
if (finished) {
// Dummy state is no longer needed
bzBTStatePop(newState, nodeState);
bzBTStateRelease(newState, nodeState);
} else {
BZ_ASSERT(status == BZ_BT_RUNNING);
nodeState->as.composite.running = child;
@@ -463,7 +475,7 @@ static inline BzBTStatus bzBTExecuteDecorator(const BzBTNode *node, f32 dt,
BZ_ASSERT(nodeState->node == node);
nodeState->as.repeat.iter++;
if (nodeState->as.repeat.iter >= node->as.repeat.n) {
bzBTStatePop(newState, nodeState);
bzBTStateRelease(newState, nodeState);
status = inStatus;
break;
}
@@ -497,7 +509,7 @@ static inline BzBTStatus bzBTExecuteNode(const BzBTNode *node, f32 dt,
break;
case BZ_BT_ACTION:
BZ_ASSERT(node->as.action.fn);
return node->as.action.fn(oldState->userData);
return node->as.action.fn(oldState->userData, dt);
}
return status;
}
@@ -506,25 +518,43 @@ BzBTStatus bzBTExecute(BzBTState *state, f32 dt) {
BZ_ASSERT(state->nodeStatePool);
BZ_ASSERT(bzObjectPoolGetObjectSize(state->nodeStatePool) == bzBTGetNodeStateSize());
BZ_ASSERT(state);
BZ_ASSERT(state->root);
if (state->root == NULL) {
return BZ_BT_FAIL;
}
BzBTState newState = {
.first = NULL,
.last = NULL,
._first = NULL,
._last = NULL,
.nodeStatePool = state->nodeStatePool
};
BzBTNodeState *first = state->first;
BzBTNodeState *first = state->_first;
const BzBTNode *firstNode = first ? first->node : state->root;
BzBTStatus status = bzBTExecuteNode(firstNode, dt, first, state, &newState);
// Release leftover states
BzBTNodeState *pState = state->first;
BzBTNodeState *pState = state->_first;
while (pState) {
BzBTNodeState *next = pState->next;
bzBTStateRelease(state, pState);
pState = next;
}
state->first = newState.first;
state->last = newState.last;
state->_first = newState._first;
state->_last = newState._last;
switch (status) {
case BZ_BT_SUCCESS:
state->onSuccess && state->onSuccess(state->userData, dt);
break;
case BZ_BT_FAIL:
state->onFailure && state->onFailure(state->userData, dt);
break;
case BZ_BT_ERROR:
state->onError && state->onError(state->userData, dt);
break;
default:
break;
}
return status;
}

View File

@@ -12,7 +12,7 @@ typedef enum BzBTStatus {
BZ_BT_ERROR,
} BzBTStatus;
typedef BzBTStatus(*BzBTActionFn)(void *data);
typedef BzBTStatus(*BzBTActionFn)(void *data, f32 dt);
typedef enum BzBTNodeType {
// Composite
@@ -38,8 +38,12 @@ typedef struct BzBTNodeState BzBTNodeState;
typedef struct BzBTState {
const BzBTNode *root;
BzBTNodeState *first;
BzBTNodeState *last;
BzBTNodeState *_first;
BzBTNodeState *_last;
BzBTActionFn onSuccess;
BzBTActionFn onFailure;
BzBTActionFn onError;
BzObjectPool *nodeStatePool;
void *userData;
@@ -91,6 +95,8 @@ BzBTNode *bzBTNodeNext(const BzBTNode *node);
const BzBTNodeState *bzBTNodeStateNext(const BzBTNodeState *state);
bool bzBTNodeMatchesState(const BzBTNode *node, const BzBTNodeState *state);
BzBTNode *bzBTCompStateGetRunningChild(const BzBTNodeState *state);
i32 bzBTRepeatStateGetIter(const BzBTNodeState *state);
f32 bzBTDelayStateGetElapsed(const BzBTNodeState *state);

View File

@@ -7,7 +7,7 @@ BzObjectPool *nodeStatePool = NULL;
BzBTNode *printBT = NULL;
BzBTState agentState;
BzBTStatus printAction(void *data) {
BzBTStatus printAction(void *data, f32 dt) {
bzLogInfo("Hello, world!");
return BZ_BT_SUCCESS;
}
@@ -48,7 +48,7 @@ void deinit(int *game) {
bzObjectPoolDestroy(nodeStatePool);
}
void igRenderBTNode(const BzBTNode *node, const BzBTNodeState *state, bool sameLine, i32 depth) {
void igVisualizeBTState(const BzBTNode *node, const BzBTNodeState *state, bool sameLine, i32 depth) {
const BzBTNode *child = bzBTNodeChild(node);
BzBTNodeType type = bzBTGetNodeType(node);
char extraInfo[128];
@@ -109,7 +109,7 @@ void igRenderBTNode(const BzBTNode *node, const BzBTNodeState *state, bool sameL
while (child) {
if (hasSingleChild) igSameLine(0, 0);
igRenderBTNode(child, state, hasSingleChild, depth);
igVisualizeBTState(child, state, hasSingleChild, depth);
child = bzBTNodeNext(child);
}
}
@@ -117,7 +117,7 @@ void igRenderBTNode(const BzBTNode *node, const BzBTNodeState *state, bool sameL
void igRenderBT(BzBTState *state) {
const BzBTNode *root = state->root;
if (igBegin("BehaviourTree", NULL, 0)) {
igRenderBTNode(root, state->first, false, 0);
igVisualizeBTState(root, state->_first, false, 0);
}
igEnd();
}