Rudimentary behaviour tree visualization

This commit is contained in:
2024-01-09 22:01:16 +01:00
parent e4cc00d3a7
commit a6b79fb14c
3 changed files with 171 additions and 20 deletions

View File

@@ -5,6 +5,7 @@ BzObjectPool *nodePool = NULL;
BzObjectPool *nodeStatePool = NULL;
BzAIBTNode *printBT = NULL;
BzAIBTState agentState;
BzAIBTStatus printAction(void *data) {
bzLogInfo("Hello, world!");
@@ -12,6 +13,7 @@ BzAIBTStatus printAction(void *data) {
}
bool init(int *game) {
rlImGuiSetup(true);
nodePool = bzObjectPoolCreate(&(BzObjectPoolDesc) {
.objectSize = bzAIBTGetNodeSize(),
});
@@ -29,40 +31,95 @@ bool init(int *game) {
BzAIBTNode *seq = bzAIBTCompSequence(nodePool, node, false);
bzAIBTDecorDelay(nodePool, seq, 1.0f);
bzAIBTAction(nodePool, seq, printAction);
bzAIBTAction(nodePool, seq, printAction, "printAction");
BzAIBTState state = bzAIBTCreateState(&(BzAIBTStateDesc) {
agentState = bzAIBTCreateState(&(BzAIBTStateDesc) {
.root = printBT,
.pool = nodeStatePool,
.userData = NULL
});
BzAIBTStatus status = BZ_AIBT_RUNNING;
i32 count = 0;
while (status == BZ_AIBT_RUNNING) {
status = bzAIBTExecute(&state, 0.2f);
count++;
assert(status != BZ_AIBT_ERROR);
}
bzLogInfo("Iter: %d", count);
return true;
}
void deinit(int *game) {
bzObjectPoolDestroy(nodePool);
bzObjectPoolDestroy(nodeStatePool);
}
return true;
void igRenderBTNode(const BzAIBTNode *node, const BzAIBTNodeState *state, i32 depth) {
const BzAIBTNode *child = bzAIBTNodeChild(node);
BzAIBTNodeType type = bzAIBTGetNodeType(node);
char extraInfo[128];
extraInfo[0] = '\0';
bool hasState = bzAIBTNodeMatchesState(node, state);
switch (type) {
case BZ_AIBT_DECOR_REPEAT:
if (hasState) {
snprintf(extraInfo, sizeof(extraInfo), "(%d < %d)",
bzAIBTRepeatStateGetIter(state),
bzAIBTDecorGetRepeat(node));
} else {
snprintf(extraInfo, sizeof(extraInfo), "(%d)", bzAIBTDecorGetRepeat(node));
}
break;
case BZ_AIBT_DECOR_DELAY:
if (hasState) {
snprintf(extraInfo, sizeof(extraInfo), "(%.2f < %.2fms)",
bzAIBTDelayStateGetElapsed(state),
bzAIBTDecorGetDelay(node));
} else {
snprintf(extraInfo, sizeof(extraInfo), "(%.2fms)", bzAIBTDecorGetDelay(node));
}
break;
case BZ_AIBT_ACTION:
snprintf(extraInfo, sizeof(extraInfo), "(%s:%p)",
bzAIBTActionGetName(node),
bzAIBTActionGetFn(node));
break;
default:
break;
}
if (hasState)
state = bzAIBTNodeStateNext(state);
ImVec4 color = {1.0f, 1.0f, 1.0f, 1.0f};
if (hasState)
color = (ImVec4) {1.0f, 1.0f, 0.5f, 1.0f};
igTextColored(color, "%*s%s %s", depth * 4, "",
bzAIBTNodeTypeToStr(type), extraInfo);
while (child) {
igRenderBTNode(child, state, depth + 1);
child = bzAIBTNodeNext(child);
}
}
void igRenderBT(BzAIBTState *state) {
const BzAIBTNode *root = state->root;
if (igBegin("BehaviourTree", NULL, 0)) {
igRenderBTNode(root, state->first, 0);
}
igEnd();
}
void render(float dt, int *game) {
ClearBackground(WHITE);
BzAIBTStatus status = bzAIBTExecute(&agentState, dt);
rlImGuiBegin();
igRenderBT(&agentState);
igShowDemoWindow(NULL);
rlImGuiEnd();
}
bool bzMain(BzAppDesc *appDesc, int argc, const char **argv) {
appDesc->init = (BzAppInitFunc) init;
appDesc->deinit = (BzAppDeinitFunc ) deinit;
appDesc->render = (BzAppRenderFunc) render;
init(NULL);
return false;
return true;
}