Rudimentary behaviour tree visualization
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user