Fix and integrate BT
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user