2016-03-20 44 views
2

Immer wenn die kreisförmige Ansicht mit dem Paddel auf Storyboard kollidiert, kollidiert es tatsächlich mit dem rechteckigen Rahmen der Ansicht. Wie behebe ich dieses Problem? Ich habe auch versucht UIBezierPath, CAShapeLayer und es scheint nicht zu funktionieren.Wie mache ich eine kreisförmige Ansicht kollidieren mit dem Paddel

Der rote Pfeil ist der kollidierende Punkt, da er nicht mit der Kugel kollidiert, sondern mit dem Rahmen der Ansicht kollidiert. einmal wird der Rahmen mit dem Paddel berührt, das springt zurück und so weiter.

screen snapshot

+2

Wie werden Sie die Kollisionserfassungs? Bearbeiten Sie Ihre Frage, um den Code einzuschließen. –

+0

Ich habe nicht Kollision verwendet, schrieb eine Funktion, die die Y-Achse des Paddel und die Y-Achse der Ansicht überprüft, sobald sie gleich sind, springt der Ball zurück Ich habe NS-Timer verwendet, um den Rahmen um 20px der Ansicht zu aktualisieren 0 - 20 - 40 - 60 usw. –

+0

Sie sollten sich UI Dynamics und/oder SpriteKit ansehen. – dasdom

Antwort

4

Wenn Sie UIDynamicAnimator verwenden, können Sie die collisionBoundsType und die collisionBoundingPath für die Elemente definieren, die zum Beispiel wird kollidieren:

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

Wenn Sie dies tun, und fügen Sie dann Diese Artikel an Ihre UICollisionBehavior, wird es die Kollisionsgrenzen, die Sie für die Elemente definiert respektieren. Zum Beispiel:

collision animation


Die oben zeigt einen Blick Schlag, wie im Originalbild. Wenn Sie es wünschen, auch auf die Beine, wenn er den Rand des Paddels trifft, können Sie die collisionDelegate für die UICollisionBehavior angeben und eine neue Richtung geben:

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

und entsprechen UICollisionBehaviorDelegate und dann implementieren 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) 
} 

, dass so etwas ergibt:

enter image description here

Natürlich müssen Sie damit ziemlich herumspielen, um den gewünschten Effekt zu erzielen, aber es veranschaulicht die Grundidee, eine Kollision zu erkennen und dem Ball entsprechend eine lineare Geschwindigkeit hinzuzufügen.

+0

Danke Rob, für das Paddel habe ich UIPanGesture angewandt, um sich einmal horizontal zu bewegen, es berührt den Ball, es springt zurück, das Paddel bewegt sich überhaupt nicht, scheint nicht mit Kollision zu arbeiten. Warum das? –

+0

Sieh dir dein Originalbild an: Wenn ein richtiger Ball auf ein Paddel wie deines trifft, würde es zur Seite und nach unten schauen, nicht wieder aufspringen. – Rob

+0

Das ist perfekt, wie Sie den Ball kollidiert gezeigt haben, mit der Kante des Paddle, Aber es muss wieder nach oben zurückschlagen und den Bildschirm treffen. ist das mit Collisions & Gravity möglich? –

0

Eine noch einfachere Antwort als die akzeptierte Antwort wäre, die Grenzen zu setzen, anstatt einen definierten Weg elliptisch zu sein:

override public var collisionBoundsType: UIDynamicItemCollisionBoundsType { 
     return .Elliptical 
}