简体   繁体   English

在iOS 9中设置UIView的碰撞边界路径

[英]Setting collision bounding path of a UIView in iOS 9

In iOS 9 Apple introduced the collisionBoundsType to UIKit-Dynamics . 在iOS 9中,Apple将collisionBoundsType引入了UIKit-Dynamics

I have no issue when setting this UIDynamicItemCollisionBoundsTypeRectangle or when I set this to UIDynamicItemCollisionBoundsTypeEllipse . 设置此UIDynamicItemCollisionBoundsTypeRectangle或将其设置为UIDynamicItemCollisionBoundsTypeEllipse时,我没有任何问题。

The screenshot below is from a game I am making where the collisionBoundsType of the player is set to rectangle and the ball is set to ellipse: 下面的截图来自我正在制作的游戏,其中玩家的collisionBoundsType设置为矩形,并且球被设置为椭圆:

在此输入图像描述

However, when I set the player's collisionBoundsType to path I get weird behavior as seen here: 但是,当我将玩家的collisionBoundsType设置为路径时,我会看到奇怪的行为,如下所示:

在此输入图像描述

The view appears higher than it should and the collision body is to the right of where it should be. 视图看起来比它应该高,碰撞体位于它应该的位置。

Currently I have collisionBoundingPath set to this: 目前我将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;
}

Additionally, my drawRect function looks like this: 另外,我的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];
}

Why is this happening? 为什么会这样? How do I set the path of the collision body to be the same as the drawing in the view? 如何将碰撞体的路径设置为与视图中的图形相同?

Additionally, the red is just the background of the view (ie view.backgroundColor = [UIColor redColor]; ). 另外,红色只是视图的背景(即view.backgroundColor = [UIColor redColor]; )。

From the documentation on the UIDynamicItem here , the following statement about the coordinate system for paths seems to represent what is wrong: 这里的UIDynamicItem文档中,以下关于路径坐标系的声明似乎代表了错误:

The path object you create must represent a convex polygon with counter-clockwise or clockwise winding, and the path must not intersect itself. 您创建的路径对象必须表示逆时针或顺时针缠绕的凸多边形,并且路径不得与自身相交。 The (0, 0) point of the path must be located at the center point of the corresponding dynamic item. 路径的(0,0)点必须位于相应动态项的中心点。 If the center point does not match the path's origin, collision behaviors may not work as expected. 如果中心点与路径的原点不匹配,则碰撞行为可能无法按预期工作。

Here it states that the (0,0) for the path MUST be the center point. 这里说明路径的(0,0)必须是中心点。

I would think that the center of your arc path should be (0,0) and not (SLIME_SIZE/2,SLIME_SIZE/2) . 我认为弧形路径的中心应该是(0,0)而不是(SLIME_SIZE/2,SLIME_SIZE/2) Have you perhaps set the width and height of the UIView frame to SLIME_SIZE rather than SLIME_SIZE*2 ? 您是否可以将UIView帧的宽度和高度设置为SLIME_SIZE而不是SLIME_SIZE*2

SLIME_SIZE really seems to define the radius, so the frame width should be SLIME_SIZE*2 . SLIME_SIZE似乎确实定义了半径,因此帧宽应为SLIME_SIZE*2 If it is set as SLIME_SIZE , then that would explain why you need to translate by SLIME_SIZE/2 as a correction. 如果将其设置为SLIME_SIZE ,则可以解释为什么需要将SLIME_SIZE/2为校正。

I was able to answer this by changing: 我能够通过改变来回答这个问题:

- (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;
}

to: 至:

- (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;
}

The key difference is that I modified the center of the arc by dividing the x and y values by 2. 关键的区别在于我通过将x和y值除以2来修改弧的中心。

Debugging physics is a thing. 调试物理是一件事。 It's probably not something that iOS users have tended to think a lot about as they've generally done very simple things with UIKit Dynamics. 这可能不是iOS用户倾向于想的很多,因为他们通常使用UIKit Dynamics做了非常简单的事情。 This is a bit of a shame, as it's one of the best aspects of the recent editions of iOS, and offers a truly fun way to make compelling user experiences. 这有点令人遗憾,因为它是最近版本iOS的最佳方面之一,并提供了一种真正有趣的方式来提供引人注目的用户体验。

So... how to debug physics? 那么...如何调试物理?

