CryENGINE3初探Flowgraph(FG)(三)----使用C++创建自定义Node

来源:互联网 发布:openwrt p2p端口 编辑:程序博客网 时间:2024/04/29 01:45

    终于进入代码部分了,反正我很早就跃跃欲试了,虽然中途遇到很多问题,但还是一一解决了,废话不多说,直接步入正题。

    这本教材中提到可以用C++,C#,和lua三种语言编写代码,书中还给了个示例,但是C++的链接已经无效了,所以我们只能不管它,我把C#写的工程示例下载了下来,也是有很多问题,所以今天我们先用C++来创建自定义Node。

    在正式开始之前,版本问题还真得考虑一下。VS只能是2010以上的版本,在这里我使用的是VS2013。而对于CE3的版本,如果大家使用的是3.5系列的话,应该在CE3根目录下直接就有Code文件夹,若果是高一点的版本,比如3.6系列,就只能解压它的压缩包了。还需要说明的一点是,在我们进行编译之前,大家最好把32和64位下的dll备份一下,因为我们实际上就是重新定制自己的dll,如果不备份,会把原先的覆盖掉,这样一旦编译错误,就只能重新解压CE3的SDK了。

    然后,找到c++的解决方案(3.5系列是这个文件:CryEngine_GameCodeOnly),打开它,右键编译一下,看看是否有错误。如果能正确生成dll文件,恭喜你,就可以直接用了,如果提示了很多错误的话,就得根据不同的原因折腾一大会儿了。我这边也是出了很多问题,最后经网上一位大神的指点,总算是解决了。

下图为成功生成dll


    这里具体会遇到哪些问题我也不知道,这就看大家VS玩的怎么样了,我这边出现了中英文字符的问题,降低了一下警告的等级,不把警告视为错误,然后就好了。如果大家在这一步有问题的话,欢迎提出来,我们一起想办法解决。降低警告的方法:右键CryGameSDK,选择属性,然后就是下图了:

    好吧,准备工完成后,我们就正式进入编程这一步。在这里我提前说明一下,我也是刚刚接触CE3的编码,所以里面很多封装好的函数具体的作用什么的也不是分的很清。我觉得在这种情况下,我们不用做太多的纠结,直接先跟着教程来做就是了,慢慢的接触的多了自然就会知道。

    好,那我们就动手吧!C++编写自定义节点共有如下几个步骤:

(一).新建一个cpp文件。

    书上说,我们的Node信息不会在工程的其他区域涉及到,所以不必添加.h文件。

    在CryGameSDK下找到Node文件夹,右键建立cpp文件,取名“TotorialNode.cpp”(totorial:翻译为示例)。然后再文件中需要添加头文件、建立一个类,具体代码为如下:

#include  "StdAfx.h"#include "Nodes\G2FlowBaseNode.h"class CTutorialNode :public CFlowBaseNode < eNCT_Instanced >{
};REGISTER_FLOW_NODE("Tutorial:Multiplier", CTutorialNode);

    书中解释:

  (1)G2FlowBaseNode虽然不是CE3严格意义上的一个组件,但是它封装了许多实用的函数。

  (2)书中对类的定义是这么解释的:CTutorialNode继承自CFlowBaseNode,后面的< eNCT_Instanced >表明了这个node将会成为游戏运行过程中的一个实例。(这句话的理解、还得琢磨琢磨,想一想,我水品有限,也只能翻译到这个地步)。

  (3)REGISTER_FLOW_NODE("Tutorial:Multiplier", CTutorialNode);是用来完成在开始运行时node的注册。

(二)重写父类的函数

//书中解释:我们不需要存储任何静态的变量,所以我们就简单的使用Publicpublic:CTutorialNode(SActivationInfo *pActInfo){}virtual IFlowNodePtr Clone(SActivationInfo *pActInfo){return new CTutorialNode(pActInfo);}//端口被触发时调用,我们大部分都在这个地方写逻辑virtual void ProcessEvent(EFlowEvent evt, SActivationInfo *pActInfo){}//配置节点的显示,输入和输出virtual void GetConfiguration(SFlowNodeConfig &config){}//这个函数并不需要我们重写任何的实现,我们在在内存为这个函数只需要添加一个声明virtual void GetMemoryUsage(ICrySizer *s) const{}

