@ -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": [] | |||
} |