Dorothy物理编辑器

一、物理编辑器的介绍

  在Dorothy中有对Box2D物理引擎进行了封装。Box2D是一个十分纯粹的2D物理运算的程序库。给它设定好输入的几何图形以及物理属性,它就能持续地模拟出这些物理对象接下来的速度、加速度、碰撞、弹性和摩擦等等的物理变化来。因为Box2D提供的只是纯粹演算得来的数据,所以在游戏中使用需要把这些数据转换为图形的几何变化。这个很好办,我们只要通过把CCNode的transform()函数重写一下,让它在图形上的几何transform依据b2Body的物理数据来进行计算,就可以将物理变化同步到图形变化上来了。由此Dorothy中衍生了继承自CCNode并同步于b2Body的物理节点类oBody。
  当然这只是应用物理引擎的一个很小的基础准备。Box2D是非常专业的2D物理引擎,它提供的功能具体包括:

  • 刚体(Body):是基本的物理对象单位,包括密度、弹性系数、摩擦系数、速度衰减系数、角速度衰减系数、是否会旋转、是否启用高速物体运算、受重力影响系数、物体运动类型等属性。在2D环境中一个刚体可以视为厚度匀为一米无法在Z轴方向运动的物体。
  • 几何形状(Fixture):矩形、圆形、凸多边形、折线、闭合的折线等等。几何形状可以附加到刚体上,根据形状面积的不同将改变刚体的质量,同一个刚体上可以任意添加多个几何图形并组合成一个不能分割的整体。刚体的质心也随着添加形状的不同而变化。
  • 几何形状感应器(Sensor):刚体上除了可以添加几何形状,还可以添加几何形状的感应器,感应器是附加到刚体上,随刚体运动的不同形状的区域,没有质量也不会和刚体发生碰撞,只在刚体进入和离开感应区域时产生回调事件。
  • 关节(Joint):关节是连接两个刚体并指定这两个刚体间力的作用方式,或是限制刚体间运动规则的一些控制器。有:距离关节、摩擦关节、滑轮组、弹簧、活塞、传动装置、转动关节、轮子、焊接关节、绳索关节以及一个用于和刚体互动的移动关节等。其中的活塞、转动关节和轮子等关节还带有发动机的功能,可以指定动力值,推进速度或是转速。
  • 控制器(Controller):控制器是用于对一组刚体进行特殊地受力或是运动控制的模块。在Box2D的Contribution中有一些比如风力,和液体中的浮力的模拟控制器。

  以及Box2D有一些限制,它使用的是MKS标准的物理学单位。因为浮点数的精度限制,模拟的动态刚体的直径最好是在0.1米至10米的范围内,否则模拟会变得不太准确。还有就是堆叠物体时,叠在上面的物体的质量不能超过在下面物体的质量的10倍,否则物理表现也会变得很糟糕。当然这些限制只要小心处理,对于游戏运用物理引擎的影响并不大。
  但是游戏中使用的Box2D一个很明显的问题就是,物理引擎功能那么多,要用好真的不容易,我一直很想能好好运用Box2D特别是关节和发动机的功能制作一些机械结构,最后发现没有一个好的可视化编辑工具,非常难以驾驭Box2D。使用纯的Box2D的代码创建物理刚体,代码十分繁杂,而且又有直径为0.1~10的物理单位的要求,实际在引擎中使用时还要做物理单位和游戏坐标的转换。所以虽然有很多现有的能通过可视化编辑,生成原生Box2D代码的工具,但仍然用起来不是很方便。于是我自己写了这个和Dorothy框架深度整合物理编辑器BodyEditor。

二、一些基础准备

  前面提到使用物理引擎时需要做物理单位到游戏坐标的转换,Dorothy框架已经为此做了些工作。Dorothy中默认使用了1:100的系数,把物理距离转换成游戏坐标,这个系数个人认为比较合理,就是说Dorothy中默认支持10个像素到1000像素单位直径的动态物件。几乎可以涵盖一般的物件大小了。
  这个物理编辑器的定位是制作独立的物理物件,比如一个小车、一件物理器械、或是制作一个静态的地形场景,然后在游戏中逐个物件加载和独立使用。不建议用作一个完整的游戏编辑器,并在一次编辑中放入各种各样的物件。因为这样会导致编辑的物件难以复用。