(三)实现Node的配置函数
//添加枚举类型enum EInput{EIP_Activate,EIP_Left,EIP_Right};enum EOutput{EOP_Result};

//配置节点的显示,输入和输出virtual void GetConfiguration(SFlowNodeConfig &config){static const SInputPortConfig inputs[] ={InputPortConfig_Void("Activate", "MyDes:Trigger the calculation"),//端口名,默认值,描述InputPortConfig<float>("Left", 0, "MyDes2:The left side of the calculation"),InputPortConfig<float>("Right", 0, "MyDes2:The right side of the calculation"),{ 0 }};static const SOutputPortConfig outputs[] ={OutputPortConfig<float>("Reslut", "The Result of the calculation"),{ 0 }};config.pInputPorts = inputs;config.pOutputPorts = outputs;config.sDescription = _HELP("Multiplies two numbers");config.SetCategory(EFLN_APPROVED);}
(四)实现ProcessEvent函数

//端口被触发时调用,我们大部分都在这个地方写逻辑virtual void ProcessEvent(EFlowEvent evt, SActivationInfo *pActInfo){switch (evt){case IFlowNode::eFE_Activate:{if (IsPortActive(pActInfo, EIP_Activate)){float left = GetPortFloat(pActInfo, EIP_Left);float right = GetPortFloat(pActInfo, EIP_Right);float ans = left * right;//把ans值更新到输出端口数组ActivateOutput(pActInfo, EOP_Result, ans);}}break;}}

好了,代码就这样了。最后把完整的C++代码贴在下面

/*这是个添加自定义节点的代码*/#include  "StdAfx.h"#include "Nodes\G2FlowBaseNode.h"class CTutorialNode :public CFlowBaseNode < eNCT_Instanced >{//添加枚举类型enum EInput{EIP_Activate,EIP_Left,EIP_Right};enum EOutput{EOP_Result};//书中解释:我们不需要存储任何静态的变量,所以我们就简单的使用Publicpublic:CTutorialNode(SActivationInfo *pActInfo){}virtual IFlowNodePtr Clone(SActivationInfo *pActInfo){return new CTutorialNode(pActInfo);}//端口被触发时调用,我们大部分都在这个地方写逻辑virtual void ProcessEvent(EFlowEvent evt, SActivationInfo *pActInfo){switch (evt){case IFlowNode::eFE_Activate:{if (IsPortActive(pActInfo, EIP_Activate)){float left = GetPortFloat(pActInfo, EIP_Left);float right = GetPortFloat(pActInfo, EIP_Right);float ans = left * right;//把ans值更新到输出端口数组ActivateOutput(pActInfo, EOP_Result, ans);}}break;}}//配置节点的显示,输入和输出virtual void GetConfiguration(SFlowNodeConfig &config){static const SInputPortConfig inputs[] ={InputPortConfig_Void("Activate", "MyDes:Trigger the calculation"),//端口名,默认值,描述InputPortConfig<float>("Left", 0, "MyDes2:The left side of the calculation"),InputPortConfig<float>("Right", 0, "MyDes2:The right side of the calculation"),{ 0 }};static const SOutputPortConfig outputs[] ={OutputPortConfig<float>("Reslut", "The Result of the calculation"),{ 0 }};config.pInputPorts = inputs;config.pOutputPorts = outputs;config.sDescription = _HELP("Multiplies two numbers");config.SetCategory(EFLN_APPROVED);}//这个函数并不需要我们重写任何的实现,我们在在内存为这个函数只需要添加一个声明virtual void GetMemoryUsage(ICrySizer *s) const{s->Add(*this);}};REGISTER_FLOW_NODE("Tutorial:Multiplier", CTutorialNode);

最后,注意把位数、目录选择好,就可以编译生成dll了



打开相应CE3的版本,就可以看到我们添加的自定义Node了


    


好了,今天就先到这里,明天我试着尝试用C#编辑一下,如果成功的话,就和大家分享经验,如果不成功的话,就暂时只能先放在一边了,除此之外,做个总结,教程第三章就算完成了!如果大家有问题可以直接留言,更希望如果大神能看到这篇文章,能给出一些指点!


0 0