Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting collision bounding path of a UIView in iOS 9

In iOS 9 Apple introduced the collisionBoundsType to UIKit-Dynamics.

I have no issue when setting this UIDynamicItemCollisionBoundsTypeRectangle or when I set this to 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:

enter image description here

However, when I set the player's collisionBoundsType to path I get weird behavior as seen here:

enter image description here

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:

- (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:

- (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 (i.e. view.backgroundColor = [UIColor redColor];).

like image 659
Wyetro Avatar asked Oct 14 '15 04:10

Wyetro


Video Answer


2 Answers

From the documentation on the UIDynamicItem here, the following statement about the coordinate system for paths seems to represent what is wrong:

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. 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.

I would think that the center of your arc path should be (0,0) and not (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?

SLIME_SIZE really seems to define the radius, so the frame width should be 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.

like image 90
Rory McKinnel Avatar answered Oct 18 '22 03:10

Rory McKinnel


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.

like image 1
Wyetro Avatar answered Oct 18 '22 03:10

Wyetro