Box2DFlash如何给一个刚体的皮肤图片定位?

来源:互联网 发布:淘宝有什么好的女装店铺 编辑:程序博客网 时间:2024/04/30 15:14

Box2DFlash如何给一个矩形刚体的皮肤图片定位?

标签(空格分隔): Box2D


问题描述

这是一个Box2DFlash实际的应用问题,也是一道非常基本的几何问题。
实际的应用场景是:对于以中心点确定坐标的刚体,在每次刷新显示的时候,如何给它的皮肤定位,因为我们知道在Flash的体系中,图片都是以左上角为基准确定其在父容器的位置的。
在找到的Box2DFlash的例子中,刚体的皮肤采用了MovieClip制作,其对齐点位置可以在Flash CS编辑器环境中设置,所以不存在这个问题。
看来只能进行计算了。

解决思路

这是一个计算向量旋转后坐标的问题,已知向量的初始坐标(刚体左上角的坐标)、旋转点(刚体中心点)的坐标和旋转角度,求旋转后的向量坐标。按照向量旋转的公式计算即可。再把坐标偏移和单位转换加上就应该能得到结果了。

干扰因素

Box2D中坐标和实际像素坐标的转换

我们知道Box2D中的世界都是以公制单位计算的,而Flash的世界只有像素,所以我们会设置一个对应比例,本例中采用常量“PHYS_SCALE”存储。Box2D之外的数值在进入Box2D之前都要经过这个常量计算,Box2D中的数值在应用在其外的世界中也要用到这个常量。应该避免频繁使用它,因为会影响性能而且影响精度。

角度设置的方向性

皮肤(显示对象)和刚体的角度设置,都是正对应顺时针,负对应逆时针,最开始没有意识到。

皮肤图片尺寸的获取

刷新过程中通过刚体的GetUserData方法,获得到显示对象。但是如果有旋转,获取的width和height都不对。后来直接将这两个值存在userData中,为了后续计算方便存储前已经处理为了Box2D中的单位。

旋转方向和计算公式之间的关系

顺时针旋转和逆时针旋转的坐标计算公式还不同。

困扰

干扰因素并不是以下都解决的而是在解决过程中逐步发现,逐步解决的。所以经过了很长时间尝试,甚至对解决思路产生了怀疑。

最终解决方式

// 得到用户数据中的显示对象var dis:DisplayObject=body.GetUserData().asset as DisplayObject;// 计算图片左上角在旋转后的坐标,然后根据这个坐标计算图片左上角应的位置var leftTopPoint:b2Vec2=new b2Vec2(0,0);// 这里的width和height值是事先存储在userData中的(已经处理为了Box2D世界的单位)var disHW:Number=-body.GetUserData().width;var disHH:Number=-body.GetUserData().height;leftTopPoint.Set(disHW,disHH);// 弧度对2派取余后数值介于(-*Math.PI,Math.PI)var angle:Number=body.GetAngle()%(Math.PI*2);//刚体内部坐标转换为Box2D世界坐标var posPoint:b2Vec2=body.GetWorldPoint(leftTopPoint);//设置显示对象的旋转角度dis.x = posPoint.x* PHYS_SCALE;dis.y = posPoint.y* PHYS_SCALE;dis.rotation = angle * 180 / Math.PI;

说明

看过最终解决方式后是不是有种被欺骗的感觉,前面说的那些干扰因素有什么用呢?
回头再思考问题解决的整个过程,研究和理解那些内容是非常有助于理解Box2D原理的,因为没有看过C++版本Box2D,而Box2DFlash的文档过于简略,以至于有些内容不甚理解。
对于这个应用场景,设计者已经考虑而且实现了,拿来直接用就可以了。领悟到这点得益于不断的尝试和对Box2DFlash源码的阅读。
上面的代码中最核心的内容是leftTopPoint坐标的设置和刚体的GetWorldPoint方法应用。
leftTopPoint是刚体没有旋转时左上角点坐标,这里直接通过存储在用户数据中的显示内容宽高设置,确切的说是原始宽高的一半转换为Box2D世界的单位后的值。
刚体的GetWorldPoint方法是把刚体上的一个点转换为Box2D世界中点坐标,参数值是刚体不旋转点时候相对于刚体对齐点坐标的偏移。本例中左上角相对于矩形刚体中心点的坐标偏移就是leftTopPoint坐标所表示。

0 0