如何在标签和图像之间创建碰撞检测

How to create a Collision Detection between a label and an Image

前言

我想创建一个简单的游戏,您应该可以在其中拖动标签,如果将其拖动到正确的位置,您就赢了。更具体地说:这是一款帮助自闭症儿童的游戏。在这个游戏中,他们必须创建从 1 到 10 的正确数字序列,将带有数字的标签拖到正确的位置(实际上是图像)。现在你会更好地理解:

问题

我已经创建了拖动标签的代码(使用平移手势识别器),但我不知道如何创建碰撞检测:当卡片“1”被拖动并与蓝色图像发生碰撞时“1”有事发生, 我的心理代码是:

if LB_1 *collides with* IMG_1 {
  self.IMG_1?.backgroundColor = UIColor.green
}

我希望问题很清楚。 啊我不使用 SpriteKit。我使用 "SingleViewApplication" 作为模板而不是 "Game"。

您可以检查它们的框架是否相交。 CGRect 有方法 intersects.

所以你的 if 语句应该如下:

if LB_1.frame.intersects(IMG_1.frame) {
  self.IMG_1?.backgroundColor = UIColor.green
}

如果这对你来说还不够,你可以计算intersection rect的面积。

您想使用 contains()。如果你使用 intersects() 那么一旦两个矩形接触它就会 return 为真。使用 contains(),直到拖动的视图完全在目标视图内,它才会 return 为真,这似乎更直观。

我刚刚编写了一个实现此功能的示例应用程序,并且运行良好。

我创建了一个简单的 UIView 子class,我称之为 BoxedView,它只是在它的图层周围设置了一个边框,以便您可以看到它。

我设置了一个视图控制器,其中包含 2 个盒装视图、一个较大的 "targetView" 和一个用户可以拖动的较小视图。

我的手势识别器的 target/action 在用户拖动时移动拖动视图的框架,如果目标视图包含拖动视图,它会设置一个 Bool highlightTargetView,这会导致目标视图周围的框得到更厚。

整个视图控制器 class' 代码如下所示:

class ViewController: UIViewController {

    @IBOutlet weak var targetView: BoxedView!

    var viewStartingFrame: CGRect = CGRect.zero

    var highlightTargetView: Bool = false {
        didSet {
            targetView.layer.borderWidth = highlightTargetView ? 5 : 1
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    @IBAction func userDraggedView(_ gesture: UIPanGestureRecognizer) {
        switch gesture.state {
        case .began:
            viewStartingFrame = gesture.view?.frame ?? CGRect.zero
        case .changed:
            let offset = gesture.translation(in: view)
            gesture.view?.frame = viewStartingFrame.offsetBy(dx: offset.x, dy: offset.y)
            highlightTargetView = targetView.frame.contains(gesture.view?.frame ?? CGRect.zero)
        case .ended:
            gesture.view?.frame = viewStartingFrame
            highlightTargetView = false
        default:
            break
        }
    }
}

为了数学运算,我使用了两个视图的框架 属性,它位于父视图的坐标系中(在这种情况下,父视图是视图控制器的内容视图,但关键是我们比较两个使用相同坐标系的矩形。)如果你使用任一视图的边界 属性 你的数学将不起作用,因为视图的 bounds 在该视图的局部坐标系。

下面是程序在 运行:

时的样子

为了比较,我修改了程序以使用 intersects() 函数也显示它的样子,并创建了一个视频来展示它的样子: