@ -0,0 +1,73 @@ | |||||
%% @author zouv | |||||
%% @doc use bte for ai | |||||
-module(bte_ai). | |||||
-include_lib("erlbte/include/common.hrl"). | |||||
-export([ | |||||
init/1, | |||||
tick/1 | |||||
]). | |||||
init(Data) -> | |||||
{ok, Json, _} = rfc4627:decode(Data), % depend on rfc4627_jsonrpc | |||||
RootId = get_field_string(Json, "root"), | |||||
{ok, NodesJson} = rfc4627:get_field(Json, "nodes"), | |||||
NodeList = init_nodes([RootId], NodesJson, []), | |||||
CustomNodesModule = bte_node_behaviour:init_nodes_moudle(?MODULE), % load self-defined bte node | |||||
BteConfigData = | |||||
#r_bte_config_data{ | |||||
root_id = RootId, | |||||
nodes = NodeList, | |||||
custom_nodes_moudle = CustomNodesModule | |||||
}, | |||||
BteStatus = bte_behavior:init(BteConfigData), | |||||
{ok, BteStatus}. | |||||
init_nodes([], _NodesJson, NodeList) -> | |||||
NodeList; | |||||
init_nodes([Id | LeftIdList], NodesJson, NodeList) -> | |||||
{ok, NodeJson} = rfc4627:get_field(NodesJson, Id), | |||||
Name = get_field_string(NodeJson, "name"), | |||||
{ok, Parameters} = rfc4627:get_field(NodeJson, "parameters"), | |||||
ChildId = binary_to_list(rfc4627:get_field(NodeJson, "child", <<>>)), | |||||
Children = lists:map(fun(E) -> binary_to_list(E) end, rfc4627:get_field(NodeJson, "children", [])), | |||||
BteNode = | |||||
#r_bte_config_node{ | |||||
id = Id, | |||||
name = Name, | |||||
parameters = get_all(Parameters), | |||||
child = ChildId, | |||||
children = Children | |||||
}, | |||||
NewNodeList = [BteNode | NodeList], | |||||
if | |||||
ChildId /= "" -> | |||||
init_nodes([ChildId | LeftIdList], NodesJson, NewNodeList); | |||||
Children /= [] -> | |||||
init_nodes(Children ++ LeftIdList, NodesJson, NewNodeList); | |||||
true -> | |||||
init_nodes(LeftIdList, NodesJson, NewNodeList) | |||||
end. | |||||
get_field_string(Json, Key) -> | |||||
{ok, Value} = rfc4627:get_field(Json, Key), | |||||
binary_to_list(Value). | |||||
get_all(Parameters) -> | |||||
{obj, PrapList} = Parameters, | |||||
lists:map(fun({EKey, EValue}) -> | |||||
if | |||||
is_binary(EValue) -> | |||||
ENewValue = binary_to_list(EValue); | |||||
true -> | |||||
ENewValue = EValue | |||||
end, | |||||
{EKey, ENewValue} | |||||
end, | |||||
PrapList). | |||||
tick(BteStatus) -> | |||||
bte_behavior:tick(BteStatus). | |||||
@ -0,0 +1,29 @@ | |||||
%% @author zouv | |||||
%% @doc testing bte ai | |||||
-module(bte_ai_test). | |||||
-include_lib("erlbte/include/common.hrl"). | |||||
-export([ | |||||
test/1 | |||||
]). | |||||
% json file edit by "Behavior3JS Edotor" | |||||
% url: http://behavior3js.guineashots.com | |||||
test(FileName) -> | |||||
case file:read_file("json/" ++ FileName) of | |||||
{ok, EBinary} -> | |||||
{ok, BteStatus} = bte_ai:init(EBinary), | |||||
io:format("test___1 ~p~n", [BteStatus#r_bte_status.status]), | |||||
BteStatus1 = bte_ai:tick(BteStatus), | |||||
io:format("test___2 ~p~n", [BteStatus1#r_bte_status.status]), | |||||
% BteStatus2 = bte_ai:tick(BteStatus1), % testing bte stack | |||||
% BteStatus3 = bte_ai:tick(BteStatus2), | |||||
% BteStatus4 = bte_ai:tick(BteStatus3), | |||||
% BteStatus5 = bte_ai:tick(BteStatus4), | |||||
ok; | |||||
_ -> | |||||
skip | |||||
end. | |||||
@ -0,0 +1,54 @@ | |||||
{ | |||||
"title": "A Behavior Tree", | |||||
"description": "", | |||||
"root": "8f154647-d5a8-46b0-83af-35324d33773c", | |||||
"display": { | |||||
"camera_x": 1366, | |||||
"camera_y": 648, | |||||
"camera_z": 1, | |||||
"x": -368, | |||||
"y": -64 | |||||
}, | |||||
"properties": {}, | |||||
"nodes": { | |||||
"8f154647-d5a8-46b0-83af-35324d33773c": { | |||||
"id": "8f154647-d5a8-46b0-83af-35324d33773c", | |||||
"name": "Sequence", | |||||
"title": "Sequence", | |||||
"description": "顺序节点", | |||||
"display": { | |||||
"x": -160, | |||||
"y": -64 | |||||
}, | |||||
"parameters": {}, | |||||
"properties": {}, | |||||
"children": [ | |||||
"2af0f62a-2956-4e38-93db-28d07438164a" | |||||
] | |||||
}, | |||||
"2af0f62a-2956-4e38-93db-28d07438164a": { | |||||
"id": "2af0f62a-2956-4e38-93db-28d07438164a", | |||||
"name": "Wait", | |||||
"title": "Wait", | |||||
"description": "", | |||||
"display": { | |||||
"x": 48, | |||||
"y": -64 | |||||
}, | |||||
"parameters": { | |||||
"milliseconds": "" | |||||
}, | |||||
"properties": { | |||||
"milliseconds": "单位毫秒" | |||||
} | |||||
} | |||||
}, | |||||
"g_value": { | |||||
"parameters": {}, | |||||
"id": "GlobalValue", | |||||
"name": "GlobalValue", | |||||
"title": "GlobalValue", | |||||
"description": "全局变量" | |||||
}, | |||||
"custom_nodes": [] | |||||
} |
@ -0,0 +1,101 @@ | |||||
{ | |||||
"title": "A Behavior Tree", | |||||
"description": "", | |||||
"root": "aaa47257-0bd6-478a-87b7-dc925a003d6d", | |||||
"display": { | |||||
"camera_x": 1366, | |||||
"camera_y": 648, | |||||
"camera_z": 1, | |||||
"x": -496, | |||||
"y": -32 | |||||
}, | |||||
"properties": {}, | |||||
"nodes": { | |||||
"1682e79b-b870-4314-83fd-0b72734b7be8": { | |||||
"id": "1682e79b-b870-4314-83fd-0b72734b7be8", | |||||
"name": "Wait", | |||||
"title": "Wait", | |||||
"description": "", | |||||
"display": { | |||||
"x": 128, | |||||
"y": -64 | |||||
}, | |||||
"parameters": { | |||||
"milliseconds": "" | |||||
}, | |||||
"properties": { | |||||
"milliseconds": "单位毫秒" | |||||
} | |||||
}, | |||||
"fe7005b4-f1d4-472e-a289-7736b19665f3": { | |||||
"id": "fe7005b4-f1d4-472e-a289-7736b19665f3", | |||||
"name": "Init", | |||||
"title": "Init", | |||||
"description": "", | |||||
"display": { | |||||
"x": -80, | |||||
"y": 0 | |||||
}, | |||||
"parameters": {}, | |||||
"properties": {}, | |||||
"child": "eb1ed18e-e51e-4beb-8322-009eb91d77a2" | |||||
}, | |||||
"eb1ed18e-e51e-4beb-8322-009eb91d77a2": { | |||||
"id": "eb1ed18e-e51e-4beb-8322-009eb91d77a2", | |||||
"name": "Wait", | |||||
"title": "Wait", | |||||
"description": "", | |||||
"display": { | |||||
"x": 128, | |||||
"y": 0 | |||||
}, | |||||
"parameters": { | |||||
"milliseconds": "" | |||||
}, | |||||
"properties": { | |||||
"milliseconds": "单位毫秒" | |||||
} | |||||
}, | |||||
"aaa47257-0bd6-478a-87b7-dc925a003d6d": { | |||||
"id": "aaa47257-0bd6-478a-87b7-dc925a003d6d", | |||||
"name": "Selector", | |||||
"title": "Selector", | |||||
"description": "选择节点", | |||||
"display": { | |||||
"x": -288, | |||||
"y": -32 | |||||
}, | |||||
"parameters": {}, | |||||
"properties": {}, | |||||
"children": [ | |||||
"2e04f772-8d39-44da-8ea3-fd31a6b42d4a", | |||||
"fe7005b4-f1d4-472e-a289-7736b19665f3" | |||||
] | |||||
}, | |||||
"2e04f772-8d39-44da-8ea3-fd31a6b42d4a": { | |||||
"id": "2e04f772-8d39-44da-8ea3-fd31a6b42d4a", | |||||
"name": "RepeatUntilSuccess", | |||||
"title": "RepeatUntilSuccess", | |||||
"description": "重复执行直到子节点返回成功", | |||||
"display": { | |||||
"x": -80, | |||||
"y": -64 | |||||
}, | |||||
"parameters": { | |||||
"maxLoop": -1 | |||||
}, | |||||
"properties": { | |||||
"maxLoop": "最大重复次数,-1表示无限" | |||||
}, | |||||
"child": "1682e79b-b870-4314-83fd-0b72734b7be8" | |||||
} | |||||
}, | |||||
"g_value": { | |||||
"parameters": {}, | |||||
"id": "GlobalValue", | |||||
"name": "GlobalValue", | |||||
"title": "GlobalValue", | |||||
"description": "全局变量" | |||||
}, | |||||
"custom_nodes": [] | |||||
} |
@ -0,0 +1,135 @@ | |||||
{ | |||||
"title": "A Behavior Tree", | |||||
"description": "", | |||||
"root": "b7025cc5-af44-4a7c-b627-f51968b51088", | |||||
"display": { | |||||
"camera_x": 1366, | |||||
"camera_y": 648, | |||||
"camera_z": 1, | |||||
"x": -464, | |||||
"y": -16 | |||||
}, | |||||
"properties": {}, | |||||
"nodes": { | |||||
"b7025cc5-af44-4a7c-b627-f51968b51088": { | |||||
"id": "b7025cc5-af44-4a7c-b627-f51968b51088", | |||||
"name": "RandomSelector", | |||||
"title": "RandomSelector", | |||||
"description": "随机选择节点", | |||||
"display": { | |||||
"x": -256, | |||||
"y": -16 | |||||
}, | |||||
"parameters": {}, | |||||
"properties": {}, | |||||
"children": [ | |||||
"0cb499a9-abff-4809-8afc-b132c0bb6cbe", | |||||
"5e3b77f6-7d41-46cc-98c1-b40be501ef0a", | |||||
"b09496f8-4192-46e7-9114-19eca4048ad3" | |||||
] | |||||
}, | |||||
"0cb499a9-abff-4809-8afc-b132c0bb6cbe": { | |||||
"id": "0cb499a9-abff-4809-8afc-b132c0bb6cbe", | |||||
"name": "RepeatUntilSuccess", | |||||
"title": "RepeatUntilSuccess", | |||||
"description": "重复执行直到子节点返回成功", | |||||
"display": { | |||||
"x": -48, | |||||
"y": -80 | |||||
}, | |||||
"parameters": { | |||||
"maxLoop": -1 | |||||
}, | |||||
"properties": { | |||||
"maxLoop": "最大重复次数,-1表示无限" | |||||
}, | |||||
"child": "5381fa95-811b-4b65-a61c-ef6f4bd5539a" | |||||
}, | |||||
"5381fa95-811b-4b65-a61c-ef6f4bd5539a": { | |||||
"id": "5381fa95-811b-4b65-a61c-ef6f4bd5539a", | |||||
"name": "Inverter", | |||||
"title": "Inverter", | |||||
"description": "", | |||||
"display": { | |||||
"x": 160, | |||||
"y": -80 | |||||
}, | |||||
"parameters": {}, | |||||
"properties": {}, | |||||
"child": "cff3d48e-896b-4f62-87cc-f7a1c2d4f3ef" | |||||
}, | |||||
"cff3d48e-896b-4f62-87cc-f7a1c2d4f3ef": { | |||||
"id": "cff3d48e-896b-4f62-87cc-f7a1c2d4f3ef", | |||||
"name": "Wait", | |||||
"title": "Wait", | |||||
"description": "", | |||||
"display": { | |||||
"x": 368, | |||||
"y": -80 | |||||
}, | |||||
"parameters": { | |||||
"milliseconds": "" | |||||
}, | |||||
"properties": { | |||||
"milliseconds": "单位毫秒" | |||||
} | |||||
}, | |||||
"b09496f8-4192-46e7-9114-19eca4048ad3": { | |||||
"id": "b09496f8-4192-46e7-9114-19eca4048ad3", | |||||
"name": "Wait", | |||||
"title": "Wait", | |||||
"description": "", | |||||
"display": { | |||||
"x": -48, | |||||
"y": 48 | |||||
}, | |||||
"parameters": { | |||||
"milliseconds": "" | |||||
}, | |||||
"properties": { | |||||
"milliseconds": "单位毫秒" | |||||
} | |||||
}, | |||||
"5e3b77f6-7d41-46cc-98c1-b40be501ef0a": { | |||||
"id": "5e3b77f6-7d41-46cc-98c1-b40be501ef0a", | |||||
"name": "Repeater", | |||||
"title": "Repeater", | |||||
"description": "重复执行", | |||||
"display": { | |||||
"x": -48, | |||||
"y": -16 | |||||
}, | |||||
"parameters": { | |||||
"maxLoop": 3 | |||||
}, | |||||
"properties": { | |||||
"maxLoop": "最大重复次数,-1表示无限" | |||||
}, | |||||
"child": "58d3d3a6-5105-467e-88d3-184857c848aa" | |||||
}, | |||||
"58d3d3a6-5105-467e-88d3-184857c848aa": { | |||||
"id": "58d3d3a6-5105-467e-88d3-184857c848aa", | |||||
"name": "Wait", | |||||
"title": "Wait", | |||||
"description": "", | |||||
"display": { | |||||
"x": 160, | |||||
"y": -16 | |||||
}, | |||||
"parameters": { | |||||
"milliseconds": "" | |||||
}, | |||||
"properties": { | |||||
"milliseconds": "单位毫秒" | |||||
} | |||||
} | |||||
}, | |||||
"g_value": { | |||||
"parameters": {}, | |||||
"id": "GlobalValue", | |||||
"name": "GlobalValue", | |||||
"title": "GlobalValue", | |||||
"description": "全局变量" | |||||
}, | |||||
"custom_nodes": [] | |||||
} |