三、编辑器的使用

  1.资源输入和输出

  编辑器的资源目录,在Windows下debug版的目录为可执行程序所在路径下的Body目录,Windows下release版的目录为C:\User\Username\AppData\Local\Dorothy\Body;在Mac下的目录为/Users/Username/Library/Caches/Body。在资源目录下有一个Input和一个Output的文件夹,Input文件夹中可以放入.png、.clip和.model结尾的Dorothy图片和动画资源,Output文件夹是编辑器生成文件存储的位置,生成的物件数据文件以.body结尾。导入.body物件数据于Dorothy框架使用时,需要同时拷贝Input中使用的图片或是动画文件到框架的资源目录中使用。

  2.编辑器界面

物理编辑器界面1
物理编辑器界面2
  所有的编辑都在同一个界面中完成。进入编辑器首先会弹出要编辑物件的选择面板,选择后进入编辑界面,左侧一列有一些功能按钮,从上往下分别为:
  • 编辑按钮(Edit),用于保存或是切换要编辑的物件。
  • 矩形按钮,用于新建一个矩形刚体(Rectangle)或是给刚体添加一个额外的子矩形形状(SubRectangle),这里新建的矩形只包括直角矩形,不包括平行四边形。
  • 圆形按钮,用于新建一个圆形刚体(Circle)或是给刚体添加一个额外的子圆形形状(SubCircle)。
  • 多边形按钮,用于新建一个凸多边形刚体(Polygon)或是给刚体添加一个额外的子多边形形状(SubPolygon)。添加的多边形最多只支持8个顶点,但这不是问题,想要更多顶点,或是想要创建凹多边形,可以通过给同一个刚体添加多个子多边形组合而成。
  • 折线按钮,用于新建一个由任意多个顶点组成的折线(Chain),或是给刚体添加子折线(SubChain)。如果一个刚体上只有折线的话,会因为没有质量而不能旋转。并且折线和折线之间不会发生碰撞,折线和其他形状才会发生碰撞。
  • 闭合折线按钮,用于新建闭合的折线(Loop),或给刚体添加子图形(SubLoop),闭合折线可以形成一个首尾相连的封闭区域。
  • 删除按钮,用于删除任何在右上角面板中选择的物理对象。
  • 新建关节,点击后弹出新关节的选择面板。

  3.播放按钮

  点击右下角的播放键形状的按钮可以让物理世界运行起来,进入运行模式,可以测试一下编辑的物件。开启运行模式以后,如果之前编辑时有正确添加了发动机关节的话,屏幕上方会出现一些开关发动机的按钮,可以用来测试发动机的效果。

  4.位置调节的辅助按钮

  有时候界面上方会出现两个画着红色的方向箭头,箭头上还有一个白色的小叉的按钮。一个按钮的箭头方向是向右,另一个按钮的箭头方向是向上。当点击了向右箭头的按钮后,按钮的颜色会变为红色,然后在进行编辑操作时,只有纵向的操作有效,横向的操作会被禁用。当点击向上的箭头时又变为禁用纵向的操作。

