检测与蒙版图像相交(非矩形)

时间:2019-04-02 17:13:11

标签: swift xcode

在UIImageView框架中的蒙版图像周围移动时,如何不通过<​​strong>与func相交进行检测?

explanation image

我用来检测碰撞的代码:

movingPerson.frame.intersects(camera.frame)

movingPerson只是一个常规的UIImage,我通过touchesmoved的func来移动,而camera是一个蒙版的Image。 我尝试使用.bounds而不是.frame,但是它不起作用。

有什么简单的方法吗?

1 个答案:

答案 0 :(得分:0)

如果您想使用“非常简单的方法”,请UIDynamicItem并提供一个限制图像的路径,并让UIDynamicAnimator为您处理碰撞。如果您不知道如何获取艺术品的路径(您的工作非常简单,您应该能够在Paintcode中,在Illustrator中手动或从SVG文件中自动提取Bezier坐标),则可以使用SpriteKit,因为它实际上会自动为您的精灵生成边界多边形。

编辑示例(请注意,我不想为此编写一个完整的应用程序,所以我在一个现有的操场上添加了对撞机。碰撞有效,但碰撞后的重置无效):

import UIKit
import PlaygroundSupport

class ObstacleView: UIView {
    override var collisionBoundsType: UIDynamicItemCollisionBoundsType {
        return .path
    }

    override var collisionBoundingPath: UIBezierPath {
        return UIBezierPath(ovalIn: bounds)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = bounds.size.width / 2
    }
}

class ViewController: UIViewController {
    var dynamicAnimator: UIDynamicAnimator!
    var gravityBehavior: UIGravityBehavior!
    var pushBehavior: UIPushBehavior!
    var collisionBehavior: UICollisionBehavior!
    lazy var player: UILabel = {
        let label = UILabel()
        label.text = ""
        label.sizeToFit()
        label.isUserInteractionEnabled = true
        label.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(label)
        return label
    }()
    var isPanning = false
    var anchor: CGPoint = .zero
    let maxDistance = CGFloat(100)
    lazy var obstacles: [UIView] = {
        return (0..<2).map { index in
            let view = ObstacleView(frame: CGRect(x:100 + CGFloat(index)*200,y:200, width: 40, height: 40))
            view.backgroundColor = .blue
            view.translatesAutoresizingMaskIntoConstraints = false
            self.view.addSubview(view)
            return view
        }
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        dynamicAnimator = UIDynamicAnimator(referenceView: view)
        dynamicAnimator.delegate = self
        gravityBehavior = UIGravityBehavior(items: [player])
        let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(pan))
        _ = obstacles
        view.addGestureRecognizer(panGestureRecognizer)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        anchor = view.center
        player.center = anchor
    }

    @objc private func pan(recognizer: UIPanGestureRecognizer) {
        switch recognizer.state {
        case .began:
            guard player.bounds.contains(recognizer.location(in: player)) else {
                isPanning = false
                return
            }
            isPanning = true
        case .changed:
            guard isPanning else {
                return
            }
            player.center = recognizer.location(in: view)
            let dx = player.center.x - anchor.x
            let dy = player.center.y - anchor.y
            let distance = CGFloat(hypotf(Float(dx), Float(dy)))
            if distance > maxDistance {
                player.center.x = anchor.x + dx / distance * maxDistance
                player.center.y = anchor.y + dy / distance * maxDistance
            }
        case .ended:
            guard isPanning else {
                return
            }
            isPanning = false
            let dx = player.center.x - anchor.x
            let dy = player.center.y - anchor.y
            let distance = CGFloat(hypotf(Float(dx), Float(dy)))
            guard distance > 10 else {
                player.center = anchor
                return
            }
            if pushBehavior != nil {
                dynamicAnimator.removeBehavior(pushBehavior)
            }
            pushBehavior = UIPushBehavior(items: [player], mode: .instantaneous)
            pushBehavior.pushDirection = CGVector(dx: -dx, dy: -dy)
            pushBehavior.magnitude = distance / maxDistance * 0.75
            dynamicAnimator.addBehavior(pushBehavior)
            dynamicAnimator.addBehavior(gravityBehavior)
            collisionBehavior = UICollisionBehavior(items: [player] + obstacles)
            collisionBehavior.translatesReferenceBoundsIntoBoundary = true
            collisionBehavior.collisionDelegate = self
            dynamicAnimator.addBehavior(collisionBehavior)
        case .cancelled:
            isPanning = false
            player.center = anchor
        default:
            break
        }
    }
}

extension ViewController: UIDynamicAnimatorDelegate {
    func dynamicAnimatorDidPause(_ animator: UIDynamicAnimator) {
        dynamicAnimator.removeAllBehaviors()
        player.center = anchor
    }
}

extension ViewController: UICollisionBehaviorDelegate {
    func collisionBehavior(_ behavior: UICollisionBehavior, beganContactFor item1: UIDynamicItem, with item2: UIDynamicItem, at p: CGPoint) {
        print("contact")
    }
}

PlaygroundPage.current.liveView = ViewController()
PlaygroundPage.current.needsIndefiniteExecution = true