Доступ к количеству элементов в массиве и применение гравитационного поведения

У меня проблемы с падением ВСЕХ элементов массива с помощью модуля Gravity. Мне удалось заставить элемент LAST в массиве упасть, а затем оставшиеся элементы просто остаются в верхней части экрана во время тестирования. После отладки

Я использую 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()
    }

В этой игре последний автомобиль в массиве падает, и автомобиль основного игрока, которым я управляю, имеет поведение при столкновении, что является для меня большим шагом!

2 ответа

Вы создаете новый UIDynamicAnimator с каждой итерацией цикла и назначая его dynamicAnimator, Вот почему работает только последний элемент, потому что он является последним, назначенным этой переменной.

Чтобы исправить это, просто переместите эту строку в то место, которое будет вызываться только один раз.

dynamicAnimator = UIDynamicAnimator(referenceView: self.view)

viewDidLoad это возможное место, которое должно работать.

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 в основном представляет собой цикл синхронизации, который обновляет center а также transform его целей. В этом нет ничего особенного (в отличие от чего-то вроде Core Animation, в котором происходит много причудливых вещей). Имея небольшой опыт работы с iOS, вы, вероятно, могли бы реализовать всю UIKitDynamics вручную с единственной GCD-очередью (она, вероятно, даже не нуждается в этом, так как она запускает все на main....)

Другие вопросы по тегам