四、物件的制作方法

  1.制作一般的刚体

  制作普通的刚体,比如矩形和圆形刚体很简单。

  • 选择左侧的对应形状的按钮,处于选中状态的按钮会变为红色。
  • 在编辑区域点击要创建刚体的屏幕位置,完成刚体的创建。
  • 设置刚体的类型(Type),可以为动态(Dynamic)、静态(Static)和绝对运动态(Kinematic)。动态的刚体可以随意运动、旋转和互相碰撞,可以用作一般可以互动的游戏物件;静态刚体不能做任何运动,可以作为地形物件;绝对运动的刚体是一种具有无限大质量的刚体,只有动态刚体会和它碰撞,只能通过设定移动速度和角速度让它运动起来,可以用作比如超级玛丽中的移动平台之类的机关。
  • 设置刚体的名称(Name),形状大小(Size|Radius)。
  • 设置密度(Density),取值可以为[0,+)。
  • 设置摩擦系数(Friction),取值可以为[0,1]。Box2D使用该摩擦系数同时作为静摩擦系数和动摩擦系数,接触的两个物体之间的摩擦系数通过f=sqrt(f1*f2)计算得出,如果其中任意一个物体的摩擦系数为0,那么这两个物体间就不会产生摩擦。
  • 设置弹性系数(Restitution),取值可以为[0,1],弹性系数为0时表示该刚体碰撞时只会发生非弹性碰撞,为1时表示碰撞时发生完全弹性碰撞。
  • 设置速度衰减(LinearDamping)和旋转衰减(AngularDamping),取值为[0,+),为0时表示没有任何衰减,为正无穷时表示完全无法运动。速度衰减可以用于模拟受到空气阻力的影响,旋转衰减可以用于模拟轮轴摩擦力的影响。
  • 设置位置(Position)和图形中心(Center),同一个刚体上可以添加任意多个形状,所以位置指的是刚体在世界中的位置,图形中心指的是刚体上的形状中心相对于刚体中心的位置。
  • 设置禁止刚体旋转(FixedRotation),设置为true时,刚体则不会旋转,用于制作2D横板的人物角色。
  • 设置重力系数(GravityScale),可以设置为任意值,为1时表示受到正常的重力,为0时表示不受任何重力,为-1时表示受到完全反向的重力。可以用来制作气球或是其它反重力的物件。
  • 设置是否高速运动(Bullet),如果制作的刚体要用于进行高速运动,比如用作子弹,则可能需要开启这个选项。因为普通的刚体运动速度过快时,可能会直接穿过其它较小物体,而不与其发生碰撞。开启高速运动模式后,Box2D会给这个刚体进行额外的计算以保证它不会出现穿透的问题。
  • 设置为感应器(Sensor),设置刚体上的形状为感应器,感应器只是一个单纯的感应区域,没有质量也不会发生碰撞,可以随着刚体移动。有其它刚体进出感应区域时会触发事件回调。比如可以用于检测人物角色的脚下有没有接触地面。创建感应器后,还需要在程序中进行后续的使用和处理。
  • 设置感应器编号(SensorTag),给感应器设置一个整数作为编号,这个编号将在程序中用于获取刚体上的感应器对象。
  • 设置外观(Face),可以在编辑器中给刚体设置外观,在编辑器中显示的各种线框图形只是一些用于调试的图形,不适合在游戏中使用,所以游戏真正使用的物件还需要设置相应的外观。外观支持.png图片,.clip切片图片和.model的模型。点击设置外观后会弹出外观资源的选择面板,外观资源会从编辑器资源目录下的Input文件夹中读取。选择要使用的外观后,新外观会显示在刚体的位置。
  • 设置刚体外观的位置(FacePos),设置刚体外观在刚体上的摆放位置。

  2.制作多顶点的刚体

  多顶点的刚体比如多边形(Polygon)和各种折线(Chain|Loop)。他们的一般属性的设置与普通刚体相同,但是他们的形状需要通过自己添加顶点来设置。设置顶点要点击右下角属性框的Vertices属性,然后屏幕上方会出现一个“+”号按钮,一个“-”号按钮,以及两个位置调节的辅助按钮。点击“+”号按钮后,该按钮会变成红色,并进入顶点的添加模式,然后连续点击屏幕上要添加顶点的位置可以持续添加顶点,再次点击“+”号按钮退出顶点的添加模式。点击“-”号按钮后会进入顶点删除模式,再次点击后结束删除模式。

  3.给刚体添加子形状

  当选择了左侧的新建形状按钮后,在右上的面板中选择要添加子形状的刚体,然后点击屏幕上要创建子形状的位置即可创建子形状。子形状在右下属性窗口中的名称会以“Sub”开头,并会被减少一些可以设置的属性。

  4.制作距离关节

  距离关节用于连接两个刚体,并将两个刚体保持一段固定的距离。还可以使刚体之间的连接具有弹性。可以用来制作粘粘世界。

  • 通过左下角按钮打开关节面板,选择Distance。
  • 设置关节的名称(Name)。
  • 设置连接的刚体之间是否会碰撞(Collision)。
  • 选择要连接的刚体(BodyA|BodyB),刚体的选择通过在编辑界面直接点选。
  • 设置Frequency和Dumping属性,用于调节距离关节的弹性。Frequency属性为0时禁用弹性,大于0时,数值越大弹性越差;Dumping属性取值范围为[0,1],当为0时受到外力会持续地进行反弹,不容易恢复静止,当为1时受力反弹后会很快恢复静止。

  5.制作摩擦关节

  摩擦关节用于给两个刚体之间附加额外的摩擦力作用,一般用于配合转动关节和活塞使用。

  • 通过左下角按钮打开关节面板,选择Friction。
  • 设置关节的名称(Name)。
  • 设置连接的刚体之间是否会碰撞(Collision)。
  • 选择要连接的刚体(BodyA|BodyB),刚体的选择通过在编辑区域直接点选。
  • 设置施力点(WorldPos),如果用于被转动关节连接的刚体,则移动施力点的位置到转动的中心点;如果用于被活塞关节连接的刚体,则移动施力点到活塞的推进点位置。可以使用双击快捷移动施力点。
  • 设置线性摩擦力(MaxForce),单位是牛顿。被连接的刚体会同时受力。
  • 设置转动摩擦力矩(MaxTorque),单位是牛顿•米。被连接的刚体会同时受力。

  6.制作滑轮组

  是一组两头固定重物(刚体),中间经过两个定滑轮的滑轮组。如果想要其他结构的滑轮组,比如只有一个定滑轮,或是增加动滑轮的等等的话,都可以用这个关节稍加调整和组合得到。

  • 通过左下角按钮打开关节面板,选择Pulley。
  • 设置关节的名称(Name)。
  • 设置连接的刚体之间是否会碰撞(Collision)。
  • 选择要连接的刚体(BodyA|BodyB),刚体的选择通过在编辑区域直接点选。
  • 设置刚体上的连接点的位置(AnchorA|AnchorB)。
  • 设置定滑轮的位置(GroundA|GroundB),可以使用双击快速移动位置。

  7.制作弹簧

  弹簧是一种会使目标刚体恢复到初始位置和旋转角度的关节。只支持将一个动态刚体连接到一个静态刚体上,否则表现会不太正常,并且刚体只能受到固定大小的回复力,和真正的弹簧还是有些区别。其实官方把这个关节叫做发动机(Motor),我觉得不像发动机,它的特性更像弹簧一些,所以我把它叫作了弹簧。

  • 通过左下角按钮打开关节面板,选择Spring。
  • 设置关节的名称(Name)
  • 设置连接的刚体之间是否会碰撞(Collision)。
  • 选择要连接的刚体,BodyA应该选择静态刚体,BodyB选择动态刚体,受到回复力的对象为BodyB。
  • 设置BodyB要回复到的位置(Offset),可以使用双击快速移动位置。
  • 设置BodyB要回复到的角度(AngularOffset)。
  • 设置回复BodyB作用的线性力和力矩(MaxForce|MaxTorque)。
  • 设置回复稳定系数(CorrectionFactor),取值为[0,+),为0时禁用回复,系数越小回复后稳定得越快,系数越大回复时会发生反复地抖动。

  8.制作活塞

  活塞是以一个刚体为支点线性推动另一个刚体的装置。

  • 通过左下角按钮打开关节面板,选择Prismatic。
  • 设置关节的名称(Name)。
  • 设置连接的刚体之间是否会碰撞(Collision)。
  • 选择要连接的刚体(BodyA|BodyB),活塞的支撑刚体要设置为BodyA,活塞的推动刚体要设置为BodyB。
  • 设置活塞运动的支撑点(WorldPos)。
  • 设置活塞的推进方向(Axis),通过旋转设置用的方向轴到要推进的角度。
  • 设置活塞推动的刚体在推进方向上相对于支撑刚体的最小距离和最大距离(Lower|Upper),当最大距离小于最小距离时距离限制无效。
  • 设置活塞的推动力量和推进速度(MaxMotorForce|MaxMotorSpeed)。

  9.制作传动装置

  传动装置可以将任两个转动关节、活塞,或是一个转动关节和一个活塞的运动关联起来。

  • 通过左下角按钮打开关节面板,选择Gear。
  • 设置关节的名称(Name)
  • 设置被关联到一起的刚体之间是否会碰撞(Collision)。
  • 选择要关联的运动关节(JointA|JointB),关节的选择在右上区域的选择面板中完成。只能选择转动关节或是活塞。
  • 设置传动比(Ratio)。

  10.制作转动关节

  转动关节用于将一个刚体固定在另一个刚体上,并绕着一个指定的中心旋转。可以用来制作轮子或是轮轴。

  • 通过左下角按钮打开关节面板,选择Revolute。
  • 设置关节的名称(Name)。
  • 设置连接的刚体之间是否会碰撞(Collision)。
  • 选择要连接的刚体(BodyA|BodyB),刚体的选择通过在编辑区域直接点选。
  • 设置旋转中心(WorldPos),可以通过双击快速移动旋转中心。
  • 设置最大旋转角和最小旋转角(UpperAngle|LowerAngle),都设置为0时,刚体的旋转角度不受限制。
  • 设置转动力矩和转动速度(MaxMotorTorque|MotorSpeed)。

  11.制作轮子

  轮子是转动关节的升级版,除了绕着旋转轴旋转以外,还提供在一个方向轴上的弹性缓冲。

  • 通过左下角按钮打开关节面板,选择Wheel。
  • 设置关节的名称(Name)。
  • 设置连接的刚体之间是否会碰撞(Collision)。
  • 选择要连接的刚体(BodyA|BodyB),要用作轮子的刚体应选为BodyA,作为轮子的固定目标的刚体选为BodyB。
  • 设置轮子的轴心点(WorldPos),可以通过双击快速移动轮轴中心。
  • 设置缓冲弹簧的伸缩方向(Axis),通过旋转设置用的方向轴来改变弹簧角度。
  • 设置轮子的转动力矩和转动速度(MaxMotorTorque|MotorSpeed)。
  • 设置Frequency和Dumping属性,用于调节缓冲弹簧的弹性。Frequency的数值越大弹性越差;Dumping属性取值范围为[0,1],当为0时受到外力会持续地进行反弹,不容易恢复静止,当为1时受力反弹后会很快恢复静止。

  12.制作焊接关节

  焊接关节用于将两个刚体绑到一起,可以是硬性的连接,也可以是有弹性的连接。

  • 通过左下角按钮打开关节面板,选择Weld。
  • 设置关节的名称(Name)。
  • 设置连接的刚体之间是否会碰撞(Collision)。
  • 选择要连接的刚体(BodyA|BodyB),刚体的选择通过在编辑区域直接点选。
  • 设置刚体连接的中心点(WorldPos),可以通过双击快速移动。
  • 设置Frequency和Dumping属性,用于调节刚体之间连接的弹性。Frequency的数值越大弹性越差;Dumping属性取值范围为[0,1],当为0时受到外力会持续地进行反弹,不容易恢复静止,当为1时受力反弹后会很快恢复静止。

  13.制作绳索关节

  绳索关节有点像距离关节,连接两个刚体并限制它们之间的最大距离,在这个最大距离之内刚体可以自由运动。

  • 通过左下角按钮打开关节面板,选择Rope。
  • 设置关节的名称(Name)。
  • 设置连接的刚体之间是否会碰撞(Collision)。
  • 设置绳子两端各自在刚体上连接点的位置(AnchorA|AnchorB)。
  • 设置绳子的长度(MaxLength)。
标题目录