在iOS 9

时间:2015-10-14 04:32:18

标签: ios objective-c uikit-dynamics tvos uicollisionbehavior

在iOS 9中,Apple将collisionBoundsType引入UIKit-Dynamics

设置此UIDynamicItemCollisionBoundsTypeRectangle或将其设置为UIDynamicItemCollisionBoundsTypeEllipse时,我没有任何问题。

下面的截图来自我正在制作的游戏,其中玩家的collisionBoundsType设置为矩形,并且球被设置为椭圆:

enter image description here

然而,当我将玩家的collisionBoundsType设置为路径时,我会看到奇怪的行为:

enter image description here

视图看起来比它应该高,碰撞体位于它应该的位置右侧。

目前我已将collisionBoundingPath设置为:

- (UIBezierPath *)collisionBoundingPath
{
    maskPath = [[UIBezierPath alloc] init];
    [maskPath addArcWithCenter:CGPointMake(SLIME_SIZE, SLIME_SIZE) radius:SLIME_SIZE startAngle:0*M_PI endAngle:M_PI clockwise:NO];
    return maskPath;
}

此外,我的drawRect函数如下所示:

- (void) drawRect:(CGRect)rect
{
    if (!_color){
    [self returnDefualtColor];
    }
    if (!maskPath) maskPath = [[UIBezierPath alloc] init];
    [maskPath addArcWithCenter:CGPointMake(SLIME_SIZE, SLIME_SIZE) radius:SLIME_SIZE startAngle:0*M_PI endAngle:M_PI clockwise:NO];
    [_color setFill];
    [maskPath fill];
}

为什么会这样?如何将碰撞体的路径设置为与视图中的图形相同?

此外,红色只是视图的背景(即view.backgroundColor = [UIColor redColor];)。

3 个答案:

答案 0 :(得分:2)

从UIDynamicItem here的文档中,以下关于路径坐标系的陈述似乎代表了错误:

  

您创建的路径对象必须表示凸多边形   逆时针或顺时针缠绕,路径不得   相交自己。路径的(0,0)点必须位于   相应动态项的中心点。如果中心点   与路径的原点不匹配,碰撞行为可能无效   预期

这里说明路径的(0,0)必须是中心点。

我认为弧形路径的中心应该是(0,0)而不是(SLIME_SIZE/2,SLIME_SIZE/2)。您是否可以将UIView帧的宽度和高度设置为SLIME_SIZE而不是SLIME_SIZE*2

SLIME_SIZE似乎确实定义了半径,因此框架宽度应为SLIME_SIZE*2。如果将其设置为SLIME_SIZE,则可以解释为什么需要按SLIME_SIZE/2进行翻译作为更正。

答案 1 :(得分:1)

我能够通过改变来回答这个问题:

- (UIBezierPath *)collisionBoundingPath
{
    maskPath = [[UIBezierPath alloc] init];
    [maskPath addArcWithCenter:CGPointMake(SLIME_SIZE, SLIME_SIZE) radius:SLIME_SIZE startAngle:0*M_PI endAngle:M_PI clockwise:NO];
    return maskPath;
}

为:

- (UIBezierPath *)collisionBoundingPath
{
    maskPath = [[UIBezierPath alloc] init];
    [maskPath addArcWithCenter:CGPointMake(SLIME_SIZE / 2, SLIME_SIZE / 2) radius:SLIME_SIZE startAngle:0*M_PI endAngle:M_PI clockwise:NO];
    return maskPath;
}

关键的区别在于我通过将x和y值除以2来修改弧的中心。

答案 2 :(得分:1)

调试物理是一件事。它可能不是iOS用户倾向于认真思考的东西,因为他们通常使用UIKit Dynamics做了非常简单的事情。这有点令人遗憾,因为它是最近版本iOS的最佳方面之一,并提供了一种真正有趣的方式来提供引人注目的用户体验。

那么...如何调试物理?

一种方法是在心理上想象发生了什么,然后将其与正在发生的事情联系起来,找到想象与真实之间的不一致,然后通过混合过程解决问题消除,精神或真实的审判&错误和演绎,直到问题得到确定和解决。

另一种方法是对所有创建和交互的内容进行视觉描述,提供足够的反馈,以更快速地确定元素的性质和范围,它们之间的关系和事件/事件,并通过字面视觉解决问题。

为此,自引入以来,已经创建了各种视觉调试器和物理模拟的构建器。

不幸的是,iOS没有这样的基于屏幕的编辑器或场景编辑器"对于UIKit Dynamics而言,Sprite Kit和Scene Kit中可用于此类可视化调试的内容至多是基本的。

然而,所有UIKit视图中都存在CALayers,可以手动创建和绘制CAShapeLayers,以准确地表示任何和所有物理元素,它们的边界以及它们的锚点和关系。

CAShapeLayers是一个"容器"对于CGPath,可以在轮廓和填充中使用不同的颜色,在单个CAShapeLayer中可以有多个CGPath元素。

而且,引用伟大的罗布:

  

"如果您将CAShapeLayer作为图层添加到视图中,则不必   自己实现任何绘图代码。只需添加CAShapeLayer即可   你完成了。您甚至可以稍后更改路径,例如,它   会自动为你重绘它。 CAShapeLayer让你走出困境   编写自己的drawRect或drawLayer例程的杂草。"

如果您有大量的交互元素并想要调试它们,CAShapeLayer的性能问题可能会发挥作用,此时您可以使用shouldRasterize将每个元素转换为位图,并获得显着的性能提升当击中由"动态"创造的限制时CAShapeLayers的功能。

此外,为了表示约束和关节之类的东西,只需设置属性,就可以在CAShapeLayers上创建虚线的简单过程。以下是设置CAShapeLayer属性的基础知识,以及使用数组创建5-5-5虚线轮廓的方法,其中包含块笔划,宽度为3,无填充。

ALTER PROCEDURE [dbo].[sp_cbqueue_pickup_some]
as
select languagesrc,countrysrc,operatorsrc from cbqueue