One way is to mentally imagine what's going on, and then correlate that with what's going on, and find the dissonance between the imagined and the real, and then problem solve via a blend of processes of elimination, mental or real trial & error and deduction, until the problem is determined and solved. 一种方法是在心理上想象正在发生的事情,然后将其与发生的事情联系起来,找到想象与真实之间的不和谐,然后通过消除,精神或真实的试验和错误以及演绎过程的混合来解决问题,直到问题得到确定和解决。

Another is to have a visual depiction of all that's created and interacting presenting sufficient feedback to more rapidly determine the nature and extents of elements, their relationships and incidents/events, and resolve issues with literal sight. 另一种方法是对所有创建和交互的视觉描述提供足够的反馈,以更快地确定元素的性质和范围,它们的关系和事件/事件,并用字面视觉解决问题。

To this end, various visual debuggers and builders of physics simulations have been created since their introduction. 为此,自引入以来,已经创建了各种视觉调试器和物理模拟的构建器。

Unfortunately iOS does not have such a screen based editor or "scene editor" for UIKit Dynamics, and what is available for this sort of visual debugging in Sprite Kit and Scene Kit is rudimentary, at best. 不幸的是,iOS没有为UIKit Dynamics提供这样的基于屏幕的编辑器或“场景编辑器”,并且Sprite Kit和Scene Kit中可用于此类可视化调试的内容至多是基本的。

However there's CALayers, which are present in all UIKit Views, into which CAShapeLayers can be manually created and drawn to accurately represent any and all physical elements, their bounds and their anchors and relationships. 然而,所有UIKit视图中都存在CALayers,可以手动创建和绘制CAShapeLayers,以准确地表示任何和所有物理元素,它们的边界以及它们的锚点和关系。

CAShapeLayers are a "container" for CGPaths, and can have different colours for outline and fill, and more than one CGPath element within a single CAShapeLayer. CAShapeLayers是CGPaths的“容器”,可以在轮廓和填充中使用不同的颜色,在单个CAShapeLayer中可以有多个CGPath元素。

And, to quote the great Rob: 而且,引用伟大的罗布:

"If you add a CAShapeLayer as a layer to a view, you don't have to implement any drawing code yourself. Just add the CAShapeLayer and you're done. You can even later change the path, for example, and it will automatically redraw it for you. CAShapeLayer gets you out of the weeds of writing your own drawRect or drawLayer routines." “如果将一个CAShapeLayer作为图层添加到视图中,则不必自己实现任何绘图代码。只需添加CAShapeLayer即可完成。例如,您甚至可以更改路径,它会自动生成为你重新绘制它.CAShapeLayer让你摆脱编写自己的drawRect或drawLayer例程的杂草。“

If you have an enormous number of interacting elements and want to debug them, CAShapeLayer's performance issues might come into play, at which point you can use shouldRasterize to convert each to a bitmap, and get a significant performance improvement when hitting limits created by the "dynamic" capabilities of CAShapeLayers. 如果您有大量的交互元素并且想要调试它们,那么CAShapeLayer的性能问题可能会发挥作用,此时您可以使用shouldRasterize将每个元素转换为位图,并在达到“由”创建的限制时获得显着的性能提升。 CAShapeLayers的动态“功能。

Further, for representing things like constraints and joints, there's a simple process of created dashed lines on CAShapeLayers, by simply setting properties. 此外,为了表示约束和关节之类的东西,只需设置属性,就可以在CAShapeLayers上创建一个简单的虚线过程。 Here's the basics of setting up a CAShapeLayer's properties, and the way to use an array to create a 5-5-5 dashed outline with a block stroke, width of 3, no fill. 以下是设置CAShapeLayer属性的基础知识,以及使用数组创建具有块笔划,宽度为3,无填充的5-5-5虚线轮廓的方法。

CAShapeLayer *shapeLayer = [CAShapeLayer layer];
[shapeLayer setBounds:self.bounds];
[shapeLayer setPosition:self.center];
[shapeLayer setFillColor:[[UIColor clearColor] CGColor]];
[shapeLayer setStrokeColor:[[UIColor blackColor] CGColor]];
[shapeLayer setLineWidth:3.0f];
[shapeLayer setLineJoin:kCALineJoinRound];
[shapeLayer setLineDashPattern:
 [NSArray arrayWithObjects:[NSNumber numberWithInt:10],
  [NSNumber numberWithInt:5],nil]];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM