1

我在使用 Gravity 模块让数组的所有元素掉落时遇到问题。我设法让数组中的最后一个元素下降,然后在测试期间剩余的元素只停留在屏幕顶部。调试时

我正在使用 UIKit 并希望在使用其他各种引擎(如 SpriteKit 和 GameplayKit)之前彻底理解这种语言。

func mainGame()
    {
    let cars = ["car5", "car1", "car6", "car3", "car2", "car4"]
    var random2 = Int(arc4random_uniform(UInt32(cars.count))) + 1
    for i in 1...random2
        {
        let image = UIImage(named: cars[i - 1])
        let carView = UIImageView(image: image!)
        carView.frame = CGRect(x:i * 52, y:0 , width: 40, height: 50)
        view.addSubview(carView)
        dynamicAnimator = UIDynamicAnimator(referenceView: self.view)
        gravityBehavior = UIDynamicItemBehavior(items: [carView]) //cars falling
        dynamicAnimator.addBehavior(gravityBehavior)
        collisionBehavior = UICollisionBehavior(items: [carView, mainCar]) //collide
        collisionBehavior.translatesReferenceBoundsIntoBoundary = false
        gravityBehavior.addLinearVelocity(CGPoint(x: 0, y: 200), for: carView)
        dynamicAnimator.addBehavior(collisionBehavior)

        }
    collisionBehavior.addBoundary(withIdentifier: "Barrier" as NSCopying, for: UIBezierPath(rect: mainCar.frame))
    collisionBehavior.removeAllBoundaries()
    }

游戏到目前为止,阵列中的最后一辆车倒下,我控制的主要玩家汽车有碰撞行为,这对我来说是一大步!

4

2 回答 2

1

您正在为UIDynamicAnimator循环的每次迭代创建一个新的并将其分配给dynamicAnimator. 这就是为什么只有最后一个元素起作用的原因,因为它是分配给该变量的最后一个元素。

要修复它,只需将此行移动到只能调用一次的地方。

dynamicAnimator = UIDynamicAnimator(referenceView: self.view)

viewDidLoad是一个应该工作的可能地方。

于 2018-02-27T20:34:37.707 回答
0

UIKitDynamics 落后于大多数类似的框架。您不会为对象设置动画。您有一个动画师并将对象附加到它。正如 Clever Error 所指出的,在这种情况下您只需要一名动画师。

关键是您不要将重力附加到汽车上。您将汽车附加到行为(重力),然后将行为附加到动画师。是的,这很奇怪而且倒退。

我还没有测试过这个,但正确的代码会更接近这个:

func mainGame()
    {
    let cars = ["car5", "car1", "car6", "car3", "car2", "car4"]
    var random2 = Int(arc4random_uniform(UInt32(cars.count))) + 1

    var carViews: [UIImageView] = []
    dynamicAnimator = UIDynamicAnimator(referenceView: self.view)

    // First create all the views
    for i in 1...random2
        {
        let image = UIImage(named: cars[i - 1])
        let carView = UIImageView(image: image!)
        carView.frame = CGRect(x:i * 52, y:0 , width: 40, height: 50)
        view.addSubview(carView)
        carViews.append(carView)
        }

    // and then attach those to behaviors:

    gravityBehavior = UIGravityBehavior(items: carViews) //cars falling
    dynamicAnimator.addBehavior(gravityBehavior)

    collisionBehavior = UICollisionBehavior(items: carView + mainCar) //collide
    collisionBehavior.translatesReferenceBoundsIntoBoundary = false
    dynamicAnimator.addBehavior(collisionBehavior)

    collisionBehavior.addBoundary(withIdentifier: "Barrier" as NSCopying, for: UIBezierPath(rect: mainCar.frame))
    collisionBehavior.removeAllBoundaries()

    // You don't need this; it's built into Gravity
    // gravityBehavior.addLinearVelocity(CGPoint(x: 0, y: 200), for: carView)
    }

UIKitDynamics 与大多数动画框架不同的主要方式是动画的东西不知道它们正在被动画。你不能问一辆车它有什么行为,因为它没有。UIDynamicAnimator 基本上是一个定时循环,用于更新其目标的centertransform。它真的没有什么花哨的东西(与Core Animation之类的东西相比,它有很多花哨的东西)。有了一点 iOS 经验,您可能可以使用单个 GCD 队列手动实现所有 UIKitDynamics(它可能甚至不需要那个,因为它在 main 上运行所有东西......)

于 2018-02-27T22:01:41.980 回答