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