行为树最后一个要讲的地方,是关于前提(Precondition),在第一部分里,我略微提到了一下,这次我们来仔细看看,再来看看关于前提的纯虚基类的定义:

1: class BevNodePrecondition

2: {

3: public:

4: virtual bool ExternalCondition(const BevNodeInputParam& input) const = 0;

5: };

每一个前提类,都需要实现这个判断的虚函数。我在《用类来表示逻辑运算–关于行为树前提的一种实现方式》提到,我们可以用类来表示逻辑运算,这样的好处是可以做到模块化,同样的判断条件可以复用,所以在库中,我也实现了这种逻辑的表达方式,定义了基本的逻辑运算类

1: class BevNodePreconditionTRUE{};

2: class BevNodePreconditionFALSE{};

3: class BevNodePreconditionNOT{};

4: class BevNodePreconditionAND{};

5: class BevNodePreconditionOR{};

6: class BevNodePreconditionXOR{};

从这些类的名字应该就可以明显的看出这些类的含义了,和逻辑操作符一样,有些类的构造函数需要两个参数,以此来表示二元的逻辑运算(AND,OR,XOR),有些只需要一个参数,以此来表示一元的逻辑运算(NOT)。前提类被用来附在行为树的节点上(每一个节点都可以附加),默认情况下,节点上是没有前提类的,也就是不存在“外在前提”,而只有“内在前提”,这和附了一个BevNodePreconditionTRUE(永远返回True)的“外在前提”的节点是等价的。

好了,行为树库的内容基本就是这些了。接下去我们来看看例子程序,介绍如何用库来创建行为树,例子的代码在BevTreeTest这个工程中,编译后可直接运行,这个例子分别演示了三个行为树,从简单到复杂,单击鼠标可以在这三个例子间切换。这个程序实现了这样一个功能,“在场景地图上,定时会产生一个目标点,智能体就会根据行为树的定义,用不同的行为模式移动到目标点”。

在这个程序中,我为智能体一共定义了4个行为:

1: class NOD_Idle{}; //空闲,表现是颜色不停变化

2: class NOD_Breathe{}; //呼吸,表现是大小规律性变化

3: class NOD_MoveTo{}; //移动,平移到某目标点

4: class NOD_FaceTo{}; //转向,转向到某方向

再定义了2个“外在前提”:

1: class CON_HasReachedTarget{}; //是否到达目标点

2: class CON_HasFacedToTarget{}; //是否朝向目标点

我就用第一个例子来说,第一例子的行为树图如下:

这是一个很简单的行为树,根节点是一个带优先级的选择节点,所以MoveTo比Idle的优先级高,MoveTo带有一个“外在前提”,“当没有到达目标点”时,会选在MoveTo的行为,反之,则选Idle的行为。

在代码中,可以这样来定义这棵行为树

1: BevNode& ret =

2: BevNodeFactory::oCreatePrioritySelectorNode(NULL, "root");

3: BevNodeFactory::oCreateTeminalNode(&ret, "move to")

4: .SetNodePrecondition(new BevNodePreconditionNOT(new CON_HasReachedTarget()));

5: BevNodeFactory::oCreateTeminalNode(&ret, "idle")

6: .SetNodePrecondition(new BevNodePreconditionTRUE());

7: m_BevTreeRoot = &ret;

我在库中定义了一些工厂方法,帮助创建相关的节点。值得注意的是,我在这里演示了用类表示逻辑的用法。我在定义行为树的时候,会用一些格式上的缩进,来表示相应的父子结构,这仅仅是为了视觉上比较明了。当然,以后可以改进行为树的定义接口,更可以用数据文件来定义行为树。

这样定义完毕后,我们就可以用行为树来决策我们的行为了,代码相当简单

1: BevNodeInputParam input(&m_BevTreeInputData);

2: BevNodeOutputParam output(&m_BevTreeOutputdata);

3: if(m_BevTreeRoot->Evaluate(input))

4: {

5: m_BevTreeRoot->Tick(input, output);

6: }

在例子中,我尽量把行为树中要输出的变量写到BevNodeOutputParam结构中(而不是直接修改智能体的信息),这样做的好处是可以让行为树的输入和输出的接口相当清晰,做成黑盒,可以参考我在这里的讨论。

第二个例子演示了并行节点的用法,第三个例子演示了序列节点的用法,就不多说了,大家可以自行看代码。

所有的代码可以通过以下方式获得:

下载地址:

GoogleCode下载点(exe文件夹中已包含可执行文件)

也可用svn通过以下地址来得:

http://tsiu.googlecode.com/svn/branches/blogver/

编译方法:

用VS2005以上打开,选择Debug NoDx或者Release NoDx,编译后,运行BevTreeTest.

相关代码:

TAI_BevTree.h

TAI_BevTree.cpp

关于TsiU

TsiU是我一直在维护的一个自己用的小型的框架,我平时做的一些AI的sample,或者一些工具,都会基于这个框架,TsiU有一些基本的UI控件库,网络模块库,GDI绘图模块,D3D绘图模块等等,可以快速的做成一个小型的示例程序,很方便(具体可参考SampleApps里的例子程序),并且整个架构是用Object的方式来组织,非常容易理解和扩展。整个框架很轻量化,基本就是做了一些底层的基本的功能,这样我在平时做东西的时候,就不需要重新写底层了,把精力都放在高层的实现了。以后分享代码都会基于这个框架,大家也可以通过svn来随时update到我最新的改动。下图就是TsiU里的几个工程介绍,代码不多,大家想看的也可以自己看一下:)

————————————————————————

作者:Finney

Blog:AI分享站(http://www.aisharing.com/)

Email:finneytang@gmail.com

本文欢迎转载和引用,请保留本说明并注明出处

————————————————————————

python3版本800行的代码_用800行代码做个行为树(Behavior Tree)的库(3)相关推荐

  1. 简单20行python代码_用 20 行 python 代码实现人脸识别!Python实现就是这么简单!...

    今天给大家介绍一个世界上最简洁的人脸识别库 face_recognition,你可以使用 Python 和命令行工具进行提取.识别.操作人脸. 基于业内领先的 C++ 开源库 dlib 中的深度学习模 ...

  2. python回测代码_只用3行Python回测你的交易策略

    作者|Lorenzo Ampil 编译|VK 来源|Towards Data Science 自从我开始学习投资,我接触了不同的股票分析方法-技术分析和基本面分析.我甚至读过很多关于这些技巧的书和文章 ...

  3. 安卓清理垃圾清理代码_用方面清理代码

    安卓清理垃圾清理代码 在我以前的文章中,我描述了字母转换,并且提到了我们使用AspectJ来解决该任务,但是我没有提及AspectJ的工作原理和一般性方面. 因此,在接下来的几行中,我将解释: 什么是 ...

  4. 什么样的代码是好代码_什么是好代码?

    什么样的代码是好代码 编码最佳实践 (Coding Best-Practices) In the following section, I will introduce the topic at ha ...

  5. python 代码_如何让Python代码加速运行?

    Python 是一种脚本语言,相比 C/C++ 这样的编译语言,在效率和性能方面存在一些不足.但是,有很多时候,Python 的效率并没有想象中的那么夸张.本文对一些 Python 代码加速运行的技巧 ...

  6. 如何在vscode运行php代码_如何提高 PHP 代码的质量?

    说实话,在代码质量方面,PHP 的压力非常大.通过阅读本系列文章,您将了解如何提高 PHP 代码的质量. 我们可以将此归咎于许多原因,但这肯定不仅仅是因为 PHP 生态系统缺乏适当的测试工具.在本文中 ...

  7. ms查约束具体代码_程序员写代码之前应该做的5件事,看完编程效率瞬间提升

    作者:borisyang,腾讯 WXG 应用开发工程师 作为程序员,刚刚开始学会写代码,常常是接过需求就开始撸代码.有时候发现,写完代码,需求变了.更多时候,觉得写业务代码枯燥无聊,没有技术含量.另外 ...

  8. 河南科技学院计算机专业代码,商丘工学院代码_商丘工学院专业代码_2021商丘工学院招生代码,报考代码...

    更新日期:2021-07-01 18:23 学校类型: 民办学校 教学领域: 电    话:0370-5072102 官网: www.sstvc.com 学校地址: 河南省商丘市长江东路221号 报考 ...

  9. 图像分割技术语义分割代码_用5行代码对150类对象进行语义分割

    图像分割技术语义分割代码 It is now possible to perform segmentation on 150 classes of objects using ade20k model ...

最新文章

  1. 简明Python3教程 4.安装
  2. .Net运行时的相互关系
  3. ajax实现php验证码验证码,PHP验证码之Ajax验证实现方法_PHP教程
  4. 【终于等到你】7种策略解除云风险警报
  5. Spark编译报错问题日志记录
  6. 简谈“开放平台”设计中的一些感悟
  7. 【UML关系(泛化、实现、依赖、关联(聚合,组合))】
  8. <HTML>简单登录页面代码
  9. getinfo怎么用php,PHP curl_getinfo函数
  10. 表示自己从头开始的句子_表示一切从头开始的唯美句子38条
  11. iMac重装系统的问题:无法与恢复服务器取得联系/将安装器信息下载到目标卷宗失败
  12. HTC IMEI码或SN码查询地址
  13. 中台战略-建中台与拆中台
  14. 最通俗易懂的讲解HTTPS的加密原理【多图、易懂】
  15. 【摸鱼神器】UCode Cms管理系统 内置超好用的代码生成器 解决多表连接痛点
  16. python定义一个dog类 类属性有名字_python 基础 12 初识类,类方法,类属性
  17. Xamarin是无懈可击还是鸡肋?浅谈对Xamarin的学习
  18. IDEA中Maven配置出现Cannot resolve plugin org.apache.maven.pluginsmaven-resources-plugin3.1.0
  19. PSP2000可用PDF阅读软件Bookr
  20. connect()函数

热门文章

  1. python制作简易名片管理系统
  2. 126邮箱如何导入html,网易邮箱可拖曳附件:国内邮箱首家支持HTML5
  3. 主机启动键盘鼠标显示器都不亮
  4. npm install报错code128
  5. 央视调查真相:手机丢失后余额宝仍安全!
  6. android 情景感知 sdk,深度学习 情景感知
  7. 集合深入(List)
  8. 逗女友开心的笑话短信:我出生的概率是二千五百亿分之一...
  9. 群策CRM手机App,移动CRM的不二之选
  10. Grafana连接elastic search 实现数据实时显示