我如何使圆形视图与桨碰撞
How do i make a circular view collide with the paddle
每当圆形视图与故事板上的桨碰撞时,它实际上与视图的矩形框架发生碰撞。我该如何解决这个问题。我也试过 UIBezierPath
、CAShapeLayer
,但似乎没有用。
红色箭头是碰撞点,因为它似乎不是与球碰撞而是与视图的框架碰撞。一次,框架被球拍碰到它弹回来等等。
如果您使用 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
,它将遵守您为项目定义的碰撞边界。例如:
上面说明了一个斜视,就像在你的原始图像中一样。如果你想让它即使碰到桨的边缘也能弹起来,你可以为 UICollisionBehavior
指定 collisionDelegate
并给它一个新的方向:
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
}
每当圆形视图与故事板上的桨碰撞时,它实际上与视图的矩形框架发生碰撞。我该如何解决这个问题。我也试过 UIBezierPath
、CAShapeLayer
,但似乎没有用。
红色箭头是碰撞点,因为它似乎不是与球碰撞而是与视图的框架碰撞。一次,框架被球拍碰到它弹回来等等。
如果您使用 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
,它将遵守您为项目定义的碰撞边界。例如:
上面说明了一个斜视,就像在你的原始图像中一样。如果你想让它即使碰到桨的边缘也能弹起来,你可以为 UICollisionBehavior
指定 collisionDelegate
并给它一个新的方向:
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
}