Как сделать так, чтобы круговой обзор сталкивался с веслом

Всякий раз, когда круговое представление сталкивается с веслом на раскадровке, оно фактически сталкивается с прямоугольной рамкой представления. Как мне решить эту проблему. Я также пытался UIBezierPath, CAShapeLayer и это не похоже на работу.

Красная стрелка - это точка столкновения, так как она, кажется, не сталкивается с мячом, а сталкивается с рамкой вида. однажды рама касается лопасти, которая отскакивает назад и так далее.

снимок экрана

2 ответа

Решение

Если вы используете UIDynamicAnimatorВы можете определить collisionBoundsType и collisionBoundingPath для предметов, которые будут сталкиваться, например:

@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, он будет учитывать границы столкновения, которые вы определили для элементов. Например:

анимация столкновений


Вышеприведенное иллюстрирует скользящий удар, как на вашем исходном изображении. Если вы хотите, чтобы он подпрыгивал, даже если он касается края лопасти, вы можете указать 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)
}

Это дает что-то вроде:

введите описание изображения здесь

Очевидно, вам придется немного поиграться с этим, чтобы получить желаемый эффект, но он иллюстрирует основную идею обнаружения столкновения и добавления линейной скорости к шару, соответственно.

Еще более простым ответом, чем принятый ответ, было бы установить границы эллиптическими вместо определенного пути:

 override public var collisionBoundsType: UIDynamicItemCollisionBoundsType {
        return .Elliptical
 }
Другие вопросы по тегам