How do i make a circular view collide with the paddle

本小妞迷上赌 提交于 2019-12-23 13:09:10

问题


Whenever the circular view collides with the paddle on storyboard, it actually collides with the rectangular frame of the view. How do I resolve this issue. I have also tried UIBezierPath, CAShapeLayer and it doesn't seem to be working.

The red arrow is the colliding point, As it does not seem to be colliding with ball instead it collides with the frame of the view. once, the frame is touched with the paddle it bounces back and so on.


回答1:


If you're using UIDynamicAnimator, you can define the collisionBoundsType and the collisionBoundingPath for the items that will be colliding, for example:

@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
    }
}

If you do this, and then add these items to your UICollisionBehavior, it will respect the collision boundaries you defined for the items. For example:


The above illustrates a glancing blow, like in your original image. If you want it to bounce up even if it hits the edge of the paddle, you can specify the collisionDelegate for the UICollisionBehavior and give it a new direction:

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

And conform to UICollisionBehaviorDelegate and then implement 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)
}

That yields something like:

Clearly, you'll have to play around with this quite a bit to get the desired effect, but it illustrates the basic idea of detecting a collision and adding a linear velocity to the ball, accordingly.




回答2:


An even simpler answer than the accepted answer would be to set the bounds to be elliptical instead of a defined path:

 override public var collisionBoundsType: UIDynamicItemCollisionBoundsType {
        return .Elliptical
 }


来源:https://stackoverflow.com/questions/36110371/how-do-i-make-a-circular-view-collide-with-the-paddle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!