如何使圆形视图与桨碰撞

时间:2016-03-20 04:55:08

标签: ios swift uiview storyboard uikit-dynamics

每当圆形视图与故事板上的球拍碰撞时,它实际上会与视图的矩形框架发生碰撞。我该如何解决这个问题。我也尝试了UIBezierPathCAShapeLayer,但它似乎没有用。

红色箭头是碰撞点,因为它似乎没有与球碰撞,而是与视图的框架碰撞。一次,用桨板触摸框架,它会反弹,等等。

screen snapshot

2 个答案:

答案 0 :(得分:5)

如果您使用UIDynamicAnimator,则可以为要碰撞的项目定义collisionBoundsTypecollisionBoundingPath,例如:

@IBDesignable public class BallView : UIView {

    @IBInspectable public var fillColor: UIColor = UIColor.blackColor() {
        didSet { setNeedsLayout() }
    }

    override public var collisionBoundsType: UIDynamicItemCollisionBoundsType {
        return .Path
    }

    override public var collisionBoundingPath: UIBezierPath {
        let radius = min(bounds.size.width, bounds.size.height) / 2.0

        return UIBezierPath(arcCenter: CGPointZero, radius: radius, startAngle: 0, endAngle: CGFloat(M_PI * 2.0), clockwise: true)
    }

    private var shapeLayer: CAShapeLayer!

    public override func layoutSubviews() {
        if shapeLayer == nil {
            shapeLayer = CAShapeLayer()
            shapeLayer.strokeColor = UIColor.clearColor().CGColor
            layer.addSublayer(shapeLayer)
        }

        let radius = min(bounds.size.width, bounds.size.height) / 2.0

        shapeLayer.fillColor = fillColor.CGColor
        shapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: bounds.size.width / 2.0, y: bounds.size.height / 2.0), radius: radius, startAngle: 0, endAngle: CGFloat(M_PI * 2.0), clockwise: true).CGPath
    }
}

@IBDesignable public class PaddleView : UIView {

    @IBInspectable public var cornerRadius: CGFloat = 5 {
        didSet { setNeedsLayout() }
    }

    @IBInspectable public var fillColor: UIColor = UIColor.blackColor() {
        didSet { setNeedsLayout() }
    }

    override public var collisionBoundsType: UIDynamicItemCollisionBoundsType {
        return .Path
    }

    override public var collisionBoundingPath: UIBezierPath {
        return UIBezierPath(roundedRect: CGRect(x: -bounds.size.width / 2.0, y: -bounds.size.height / 2.0, width: bounds.width, height: bounds.height), cornerRadius: cornerRadius)
    }

    private var shapeLayer: CAShapeLayer!

    public override func layoutSubviews() {
        if shapeLayer == nil {
            shapeLayer = CAShapeLayer()
            shapeLayer.strokeColor = UIColor.clearColor().CGColor
            layer.addSublayer(shapeLayer)
        }

        shapeLayer.fillColor = fillColor.CGColor
        shapeLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height), cornerRadius: cornerRadius).CGPath
    }
}

如果您执行此操作,然后将这些项目添加到UICollisionBehavior,则会尊重您为项目定义的碰撞边界。例如:

collision animation

上面说明了一个瞥见的打击,就像你的原始图像一样。如果您希望它在碰到划水板边缘时反弹,您可以为collisionDelegate指定UICollisionBehavior并为其指定新方向:

let collision = UICollisionBehavior(items: [paddleView, ballView])
collision.translatesReferenceBoundsIntoBoundary = true
collision.collisionDelegate = self
self.animator.addBehavior(collision)

并符合UICollisionBehaviorDelegate,然后实施collisionBehavior(beganContactForItem:withItem:atPoint:)

func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item1: UIDynamicItem, withItem item2: UIDynamicItem, atPoint p: CGPoint) {
    let postCollisionDirection = UIDynamicItemBehavior(items: [ballView])
    postCollisionDirection.addLinearVelocity(CGPoint(x: ballView.center.x - paddleView.center.x, y: -200), forItem: ballView)
    animator.addBehavior(postCollisionDirection)
}

产生类似的东西:

enter image description here

很明显,你必须要花很多时间才能获得理想的效果,但它说明了检测碰撞并为球增加线速度的基本思路。

答案 1 :(得分:1)

比接受的答案更简单的答案是将边界设置为椭圆形而不是定义的路径:

{{1}}