用800行代码做个行为树(Behavior Tree)的库(2
上一次说到了节点的基类,它描述了在行为树上一个节点的基本结构。我们知道,在行为树上有两大类的节点,一种我称之为“控制节点”,像“选择节点”,“并行节点”,“序列节点”都属于此类,这类节点负责行为树逻辑的控制,是和具体的游戏逻辑无关的,属于行为树库的一部分,并且这类节点一般不会作为叶节点。还有一类称为“行为节点”,也就是行为树上挂载的具体行为,是和游戏逻辑相关的,不属于行为树库的一部分,需要自己去继承和实现,这类节点一般都作为叶节点出现。
先来看看“行为节点”的代码,我先从节点的基类继承了一个所有“行为节点”的基类
1: class BevNodeTerminal : public BevNode
2: {}
在它的Tick方法中,我做了一个简单的状态机(可以自行看代码),负责处理进入行为(Enter),更新行为(Execute),退出行为(Exit),所有的行为节点应该继承自BevNodeTerminal类,并且重写这些虚函数,在进入和退出行为里,可以做一个初始化和清理的工作:
1: class BevNodeTerminal : public BevNode
2: {
3: protected:
4: virtual void _DoEnter(const BevNodeInputParam& input) {}
5: virtual BevRunningStatus _DoExecute(const BevNodeInputParam& input, BevNodeOutputParam& output) { return k_BRS_Finish;}
6: virtual void _DoExit(const BevNodeInputParam& input, BevRunningStatus _ui_ExitID) {}
7: }
值得注意的是,在Tick方法中,它有一个返回值,表示当前节点是否处理完毕,在库中,我定义了一个enum来表示节点的运行状态:
1: enum BevRunningStatus
2: {
3: k_BRS_Executing = 0,
4: k_BRS_Finish = 1,
5: ...
6: };
当返回k_BRS_Finish的时候,就表示当前节点已经处理完毕了,如果再次进入该节点,就认为是重新进入了。用上面描述的那个状态机的来说的话就是,如果是重新进入,会先调用_DoEnter方法,然后调用_DoExecute方法,如果_DoExecute返回正在运行(k_BRS_Executing),那么以后再进入这个节点就会直接调用_DoExectue,如果返回已经结束(k_BRS_Finish),则会调用_DoExit,以后再进入这个节点就会重新调用_DoEnter方法了。
对于控制节点来说,它的运行状态和子节点的运行状态是息息相关的,比如,选择节点的运行状态,就是它当前选择的这个节点的运行状态,并且,有时控制节点的控制逻辑也和子节点的运行状态有关,比如序列节点,当它前一个子节点运行结束,序列节点就会自动的切换到下一个子节点运行。所以在实现具体的行为类时,我们应该要正确的返回节点的运行状态。在例子程序中,我做的一个“空闲”(idle)的行为节点,就能很好的说明问题:
1: class NOD_Idle : public BevNodeTerminal
2: {
3: public:
4: NOD_Idle(BevNode* _o_ParentNode)
5: :BevNodeTerminal(_o_ParentNode)
6: {}
7: protected:
8: virtual void _DoEnter(const BevNodeInputParam& input)
9: {
10: m_WaitingTime = 0.5f;
11: }
12: virtual BevRunningStatus _DoExecute(const BevNodeInputParam& input, BevNodeOutputParam& output)
13: {
14: const BevInputData& inputData = input.GetRealDataType<BevInputData>();
15: BevOutputData& outputData = output.GetRealDataType<BevOutputData>();
16:
17: f32 timeStep = inputData.m_TimeStep;
18: m_WaitingTime -= timeStep;
19: if(m_WaitingTime < 0)
20: {
21: outputData.m_BodyColor = D_Color(rand() % 256, rand() % 256, rand() % 256);
22: return k_BRS_Finish;
23: }
24: return k_BRS_Executing;
25: }
26: private:
27: float m_WaitingTime;
28: };
这段代码中的某些内容不明白也没有关系,我们主要关注的是关于节点运行状态的部分。这个Idle行为做了一件这样的事,就是不停的变换自己的颜色,间隔是0.5秒,当时间一到,就会返回运行结束(k_BRS_Finish),并输出当前的颜色,当时间还没到,则返回运行中(k_BRS_Executing),并且维持当前颜色。可以看到,我们用运行状态控制了计时器的重置,选择在_DoEnter方法中重置了计时器,当然,更合理的做法是在时间一到的时候,就重置计时器,并且永远返回运行中,不过这个例子里,我主要就是想用来演示运行状态,和_DoEnter的相关用法。
接下去再来看看控制节点,我一共写了5种控制节点,带优先级的选择节点(BevNodePrioritySelector),不带优先级的选择节点(BevNodeNonePrioritySelector),序列节点(BevNodeSequence),并行节点(BevNodeParallel),循环节点(BevNodeLoop),这些节点的进入条件和选择逻辑都是按照在行为树中改节点的定义来做的,我想用一张表格来说明:
可能看表格内的描述会感觉有点拗口,可以结合代码一起看,会理解的更好。特别要提一点的是,在某些控制节点的Evaluate方法中,我会修改和记录可以运行的节点索引,当调用Tick的时候,就可以用这个索引来找到可以运行的节点了。这种模式和我以前提到的行为树更新模式有点不太一样,不过本质上是相同的。
(待续…)
转载于:https://blog.51cto.com/568464209/1732927
用800行代码做个行为树(Behavior Tree)的库(2相关推荐
- c语言800行代码系统,用800行代码做个行为树(Behavior Tree)的库(1)
最近一直在忙新项目的准备,甚少涉及AI的东西,所以博客也疏于更新.春节前,收到一个网友的邮件,说看了行为树的一些东西,但还是不知道如何去入手实现,我就乘着春节假期,动手写了一个简单的行为树的库,和大家 ...
- python3版本800行的代码_用800行代码做个行为树(Behavior Tree)的库(3)
行为树最后一个要讲的地方,是关于前提(Precondition),在第一部分里,我略微提到了一下,这次我们来仔细看看,再来看看关于前提的纯虚基类的定义: 1: class BevNodePrecond ...
- 用800行代码做个行为树(Behavior Tree)的库(3)
转自http://www.aisharing.com/archives/530 行为树最后一个要讲的地方,是关于前提(Precondition),在第一部分里,我略微提到了一下,这次我们来仔细看看,再 ...
- 初次玩pyecharts:30行代码做一个可视化广东省各地天气温度排行图
初次玩pyecharts:30行代码做一个可视化广东省各地天气温度排行图 开篇点题,直接上效果图 开篇再点题,直接上源码 import re import requests from pyechart ...
- 使用行为树(Behavior Tree)实现游戏AI
注意:本文版权归Csdn AKara所有,此处纯粹转载,如有再转,请严格按如下方式显示标明原创作者及出处,以示尊重!! 关注公众号 风色年代(itfantasycc) 200G Unity资料合集送上 ...
- 使用行为树(Behavior Tree)实现网游奖励掉落系统
原地址:http://blog.csdn.net/akara/article/details/6165421 [原创]使用行为树(Behavior Tree)实现网游奖励掉落系统 by AKara 2 ...
- 行为树 Behavior Tree 原理
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接: https://blog.csdn.net/LIQIANGEASTSUN/arti ...
- 行为树 Behavior Tree 原理 一
行为树 Behavior Tree 原理 一 行为树 结构图如下,一棵倒置的树 行为树采用节点描述行为逻辑,主要节点类型有: 组合节点:选择节点.顺序节点.随机选择节点.随机顺序节点.随机权重节点.并 ...
- 用30行代码做一个微信智障机器人
起因是某天早上看到这样一条朋友圈: 微信啥时候还有会员了?可怕,花里胡哨,这是要往QQ的方向发展吗.还是 Telegram 比较存粹. 连IS恐怖组织都在使用,最安全的即时通讯软件--Telegram ...
最新文章
- 10个你必须知道的ios框架
- 设计干货素材|使用纹理背景的技巧
- gif 动态加载_搞笑GIF:这个游戏最大的成功就是失败!
- 查看app包名和启动页Activity的方法
- 【研发管理】质量管理之约瑟夫·M.朱兰
- 机器人仿真软件介绍(V-REP,ROS等等)
- UML(统一建模语言)
- 计算机里面的wps如何删除,如何快速删除电脑上的wps的所有换行符
- 用R语言进行Cox回归生存分析
- Excel---饼图美化与ppt图表
- 以太坊2.0协议核心Beacon链详解
- 淘宝/天猫API接口,获得淘宝商品详情高级版
- https 以及内网如何使用
- 分享一个图片管理程序,图片批量上传,图片管理(有图片)
- Python爬虫自学笔记(三)动态网页爬取
- Python学习笔记 | opencv图像处理(一)
- HTML网页设计基础期末作业——仿Coco线上订奶茶饮料网站设计与实现6个页面(HTML+CSS+JavaScript)...
- Solidity 基础知识
- 怎么计算byte,short,int等数据类型的取值范围
- ArcGIS server使用动态工作空间的服务发布及利用ArcGIS API for Javascript添加动态图层
热门文章
- NFS共享服务搭建笔记
- redis主从复制下哨兵模式---选举原理
- vs2010类文件添加版权版本作者信息
- 洛谷1941飞扬的小鸟
- Visual Studio中的TabControl控件的用法
- [转]详细的mysql时间和日期函数
- VMware vSphere开发(1)安装配置VMware vSphere Web Services SDK的运行环境
- UML中符号的意义(转)
- Linux安装Apache报错:Cannot find a valid baseurl for repo: base/7/x86_64解决方案
- ios端 input输入框遮挡问题解决