[]分享:intersects为何碰撞不准?碰撞框rectangle的坐标你设置对了吗?
首先谈下我选择intersects + rectangle + setBounds碰撞的原因:碰撞时虽然图片和骨骼可以通过getBounds获得碰撞框,但按官方API的说法,很耗性能,特别是每帧都要检测大量碰撞且图片的大小位置会随时变化的时候。
rectangle可以通过setTo改变其大小,而图片和骨骼又可以通过setBounds(rectangle)给予一个碰撞框,setBounds后相当于覆盖了图片原有的碰撞框,当再调用getBounds时,会直接读取先前setBounds赋予的值,而不再重新计算,这点在http://ask.layabox.com/question/1397
已得到证实。
setBounds后相对于给图片内部添加了一个rectangle子对象,所以当图片的位置发生变化时,碰撞框是会跟着走的(这里只讨论矩形的模糊碰撞,所以旋转我没有进行测试)
那么问题的关键就在于我setBounds后这个rectangle能不能和图片或骨骼正好对齐,使得其碰撞不产生偏移?看下面的例子:
首先我们先假定下图(图1)是一个image图片 sp1 被添加到舞台,辅助线为坐标轴,图片大小为172*172:
为了定位准确以及换其他skin的时候也能保持中心点不变,我们改变注册点到图片正中心,如下图(图2)
sp1.pivotX=sp1.width>>1;
sp1.pivotY=sp1.height>>1;
然后我
rectangle1 = new Rectangle(0, 0, 172, 172); (前两个代表矩形框的坐标,后面是大小)
因为rectangle无法改变注册点,理论上如果它是一个可以看见的框,注册点应该默认在左上角,那么应该是图1的位置,这和之前的圆就对不上了,所以我主动给他加一个偏移,这个偏移的值应该是图片的一半(因为之前图片的注册点设置到正中心了),这样才能和sp1刚好对齐,达到图2的状态,如下面的公式
rectangle1 = new Rectangle(-86, -86, 172, 172); (-(图片长的一半),-(宽的一半),图片长,图片宽)
sp1.setBounds(rectangle1);
因为我之前spine骨骼动画就是这么做的,毫无问题。我心里想着这方法真不错,以后我这个圆就算触发某种条件变到400*300的椭圆,我只要rectangle1.setTo(-200,-150,400,300);再sp1.setBounds(rectangle1);就完成了碰撞框的更新,完美!事实上骨骼也确实可以这么做。
然而人们往往看到的都是表面现象,测试下来,rectangle1 = new Rectangle(0, 0, 172, 172);反而才能圆对齐,这就很奇怪,同样的方法用在图片和骨骼上有如此差异,这个框的坐标究竟应该如何设置?
当我试着把碰撞框调大rectangle1 = new Rectangle(0, 0, 200, 200);后我发现,实际碰撞如下图
我似乎明白了其中的玄机,setBounds后这个Rectangle(0, 0, 长, 宽); 顶点实际上并不是和图片的现有注册点对齐,而是和图片初始注册点(左上角)对齐,如果你想要碰撞框和图片正好一样大,那框的坐标设置(0,0)肯定没问题,但如果碰撞框和图片大小本身不一样该如何设置呢?把(0,0)设置成还需要补足的距离就行,以目前新注册点是中心点为例,rectangle1 = new Rectangle(-(框长的一半减去图片长的一半), -(框宽的一半减去图片宽的一半), 框长, 框宽),也就是rectangle1 = new Rectangle(-(100-86),-(100-86),200,200);就可以了。
那为什么骨骼不需要减去重设注册点的偏移呢,其实是要的,只不过这个偏移是0而已,这点和layaBox实现的原理有关,在spine如果我设置这么一个动画
加载到程序里,它的初始注册点就是两条黑线的交点,而setBounds后,rectangle1左上角和注册点对齐,所以只要偏移骨骼长宽的一半就好了。因为骨骼注册点没有变,补足偏移是0,所以造成了不需要偏移,只需要设置框的坐标为负的骨骼长宽一半的假象。
结论:setBounds使rectangle的坐标(左上角)和对象的初始注册点对齐(图片为左上角,骨骼为原生软件里的原点),至于要如何设置rectangle才能将图片和骨骼框的刚刚好,得看图片和骨骼的注册点改变了多少,跟着设置补足偏移量就行,
该原理同样适用hitArea
rectangle可以通过setTo改变其大小,而图片和骨骼又可以通过setBounds(rectangle)给予一个碰撞框,setBounds后相当于覆盖了图片原有的碰撞框,当再调用getBounds时,会直接读取先前setBounds赋予的值,而不再重新计算,这点在http://ask.layabox.com/question/1397
已得到证实。
setBounds后相对于给图片内部添加了一个rectangle子对象,所以当图片的位置发生变化时,碰撞框是会跟着走的(这里只讨论矩形的模糊碰撞,所以旋转我没有进行测试)
那么问题的关键就在于我setBounds后这个rectangle能不能和图片或骨骼正好对齐,使得其碰撞不产生偏移?看下面的例子:
首先我们先假定下图(图1)是一个image图片 sp1 被添加到舞台,辅助线为坐标轴,图片大小为172*172:
为了定位准确以及换其他skin的时候也能保持中心点不变,我们改变注册点到图片正中心,如下图(图2)
sp1.pivotX=sp1.width>>1;
sp1.pivotY=sp1.height>>1;
然后我
rectangle1 = new Rectangle(0, 0, 172, 172); (前两个代表矩形框的坐标,后面是大小)
因为rectangle无法改变注册点,理论上如果它是一个可以看见的框,注册点应该默认在左上角,那么应该是图1的位置,这和之前的圆就对不上了,所以我主动给他加一个偏移,这个偏移的值应该是图片的一半(因为之前图片的注册点设置到正中心了),这样才能和sp1刚好对齐,达到图2的状态,如下面的公式
rectangle1 = new Rectangle(-86, -86, 172, 172); (-(图片长的一半),-(宽的一半),图片长,图片宽)
sp1.setBounds(rectangle1);
因为我之前spine骨骼动画就是这么做的,毫无问题。我心里想着这方法真不错,以后我这个圆就算触发某种条件变到400*300的椭圆,我只要rectangle1.setTo(-200,-150,400,300);再sp1.setBounds(rectangle1);就完成了碰撞框的更新,完美!事实上骨骼也确实可以这么做。
然而人们往往看到的都是表面现象,测试下来,rectangle1 = new Rectangle(0, 0, 172, 172);反而才能圆对齐,这就很奇怪,同样的方法用在图片和骨骼上有如此差异,这个框的坐标究竟应该如何设置?
当我试着把碰撞框调大rectangle1 = new Rectangle(0, 0, 200, 200);后我发现,实际碰撞如下图
我似乎明白了其中的玄机,setBounds后这个Rectangle(0, 0, 长, 宽); 顶点实际上并不是和图片的现有注册点对齐,而是和图片初始注册点(左上角)对齐,如果你想要碰撞框和图片正好一样大,那框的坐标设置(0,0)肯定没问题,但如果碰撞框和图片大小本身不一样该如何设置呢?把(0,0)设置成还需要补足的距离就行,以目前新注册点是中心点为例,rectangle1 = new Rectangle(-(框长的一半减去图片长的一半), -(框宽的一半减去图片宽的一半), 框长, 框宽),也就是rectangle1 = new Rectangle(-(100-86),-(100-86),200,200);就可以了。
那为什么骨骼不需要减去重设注册点的偏移呢,其实是要的,只不过这个偏移是0而已,这点和layaBox实现的原理有关,在spine如果我设置这么一个动画
加载到程序里,它的初始注册点就是两条黑线的交点,而setBounds后,rectangle1左上角和注册点对齐,所以只要偏移骨骼长宽的一半就好了。因为骨骼注册点没有变,补足偏移是0,所以造成了不需要偏移,只需要设置框的坐标为负的骨骼长宽一半的假象。
结论:setBounds使rectangle的坐标(左上角)和对象的初始注册点对齐(图片为左上角,骨骼为原生软件里的原点),至于要如何设置rectangle才能将图片和骨骼框的刚刚好,得看图片和骨骼的注册点改变了多少,跟着设置补足偏移量就行,
该原理同样适用hitArea
没有找到相关结果
已邀请:
要回复问题请先登录
1 个回复
layabox
赞同来自: