加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

torque源码分析

发布时间:2020-12-15 06:30:48 所属栏目:百科 来源:网络整理
导读:转自 ? ??独自等待 ? ? ? ? http://blog.sina.com.cn/cpytiger 0. 准备知识: 0.1如何拓展引擎类例如添加成员函数和成员变量,并且能够通过脚本调用,请参看TDN文章:http://tdn.garagegames.com/wiki/Code/How_do_I_make_a_scriptable_object%3F。或者参看1

转自

? ??独自等待

0. 准备知识:

0.1如何拓展引擎类例如添加成员函数和成员变量,并且能够通过脚本调用,请参看TDN文章:http://tdn.garagegames.com/wiki/Code/How_do_I_make_a_scriptable_object%3F。或者参看1.7官方手册,在这里就不详细说明。然而这篇教程仅仅告诉了你如何做一个可以用于C++的类,却没有涉及如何在C++调用脚本代码。在这里简单做一些介绍:void Gui3DWheel::onSelectChanged(U32 selectID){ Con::executef(this,"onSelectChanged",Con:: getIntArg_r(selectID ));}上面的代码是在onSelectChanged函数调用的时候,然后执行Console 函数onSelectChanged,传 入的参数类型为Int,参数为selectID。此时如果我在脚本环境下 定义了函数:function PickerButtonHolder:: onSelectChanged (%selectID){ //Do something…}那么在这个时候次函数便 会被调用。

0.2 Datablock Class,Object Class,Datablock Instance,Object Instance的联系与区别如果你不明白上面4个定义之间的区别,参看1.7官方手册->ScriptingReference->Introduction->Datablocks,上面有非常清晰的例子说明。TSStatic,GameBase的区别如果你不明白上面两个类的区别,请参看TDN文章http://tdn.garagegames.com/wiki/DTS/Scripting/AddingObjects,上面的说明同样非常清 晰。

?0.3 Torque Networking的工作方式因为我们已经学习了计算机网络的课程,是时候将他们用在实际的项目理解中了,Torque的网络协作方式可以通过这篇文章理解,如果结合源代码来看,那么你会发现很多都是我们学过的内容,例如ConnectionProtocol 类,它就采用了滑动窗口协议。此外,这篇文章里面还包含了一些相关结构和函数的作用,例如MoveWritePacketData,ReadPacketData等等。

1. Player类结构: 按照Object Class和Datablock Class的结构,Player类拥有与之对应的Player和 PlayerData,PlayerData里面的数据定义在创建Mission的时候由 服务器下发到客户端, 当创建一个玩家的时候,那么我们可以用指定的PlayerData来创建我们的Player。类成员 大部分都是Public或者是Protected,也就是说,这些成员都是可以被 子类所继承的。

2.GameBase 与Player相关的重要的函数多继承于GameBase类,从第三篇文章我们可以获知GameBase类 拥有自己 的Datablock,网络特性和更新特性。

2.1 GameBaseData GameBase类拥有自己的数据块GameBaseData。只是定义了一些基类的属性包括StringTable 和Packed两个属性,以及一些相关的成员函数。主要是为子类继承提供模板。

2.2 GameBase 网络特性 GameBase的网络特性主要由以下两个虚函数提供: 1.writePacketData():客户端传向服务器的消息一般通过这个函数传递。 2.readPacketData():读取服务器端的函数,并返回校验值。 显然,我们可以重写writePacketData()来向服务器端发送自己的速度或者状态息, 并且重写 readPacketData()来读取服务器的信息。

2.3 GameBase 更新特性 GameBase有两种更新方式,按照一般引擎的说法,即分成基于游戏逻辑的更新ProcessTick, 基于游戏 时间的更新AdvanceTime: ProcessTick():每隔32ms更新一次,无关FPS。通常用来更新位置,状态等和游戏逻辑有关的状态信息。 AdvanceTime():实际游戏时间的更新。通常用来更新动画等和游戏时间相关的信息。 interpolateTick():用来在两个Tick之间插值的函数。

3. ShapeBase ShapeBase提供了基本的模型载入,声音,动画以及伤害状态,能量,物理,以及提供给你了 嵌入点可以给你嵌入物体和图片等功能。这个类已经十分强 大,涉及到游戏的方方面面, 共计有4千行代码。在此仅仅挑些我觉得重要的方法来叙述一下。

3.1 ShapeBaseData ShapeBaseData里包含了和阴影相关的属性,爆炸相关的属性,物理相关的属性。 更为重要的是,ShapeBaseData里包含了模型数据的数据。Resource shape和相关的 BoundingBox,然而却没有包含碰撞的盒子信息,碰撞盒子的信息被延迟到ShapeBase类里被包含。 另外一点比较重要的是,这个时候,我们已经发现源代码中包含有大量的ConsoleMethod的声明, 来供脚本引 擎调用。我随便翻查一个我们平时调用的方法:?

?ConsoleMethod( ShapeBase,setWhiteOut,void,3,"(float flashLevel)") { F32 flash = dAtof(argv[2]); if (object->isServerObject()) object->setWhiteOut(flash); } 我们便可以发现,在脚本使用SetWhiteOut这个函数的时候,返回值为void,最小需要3个参数, 最大需要3个参数,说明为“flashLevel”,方法类为ShapeBase。而脚本引擎的setWhiteOut 最终被解析成 C++引擎中的setWhiteOut(flash)这个函数: void ShapeBase::setWhiteOut(const F32 flash) { mWhiteOut = flash; if (mWhiteOut < 0.0) mWhiteOut = 0; else if (mWhiteOut > 1.5) mWhiteOut = 1.5; } 更多的时候,我们并不会那么容易找到它脚本引擎中的函数所对应的C++代码,因为脚本本身 可以定义函数,所以一句脚 本通常会首先解释成脚本里的函数,才进一步解释成C++的代码, 这个时候则需要我们耐心地一次次跟踪和查找。

3.2 ShapeBase ShapeBase里最重要的三个数 据成员: ShapeBase* mControllingObject; //控制对象 ShapeBaseData* mDataBlock; //相应的数据块 Convex * mConvexList; //碰撞盒子列表 比较重要的成员函数:

?3.2.1. 物理碰撞检测方面: 物理碰撞在发生了以后,会被添加到一个列表里面,当这个物理碰撞Timeout了之后,便会得到通知 (默认为0.1s)。 void notifyCollision(); virtual void onCollision(ShapeBase* object,VectorF vec); void queueCollision(ShapeBase* object,const VectorF& vec);

4. Player

4.1 PlayerData 相信PlayerData里的数据成员无需在这里再做详述了,因为在游戏开发大全的第5章有非常详细的列表 来说明情况。

4.2 Player Player里面的最重要的函数莫过于ProcessTick(),ProcessTick()的详细流程如下: 而ProcessTick()里的信息均来自于unpackUpdate,以及所有要发送的信息都是通过packUpdate()来完成, 这两个重要的函 数用于与网络中的其他玩家同步。

5. 更改Player结构

5.1 为Player添加分组 首先,我们有两个地方可以添加分组信息,可以在PlayData里添加,也可以在Player类里添加,这个时候, 就要根据各自的需求去完成了。 在Datablock里放的话,我们在一开始的时候 现在我们简简单单地为Player加上分组,只需要修改三处地方便可。

?1. 首先在Player公共域内添加一个成员变量: int team;?

?2. 由于Player类没有重写initPersistFields(),我们需要重写了这个变量,那么才可以将Player中的 team变量 暴露在脚本中调 用,否则我们可以通过写Console 函数来访问Player里的属性。所以在此我们重写 initPersistFields(): void Player::initPersistFields() { Parent::initPersistFields(); addField( "team",TypeS32,Offset( team,Player) ); }?

?3. 重写了之后,我们便可以重新编译引擎。以后在脚本中,我们便可以直接通过%player.team来访问 team属性了。

5.2 为Player函数添加魔法攻击 掌握了上面的知识之后,想要做出魔法攻击仍然是比较困难的,因为对于魔法攻击而言, 魔法效果和魔法返回都是需要程序控制的,魔法效果可以通过创建一个动态 Trigger来实现范围魔法, 而对于绚丽的魔法效果而言,需要控制就比较困难了。 因此学习Torque绘图函数就变得非常有必要。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读